通过windbg 得到我们要 hook 的api 地址的方法以及 hook NtOpenProcess 的例子。。。

今天,突然想对 hook 进行一些学习,因为对于一些底层的操作,都是在于ANTI-HOOK 。。。然后才能得到最后的使用权,为此,

自己也要掌握这种很强大的编程手法,那么首先,我们应该知道的一些是,在 win2000 以后,对于 SSDT 的操作,系统都是写了保护的,

那么我们首先应该做的是怎么样来解除掉它们,替换我们的执行地址,当然在这里,我们必须要知道这个结构:

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
 PVOID   ServiceTableBase;
 PULONG  ServiceCounterTableBase;
 ULONG   NumberOfService;
 ULONG   ParamTableBase;

}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;   // 由于KeServiceDescriptorTable只有一项,这里就简单点了

他就是SSDT 表了,这张表就类似于 PE 文件中的 IAT ,存储着一系列的函数地址,我们都知道,现在的系统都是基于保护模式的,当我们要访问内核的时候,MS 已经为我们定义好了接口,那么当我们调用哪些接口的时候,哪些接口会在这张表中查找需要的服务的地址函数,

我们在这里可以截获我们要过滤的函数请求,达到我们的目的。。。

 

这个结构有四个域:

反汇编得到:

 

HookApi!_SERVICE_DESCRIPTOR_TABLE
   +0x000 ServiceTableBase : Ptr32 Void
   +0x004 ServiceCounterTableBase : Ptr32 Uint4B
   +0x008 NumberOfService  : Uint4B
   +0x00c ParamTableBase   : Uint4B

 

//我们的替代的函数,是一个裸函数,编译器不会像其他的函数一样处理它。。。
__declspec(naked) NTSTATUS MyApiAddress(PHANDLE  phandle,
            ACCESS_MASK DesireAddress,
            POBJECT_ATTRIBUTES pObjectAttributes,
            PCLIENT_ID  pClientID)
{
 KdPrint(("NtPOpenProcess...Call"));

 __asm
 {
  push 0C4h;                                      //这两个域,是通过我们要HOOK 的 API 定位得到的
  push 804daaa8h;                 

  jmp  [g_JmpServerAddr];
 }
}

 

kd> u 805c2296
nt!NtOpenProcess:

这里是我们要调用的函数的入口点:

两个参数,遵循 C 的调用方式,手工清栈。。。就得到了
805c2296 68c4000000      push    0C4h                       //
805c229b 68a8aa4d80      push    offset nt!ObWatchHandles+0x25c (804daaa8)
805c22a0 e86b6cf7ff      call    nt!_SEH_prolog (80538f10)


805c22a5 33f6            xor     esi,esi
805c22a7 8975d4          mov     dword ptr [ebp-2Ch],esi
805c22aa 33c0            xor     eax,eax
805c22ac 8d7dd8          lea     edi,[ebp-28h]
805c22af ab              stos    dword ptr es:[edi]

有两种方法获得我们要HOOK 的地址,可以通过函数,推荐PVOID 
  MmGetSystemRoutineAddress(

    IN PUNICODE_STRING  SystemRoutineName 
    ); 

比较方便,不用涉及其他的操作,返回的是要查的地址。。。。

不然的话,需要查MS 定义的服务描述表,而且个个平台还不一样,难以做到跨平台。。。

 

上边就完成了我们的导向工作,只要获取到了需要跳转的地址就 OK 了。。。

extern PSERVICE_DESCRIPTOR_TABLE    KeServiceDescriptorTable; // KeServiceDescriptorTable为导出函数

 

操作之前:

我们需要:

// 去掉内存保护
VOID ClearMemoryProtect()
{
 __asm           
 {
  cli;
  mov eax, cr0;
  and eax, not 10000h;
  mov cr0, eax;
 }
}

 

// 跳转到NtOpenProcess函数头+10的地方,这样在其前面写的JMP都失效了,完成替换

 g_JmpServerAddr = (ULONG)NtOpenProcess + 10;  

 

 

// 回复内存的保护
VOID RecoverMemoryProtect()
{
 __asm          
 {
  cli;
  mov eax, cr0;
  or eax, not 10000h;
  mov cr0, eax;
  sti;
 }
}

 

 *((ULONG*)uAddress) = (ULONG)MyApiAddress;  // HOOK SSDT

 

去除内存的写保护,操作完成自后,回复之。。。。

然后我们就可以完成监视的功能。。。

 

 

 

你可能感兴趣的:(通过windbg 得到我们要 hook 的api 地址的方法以及 hook NtOpenProcess 的例子。。。)