请教通过module hijack syscall_table的方法修改系统调用函数的地址

never0508 2009-04-17 02:30:27
想测试一下自己写的系统调用函数,如果每次都重编译一次内核太麻烦了,到网上找了一下,发现可以通过查找,找到了如下资料
http://technica.blogbus.com/logs/18945123.html
http://www.linuxeden.com/html/develop/20071031/36891.html
http://hi.baidu.com/tigerwooz/blog/item/cfe3e6a285990ea5cbefd0ae.html
,其中一个源码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>

MODULE_LICENSE("Dual BSD/GPL");

#define __NR_newhandler 333

struct {
unsigned short limit;
unsigned int base;
} __attribute__((packed)) idtr;

struct {
unsigned short off1;
unsigned short sel;
unsigned char none, flags;
unsigned short off2;
} __attribute__((packed)) idt;

unsigned int** syscall_table;
unsigned int old_handler;

asmlinkage int sys_newhandler(void) {

printk(KERN_ALERT "Inside new_handler().\n");
return 0;
}

unsigned int get_sys_call_table(void)
{
unsigned int sys_call_off;
unsigned int sys_call_table;
char* p;
int i;
// 获取中断描述符表寄存器的地址
asm("sidt %0":"=m"(idtr));
printk("addr of idtr: %x\n", (int)&idtr);
// 获取0x80中断处理程序的地址
memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
sys_call_off=((idt.off2<<16)|idt.off1);
printk("addr of idt 0x80: %x\n", sys_call_off);
// 从0x80中断服务例程中搜索sys_call_table的地址
p=sys_call_off;
for (i=0; i<100; i++)
{
if (p[i]=='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85')
{
sys_call_table=*(unsigned int*)(p+i+3);
printk("addr of sys_call_table: %x\n", sys_call_table);
return sys_call_table;
}
}
return 0;
}

static int mymod_init(void) {
syscall_table = (unsigned int*)get_sys_call_table();
old_handler = syscall_table[__NR_newhandler];

//篡改内存中的syscall_table中ofset为__NR_newhandler处的内容,也就是编号

//为 __NR_newhandler的syscall的处理程序的入口
syscall_table[__NR_newhandler] = (unsigned long)sys_newhandler;
return 0;
}
static int mymod_exit(void){
printk("over\n");
return 0;
}
module_init(mymod_init);
module_exit(mymod_exit);

我按这个方法试了,但总是在insmod 的时候报Segment Error,在执行倒数第八行
//为 __NR_newhandler的syscall的处理程序的入口
syscall_table[__NR_newhandler] = (unsigned long)sys_newhandler;

这条语句之前出错。想问一下哪位之前研究过这个,并且成功修改了调用表某个函数的地址的,望赐教。

这个问题我研究了好几天,仍不解,对 了,我的内核版本是2.6.29的,网上说上面这个方法是2.6.20左右的,但这个我看不出会是版本问题。

希望有见解的都帮帮忙,不胜感激!
...全文
296 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
deep_pro 2009-12-17
  • 打赏
  • 举报
回复
lz留个邮箱
我以前也玩过一段时间的hack
在黑防上发过这方面的文章,早忘了是不是 module hijack
反正跟你的一样低级,需要lkm实现
把文章和代码给你
Iismama 2009-12-17
  • 打赏
  • 举报
回复
不要想了,6.1x后,禁止module写syscall_table!!!!!,那句话就是写syscall_table.自己好好想一想!
never0508 2009-04-19
  • 打赏
  • 举报
回复
可能吧,但我现在急需实现这个功能,如果你有什么办法,望赐教。
独孤过儿 2009-04-18
  • 打赏
  • 举报
回复
建议楼主随便翻翻LDD和有关AT&T汇编再加上点Linux内核原理的东西,就觉得这个trip没什么意思了
独孤过儿 2009-04-18
  • 打赏
  • 举报
回复
说实话,这个真的不怎么样,没什么技术含量...
never0508 2009-04-18
  • 打赏
  • 举报
回复
那个资料先前我也找到过,不过他那个没说明是哪个版本的,好像是之前的,现在好像不行了,我在2.6.29上是没调通,而且他的代码错误百出啊,include都打错了。估计他自己都没跑一便。
never0508 2009-04-18
  • 打赏
  • 举报
回复
对,就是用在调试啊,现在是不知道为什么老是加载时出现segment error错误,实在是弄不明白哪错了,dmesg里提示说unable to handle kernel paging request at c0391a44,
会是类型转换时出的问题吗,不知道哪位指针比较清楚,看看。
  • 打赏
  • 举报
回复
学习来的~~帮顶
morris88 2009-04-17
  • 打赏
  • 举报
回复
这个技术貌似可用于可加载模块的调试。
但是,一般来说,更主要的用途就是病毒、木马...
  • 打赏
  • 举报
回复
http://blog.chinaunix.net/u2/79914/showart_1826204.html
参考下这个
never0508 2009-04-17
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 morris88 的回复:]
extern unsigned long sys_call_table[NR_syscalls];
[/Quote]
你这里直接引用sys_call_table前提是内核有export系统调用表才行,好像从某个版本之后,为了安全考虑,就不export系统调用表了,所以才通过在代码中查找 call 0x*****(sys_call_table)的命令来间接获取系统调用表的地址。

你这个方法在哪个版本上成功了?能不能给出完整代码,谢谢!
morris88 2009-04-17
  • 打赏
  • 举报
回复
	/*
* For fsyscall entrpoints with no light-weight handler, use the ordinary
* (heavy-weight) handler, but mark it by setting bit 0, so the fsyscall entry
* code can tell them apart.
*/
for (i = 0; i < NR_syscalls; ++i) {
extern unsigned long fsyscall_table[NR_syscalls];
extern unsigned long sys_call_table[NR_syscalls];

if (!fsyscall_table[i] || nolwsys)
fsyscall_table[i] = sys_call_table[i] | 1;
}
morris88 2009-04-17
  • 打赏
  • 举报
回复
貌似 2.6.29 是 sys_call_table,而不是 syscall_table...

4,441

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧