idt hook 3

二.IDT hook
   (一)基本思路:IDT(Interrupt Descriptor Table)中断描述符表,是用来处理中断的。中断就是停下现在的活动,去完成新的任务。一个中断可以起源于软件或硬件。比如,出现页错误,调用IDT中的0x0E。或用户进程请求系统服务(SSDT)时,调用IDT中的0x2E。而系统服务的调用是经常的,这个中断就能触发。我们现在就想办法,先在系统中找到IDT,然后确定0x2E在IDT中的地址,最后用我们的函数地址去取代它,这样以来,用户的进程(可以特定设置)一调用系统服务,我们的hook函数即被激发。
   (二)需解决的问题:从上面分析可以看出,我们大概需要解决这几个问题:
   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;
  
   }
具体代码见:
www.rootkit.com/vault/fuzen_op/strace_Fuzen.zip
   (三)注意点:
  
1.每个处理器都有个IDT,所以对于多CPU一定要注意,所有的IDT都要hook。
   2.在winxp,win2k3,vsta下失效。
  
   三.SYSENTRY hook
   为了性能的考虑,xp后的系统都改用sysentry命令来进入ring0,去调用SSDT中的服务,不再是通过IDT中的 int 2E。这也使得我们hook也变得相对容易了。


   首先获得sysentry的地址,然后改之,不用再考虑IDT了。见下面的代码:
   #include "ntddk.h"
  
   ULONG d_origKiFastCallEntry; // 原ntoskrnl!KiFastCallEntry地址
  
   VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
   {
     DbgPrint("ROOTKIT: OnUnload called/n");
   }
  
   // Hook function
   __declspec(naked) MyKiFastCallEntry()
   {
     __asm {
       jmp [d_origKiFastCallEntry]   //这啥都没做,换成你想干的
           }
   }
  
  
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
   {
     theDriverObject->DriverUnload   = OnUnload;
  
     __asm {
                      mov ecx, 0x176                 
       rdmsr                           // 读IA3_SYSENTER_EIP寄存器值,存有sysenter的地址             
       mov d_origKiFastCallEntry, eax //保存原值,以便恢复
       mov eax, MyKiFastCallEntry      // hook函数地址
       wrmsr                           // 将hook函数移入IA32_SYSENTER_EIP寄存器
     }
  
     return STATUS_SUCCESS;
   }
  
  
基本的改变数据结构的hook就说到这里,当然还有DKOM这种高级的技术,有兴趣的自己去看看吧。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用中提到,hook可以分为两类:一种是修改函数代码,一种是修改函数地址。其中,修改函数代码的方式可以通过Inline hook实现,而修改函数地址的方式可以通过IAT hook、SSDT hook、IRP hookIDT hook等方法实现。引用中给出了一个使用memcpy函数进行hook的示例代码。在这个示例中,先定义了一个结构体Thook修改代码,结构体中包含了一些汇编指令和跳转地址等信息。然后通过调用memcpy_s函数,将这个结构体的内容拷贝到目标函数的地址,从而实现对目标函数的hook。同样地,引用中也给出了另一个使用memcpy函数进行hook的示例代码,并且提到了备份被覆盖的代码以及跳转地址等操作。综上所述,可以使用memcpy函数进行hook操作,通过拷贝特定的指令或者结构体内容到目标函数的地址来实现hook。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [浅谈hook攻防](https://blog.csdn.net/hongduilanjun/article/details/124676926)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [各种HOOK方式和检测对抗方法](https://blog.csdn.net/qq_43355637/article/details/127061136)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值