LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   syscall hook (https://www.linuxquestions.org/questions/linux-kernel-70/syscall-hook-534169/)

robertos 03-03-2007 07:50 AM

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!)

raynor 03-04-2007 12:20 AM

// 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;
}

raynor 03-04-2007 03:56 AM

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;
}

robertos 03-04-2007 05:21 AM

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.

robertos 03-04-2007 08:04 AM

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:(

raynor 03-06-2007 11:53 PM

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.

raynor 03-07-2007 02:24 AM

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.");

robertos 03-07-2007 09:20 AM

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

robertos 03-07-2007 09:22 AM

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?

raynor 03-08-2007 01:41 AM

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

raynor 03-08-2007 01:54 AM

Post your code ,let me make a try.
 
besides ,tell me you kernel version.

robertos 03-08-2007 12:47 PM

i have kernel 2.6.19-1.2911.6.5.fc6 and Fedore Core 6 as you can see....

raynor 03-08-2007 08:44 PM

ok,post your code ,let me review it .

robertos 03-09-2007 12:41 AM

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.");

robertos 03-09-2007 01:23 AM

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


All times are GMT -5. The time now is 03:54 AM.