LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 03-03-2007, 08:50 AM   #1
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Rep: Reputation: 15
syscall hook


Hello,

How can i hook a syscall in 2.6?More exactly how can i calculate the sys_call_table adress from a kernel module?(not from System.map)

Thanks.
(sorry cause i've posted this in the wrong place!)
 
Old 03-04-2007, 01:20 AM   #2
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
// The following code is from StJude v0.22
// Timothy Lalwess (lawless@wwjh.net)
// Since 2.4.18 ,sys_call_table is not exported.
static void **sys_call_table=NULL;
extern asmlinkage long sys_exit(int error_code);
static int hack_sys_call()
{
unsigned long ptr;
extern int loops_per_jiffy;
for(ptr=(unsigned long )&loops_per_jiffy;ptr<(unsigned long )&boot_cpu_data;ptr+=sizeof(void*)){
unsigned long *p=(unsigned long *)ptr;
if(p[1]==(unsigned long)sys_exit){
sys_call_table=(void**)p;
break;
}
}
if(!sys_call_table){
printk(KERN_WARNING "Can not find the sys_call_table.Aborting load. Feel safe to rmmod.\n");
return 1;
}
return 0;
}
 
Old 03-04-2007, 04:56 AM   #3
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
a new solution

It maybe work well.
struct _idt {
unsigned short offset_low, segment_sel;
unsigned char reserved, flags;
unsigned short offset_high;
} __attribute__ ((packed));

unsigned long *get_system_call_table(void)
{
unsigned char idtr[6], *shell, *sort;
struct _idt *idt;
unsigned long system_call;
unsigned short offset_low, offset_high;
int i;
char *p;

__asm__ __volatile__("sidt %0":"=m"(idtr)::"memory");

idt = (struct _idt *)(*(unsigned long *)&idtr[2] + 8 * 0x80);
offset_low = idt->offset_low;
offset_high = idt->offset_high;
system_call = (offset_high << 16) | offset_low;
/*
* We often place the function 'system_call' address in IDT.
* while machine code \xff\x14\85 stands for anything like
* call offset<,eax,4> offen steps. It is really what we want.
*/
shell = (char *)system_call;
sort = "\xff\x14\x85";
for (i = 0; i < (100 - 2); i++) {
if (shell[i] == sort[0] && shell[i + 1] == sort[1] &&
shell[i + 2] == sort[2])
break;
}
p = (char *)&shell[i + 3];
return (unsigned long *)*(unsigned long *)p;
}

static int my_module_init(void)
{
printk("0x%08lx\n", (long)get_system_call_table());
return 0;
}
static void my_module_exit(void)
{
return;
}
 
Old 03-04-2007, 06:21 AM   #4
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
I have tried it and i get the following error:

Mar 4 14:22:08 adi kernel: find_sys: Unknown symbol sys_exit

allthough sys_exit is declared with extern asmlinkage etc....probably it should be declared different?

This is for the first method. Now i'll try the second one.

Last edited by robertos; 03-04-2007 at 07:27 AM.
 
Old 03-04-2007, 09:04 AM   #5
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
i have used sys_close instead of sys_exit and now it doesn't show me that undefined error.
However when i try to hook unlink it doesn't work.

the second method with the idt shows me the same result as in the system.map. How ever when i try to hook sys_unlink it Ooops
 
Old 03-07-2007, 12:53 AM   #6
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
1. the first snippet is of no use now ,because the sys_call_table is moved to .rodata,so it would not be among the area between loops_per_jiffy and boot_cpu_data.
2. the second slice should be ok right now, but may be out-of-date in future .There are 2 methods to execute system calls currently,one by 'int 0x80' and 'iret' but which has poor performance in P4,and the other by 'sysenter' and 'sysexit',so if we don't use IDT 0x80 ,we can not use the second method to get sys_call_table.

>>i have used sys_close instead of sys_exit and now it doesn't show me that undefined error.
>>However when i try to hook unlink it doesn't work.
1.sys_call_table[1]==sys_exit; or you can use sys_call_table[SYS_clone]=sys_clone.
2. even if works , an Oops will be following soon..

>>the second method with the idt shows me the same result as in the system.map. How ever when i >>try to hook sys_unlink it Ooops
sys_call_table is in .rodata ,so you can not direct change it ,otherwise a do_page_fault will happen.

The only way is to reset the page attribute and make sure you have the right to write the sys_call_table.
Slice are as follows:


pgprot_t prot;
struct page * which_page_sys_call_table_in;

which_page_sys_call_table_in = virt_to_page(sys_call_table);
prot.pgprot = VM_READ | VM_WRITE | VM_EXEC;
change_page_attr(which_page_sys_call_table, 1, prot);
then when writing the sys_call_table vectors, you will not trigger the do_page_fault exception.
 
Old 03-07-2007, 03:24 AM   #7
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
attached with my slice ,you can reuse it.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/mm.h>
#include <linux/syscalls.h>
#include <sys/syscall.h>
#include <asm/cacheflush.h>

unsigned long **sys_call_table = NULL;

typedef asmlinkage long (*my_unlink_type) (const char __user *);
static my_unlink_type sys_unlink_orig = NULL;

asmlinkage static long my_sys_unlink(const char __user * filename)
{
return sys_unlink_orig(filename);
}

struct _idt {
unsigned short offset_low, segment_sel;
unsigned char reserved, flags;
unsigned short offset_high;
} __attribute__ ((packed));

static void get_system_call_table(void)
{
unsigned char idtr[6], *shell, *sort;
struct _idt *idt;
struct page *sys_call_table_page;
pgprot_t prot;
unsigned long system_call;
unsigned short offset_low, offset_high;
int i;
char *p;

__asm__ __volatile__("sidt %0":"=m"(idtr)::"memory");

idt = (struct _idt *)(*(unsigned long *)&idtr[2] + 8 * 0x80);
offset_low = idt->offset_low;
offset_high = idt->offset_high;
system_call = (offset_high << 16) | offset_low;
/*
* We often place the function 'system_call' address in IDT.
* while machine code \xff\x14\85 stands for anything like
* call offset<,eax,4> offen steps. It is really what we want.
*/
shell = (char *)system_call;
sort = "\xff\x14\x85";
for (i = 0; i < (100 - 2); i++) {
if (shell[i] == sort[0] && shell[i + 1] == sort[1] &&
shell[i + 2] == sort[2])
break;
}
p = (char *)&shell[i + 3];
sys_call_table = (unsigned long **)*(unsigned long *)p;
sys_call_table_page = virt_to_page(sys_call_table);
prot.pgprot = VM_READ | VM_WRITE | VM_EXEC;
change_page_attr(sys_call_table_page, 1, prot);
}

static int my_module_init(void)
{
get_system_call_table();
sys_unlink_orig = (my_unlink_type) sys_call_table[SYS_unlink];
sys_call_table[SYS_unlink] = (unsigned long *)my_sys_unlink;
return 0;
}

static void my_module_exit(void)
{
sys_call_table[SYS_unlink] = (unsigned long *)sys_unlink_orig;
return;
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Ying Chu,xjtuychu@gmail.com");
MODULE_DESCRIPTION("System Calls hack in kernel 2.6 use IDT vector 128.");
 
Old 03-07-2007, 10:20 AM   #8
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
but

thanks,i've just wanted to post my code,but i see you already posted yours
However it's not working.i've also tested your code,posted(the whole) module and it Ooops
I don't understand why....i'm curios abput that segfault....

insmod find_sys3.ko
Segmentation fault
[root@adi netfilter]#
Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: Oops: 0003 [#1]

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: SMP

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: CPU: 1

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: EIP: 0060:[<e0c120aa>] Tainted: G M VLI

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: EFLAGS: 00210246 (2.6.19-1.2911.6.5.fc6 #1)

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: EIP is at my_module_init+0x93/0xa1 [find_sys3]

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: eax: 00000000 ebx: e0c12514 ecx: dfdf18a8 edx: c062a528

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: esi: e0c12580 edi: d5680f98 ebp: 0000001e esp: d8650ebc

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: ds: 007b es: 007b ss: 0068

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: Process insmod (pid: 3417, ti=d8650000 task=de5be890 task.ti=d8650000)

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: Stack: 8500001e ff433f7b 07ff2580 c0736000 e0c12580 c0443096 e0c125c8 c063f14c

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: e0c1258c 00000000 00013e87 00000488 00000000 e0c12580 00000000 00000000

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: 00000000 00000000 00000000 00000006 00000000 00000000 00000000 00000000

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: Call Trace:

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: [<c0443096>] sys_init_module+0x17ff/0x19aa

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: [<c040404b>] syscall_call+0x7/0xb

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: [<0089e402>] 0x89e402

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: =======================

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: Code: 37 c1 e0 05 00 00 00 40 c1 e8 0c c1 e0 05 03 05 80 66 86 c0 e8 23 d1 80 df 8b 15 80 37 c1 e0 83 c2 28 8b 02 a3 84 37 c1 e0 31 c0 <c7> 02 00 20 c1 e0 83 c4 10 5b c3 90 90 90 ff 14 85 00 00 00 00

Message from syslogd@adi at Wed Mar 7 17:17:19 2007 ...
adi kernel: EIP: [<e0c120aa>] my_module_init+0x93/0xa1 [find_sys3] SS:ESP 0068:d8650ebc
 
Old 03-07-2007, 10:22 AM   #9
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
oh, the only thing i've modified in your source are the include files they now are:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/mm.h>
#include <linux/syscalls.h>
#include <asm/cacheflush.h>
#include <asm/unistd.h>

because it couldn't find SYS_unlink...and now it's __NR_unlink in the source.but i guess that shouldn't count,right?
 
Old 03-08-2007, 02:41 AM   #10
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
what about your Makefile.

You forgot to use the EXTRA_CFLAGS in your Makefile.
obj-m += xxx.o
EXTRA_CFLAGS += -I /usr/include

Last edited by raynor; 03-08-2007 at 02:55 AM.
 
Old 03-08-2007, 02:54 AM   #11
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
Post your code ,let me make a try.

besides ,tell me you kernel version.
 
Old 03-08-2007, 01:47 PM   #12
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
i have kernel 2.6.19-1.2911.6.5.fc6 and Fedore Core 6 as you can see....
 
Old 03-08-2007, 09:44 PM   #13
raynor
LQ Newbie
 
Registered: Jan 2007
Posts: 10

Rep: Reputation: 0
ok,post your code ,let me review it .
 
Old 03-09-2007, 01:41 AM   #14
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
I think is something with my kernel,or with this Fedora ...somebody talled me,i quote "FC is the end of life!"
It's exactly your code:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/mm.h>
#include <linux/syscalls.h>
#include <sys/syscall.h>
#include <asm/cacheflush.h>

unsigned long **sys_call_table = NULL;

typedef asmlinkage long (*my_unlink_type) (const char __user *);
static my_unlink_type sys_unlink_orig = NULL;

asmlinkage static long my_sys_unlink(const char __user * filename)
{
return sys_unlink_orig(filename);
}

struct _idt {
unsigned short offset_low, segment_sel;
unsigned char reserved, flags;
unsigned short offset_high;
} __attribute__ ((packed));

static void get_system_call_table(void)
{
unsigned char idtr[6], *shell, *sort;
struct _idt *idt;
struct page *sys_call_table_page;
pgprot_t prot;
unsigned long system_call;
unsigned short offset_low, offset_high;
int i;
char *p;

__asm__ __volatile__("sidt %0":"=m"(idtr)::"memory");

idt = (struct _idt *)(*(unsigned long *)&idtr[2] + 8 * 0x80);
offset_low = idt->offset_low;
offset_high = idt->offset_high;
system_call = (offset_high << 16) | offset_low;
/*
* We often place the function 'system_call' address in IDT.
* while machine code \xff\x14\85 stands for anything like
* call offset<,eax,4> offen steps. It is really what we want.
*/
shell = (char *)system_call;
sort = "\xff\x14\x85";
for (i = 0; i < (100 - 2); i++) {
if (shell[i] == sort[0] && shell[i + 1] == sort[1] &&
shell[i + 2] == sort[2])
break;
}
p = (char *)&shell[i + 3];
sys_call_table = (unsigned long **)*(unsigned long *)p;
sys_call_table_page = virt_to_page(sys_call_table);
prot.pgprot = VM_READ | VM_WRITE | VM_EXEC;
change_page_attr(sys_call_table_page, 1, prot);
}

static int my_module_init(void)
{
get_system_call_table();
sys_unlink_orig = (my_unlink_type) sys_call_table[SYS_unlink];
sys_call_table[SYS_unlink] = (unsigned long *)my_sys_unlink;
return 0;
}

static void my_module_exit(void)
{
sys_call_table[SYS_unlink] = (unsigned long *)sys_unlink_orig;
return;
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Ying Chu,xjtuychu@gmail.com");
MODULE_DESCRIPTION("System Calls hack in kernel 2.6 use IDT vector 128.");
 
Old 03-09-2007, 02:23 AM   #15
robertos
LQ Newbie
 
Registered: Feb 2007
Posts: 27

Original Poster
Rep: Reputation: 15
raynor,thanks for trying to help. Someway i can contact you in private? I don't see any PM's around here....
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
syscall hook robertos Programming 4 03-06-2007 12:48 AM
Making syscall chdir permanent when app ends mcamember Programming 4 12-22-2006 08:03 PM
assembly execve (syscall 11) rblampain Programming 2 07-03-2005 10:23 AM
what is difference between syscall of linux and Unix sdamo Linux - General 1 06-12-2005 02:07 AM
Linux syscall 11 (execve) Genjix Programming 1 12-30-2004 12:38 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 12:23 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration