[求助]获取system_call地址造成系统重启的问题(个人崩溃中)
本帖最后由 做酷 于 2014-05-28 22:55 编辑最近在学习hook系统调用,但是在获取system_call地址的时候,遇到一个自己无法理解的问题,还请各位帮忙看一看:
一、环境信息
#lsb_release -a
LSB Version: :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: RedHatEnterpriseServer
Description: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
Release: 5.2
Codename: Tikanga
# uname -a
Linux localhost.localdomain 2.6.18-92.el5xen #1 SMP Tue Apr 29 13:45:57 EDT 2008 i686 i686 i386 GNU/Linux
二、测试代码
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/dirent.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <linux/proc_fs.h>
struct idt_descriptor
{
unsigned short off_low;
unsigned short sel;
unsigned char none, flags;
unsigned short off_high;
};
void *get_system_call(void)
{
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc;
asm ("sidt %0" : "=m" (idtr));
base = *((unsigned long *) &idtr);
//中断描述符表的第0x80项是system_call函数的
memcpy(&desc, (void *) (base + (0x80* 8 )), sizeof(desc));
return (void *)base;
/***********************************************************************************
*insmod 模块后
*在此之上的代码执行是没有问题的,可以打印相应的值
*如果将上面的return语句去除,执行下面的语句,都会造成系统直接重启,即任何对desc成员的读取操作都会造成关机重启
*问题就是,struct idt_descriptor desc这个局部变量,为什么可写而不可读,这是什么原因造成的?该如何解决?好像类似的文章都没有提到这种现象
************************************************************************************/
//base=(unsigned long )desc.off_low;
//return (void *)base;
//printk(KERN_EMERG"hight %x\n", desc.off_high);
//printk(KERN_EMERG"low %x\n", desc.off_low);
//return ((void *) ((desc.off_high << 16) + desc.off_low));
}
static int __init init_hook(void)
{
void *system_call;
system_call = get_system_call();
printk(KERN_EMERG"Address of system_call: %x\n", (unsigned int)system_call);
return 0;
}
static void __exit exit_hook(void)
{
}
module_init(init_hook);
module_exit(exit_hook);
MODULE_LICENSE("GPL" ) ; void *get_system_call(void)
{
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc={0};
return desc.off_high;
}
将函数替换为上述内容,也是可以正常打印的
localhost kernel: Address of system_call: 0 base = *((unsigned long *) &idtr);
...
//base=(unsigned long )desc.off_low;
base指针两次赋值? 本帖最后由 做酷 于 2014-05-29 18:31 编辑
回复 3# humjb_1983
在代码说明里已经说清楚了,base赋值只是为了函数返回测试!
问题的实质是无法对struct idt_descriptor desc这个局部变量的成员进行读取,跟base赋几次值没有关系!
做酷 发表于 2014-05-29 17:50 static/image/common/back.gif
回复 3# humjb_1983
出问题是第一条没执行,还是第二条没执行?为何确认是读取时出错? 可能没有下面那段的时候,那个memcpy也被优化掉了?没有实际执行。要查看一下编译出来的汇编看看。
你要看看系统崩溃时的oops打印的错误地址是什么,对应代码的哪一行。
回复 5# humjb_1983
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc;
asm ("sidt %0" : "=m" (idtr));
base = *((unsigned long *) &idtr);
//中断描述符表的第0x80项是system_call函数的
memcpy(&desc, (void *) (base + (0x80*8)), sizeof(desc));
printk(KERN_EMERG"hight %x\n", desc.off_high);
printk(KERN_EMERG"low %x\n", desc.off_low);
这样也是重启的!
回复 6# hmsghnh
好的,我再看看! 对各位关注表示感谢!:))
再把几个测试代码贴出来说明一下:
1、
void *get_system_call(void)
{
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc={0};
return desc.off_high;
}
结果:localhost kernel: Address of system_call: 0
2、
void *get_system_call(void)
{
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc={0};
asm ("sidt %0" : "=m" (idtr));
base = *((unsigned long *) &idtr);
// 中断描述符表的第0x80项是system_call函数的
memcpy(&desc, (void *) (base + (0x80* 8 )), sizeof(desc));
return (void *)base;
}
结果:localhost kernel: Address of system_call: ff1fc860
3、
void *get_system_call(void)
{
unsigned char idtr;
unsigned long base;
struct idt_descriptor desc={0};
asm ("sidt %0" : "=m" (idtr));
base = *((unsigned long *) &idtr);
// 中断描述符表的第0x80项是system_call函数的
memcpy(&desc, (void *) (base + (0x80* 8 )), sizeof(desc));
return (void *)desc.off_low;
}
结果:关机重启 还是需要看看具体错误的指令对应到哪行代码。
页:
[1]