我正在SYS_READ
从 Linux (3.x) 中的系统调用表中覆盖,但是在卸载模块本身时遇到了一些麻烦。我首先加载找到系统调用表的模块,然后启用,用我自己的函数RW
覆盖(实际上除了调用原始函数之外什么都不做),然后等待片刻,然后卸载模块。在我的模块的卸载方法中,我将原始函数恢复回系统调用表中,并将系统调用表设置回.SYS_READ
SYS_READ
SYS_READ
SYS_READ
RO
原始SYS_READ
功能已正确恢复,但我在卸载模块时得到了这个:http: //pastebin.com/JyYpqYgL
我错过了什么?恢复真实后我应该做更多的事情SYS_READ
吗?
编辑:项目的 GitHub 链接:https ://github.com/alexandernst/procmon
编辑:
这就是我获取系统调用表地址的方式:
void **sys_call_table;
struct idt_descriptor{
unsigned short offset_low;
unsigned short selector;
unsigned char zero;
unsigned char type_flags;
unsigned short offset_high;
} __attribute__ ((packed));
struct idtr{
unsigned short limit;
void *base;
} __attribute__ ((packed));
void *get_sys_call_table(void){
struct idtr idtr;
struct idt_descriptor idtd;
void *system_call;
unsigned char *ptr;
int i;
asm volatile("sidt %0" : "=m" (idtr));
memcpy(&idtd, idtr.base + 0x80 * sizeof(idtd), sizeof(idtd));
system_call = (void*)((idtd.offset_high<<16) | idtd.offset_low);
for(ptr=system_call, i=0; i<500; i++){
if(ptr[0] == 0xff && ptr[1] == 0x14 && ptr[2] == 0x85)
return *((void**)(ptr+3));
ptr++;
}
return NULL;
}
sys_call_table = get_sys_call_table();
这就是我设置 RW/RO 的方式:
unsigned long set_rw_cr0(void){
unsigned long cr0 = 0;
unsigned long ret;
asm volatile("movq %%cr0, %%rax" : "=a"(cr0));
ret = cr0;
cr0 &= 0xfffffffffffeffff;
asm volatile("movq %%rax, %%cr0" : : "a"(cr0));
return ret;
}
void set_ro_cr0(unsigned long val){
asm volatile("movq %%rax, %%cr0" : : "a"(val));
}
最后,这是我定义系统调用和更改系统调用表的方式:
asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count);
asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count);
//set my syscall
real_sys_read = (void *)sys_call_table[__NR_read];
sys_call_table[__NR_read] = (void *)hooked_sys_read;
//restore real syscall
sys_call_table[__NR_read] = (void *)real_sys_read;