Linux4.19-获取IDT地址

疫情影响不能回临港海大,在家无聊搞Linux系列(一)

目前Linux4.19获取IDT的方法和之前几个版本相同,网上也已经有了很多帖子写了方法,如果已经掌握的朋友可以直接看我的下一篇博客:Linux4.19-通过IDT获取sys_call_table实现系统调用劫持https://blog.csdn.net/qq_41208289/article/details/106013258

我用的是目前最新的Debian10,内核为Linux4.19.0-8-686(32位x86机器)

网上很多博客获取sys_call_table的方法在新的Linux中均已失效,我这个方法目前在Linux4.19中有效。

 

以下为正文:

我们知道,IDT(Interupt Description Table)里面放的是各种中断的处理函数地址,当中断来的时候会先查这个表,然后执行相关的程序,而这个表在内存中就是一个数组,数组中的每个元素对应着一个中断,例如系统调用是0x80中断,当该中断触发时,会查找IDT的0x80处的表项,获取0x80中断处理程序的地址,再执行相关的操作。

而IDT表的每个元素,其实是一个8字节的结构体,从源代码可以看出如下定义:

struct gate_struct {
	u16		offset_low;
	u16		segment;
	struct idt_bits	bits;
	u16		offset_middle;
#ifdef CONFIG_X86_64   // 此处为x64多的一部分内容
	u32		offset_high;
	u32		reserved;
#endif
} __attribute__((packed));

后两项是64位机器多的两项,我用的是32机,因此只需看前四项,其中idt_bits为标志位,占两个字节,因此4项一共是8个字节。其中offset_middle与offset_low拼接成的32位地址即为这个表项对应的中断号的处理程序地址。

如何获取IDT表的地址?

知道了表结构,那么如何获取到表地址呢?IDT表的地址其实是专门存放在一个6字节寄存(在x86中为idtr)中的,从源代码可以看出其中的6字节数据为:

struct desc_ptr {
	unsigned short size;
	unsigned long address;
} __attribute__((packed));

其中的高32位即为idt表的地址。获取这个寄存器的值用C语言是不行的,需要用到汇编指令,因此这里需要采用内联汇编实现。

struct 
{
	unsigned short size;
	unsigned int addr; // 高32位为idt表地址
}__attribute__((packed)) idtr; // idtr是48位6字节寄存器


void get_addr_idt(void)
{
	asm("sidt %0":"=m"(idtr)); //通过idtr获取IDT表的地址
	printk(KERN_ALERT "idt table adr: 0x%x\n", idtr.addr);
}

代码解读:通过sidt指令将idtr寄存器中的内容赋值给idtr结构体中去,此时通过idtr.addr即可获取IDT表的地址。

总结

至此我们已经获取到了IDT表的地址,上面我们讲到IDT表每个表项为8字节,因此0x80中断的表项地址=IDT表地址+0x80*8

下一篇博客我将继续讲解最新的Debian10 Linux4.19在获取到IDT表地址后,如何获取sys_call_table的地址。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值