Hook 内核函数技术细节

刚开始看到通过 SSDT 来 HOOK ZwXXX 内核函数的方法时不是很了解, 等把 ZwXXX 反汇编后才发现技术细节.
原来也没什么新鲜的,就是找到目标函数在 SSDT 中的位置( 偏移量=位置*4 ), 然后保存并替换偏移量处的值为自己新的函数地址就行了。

这种技术现在已是老掉牙了,不过在实际的软件开发中也比较常用, 可以实现各种监控功能.
上次安了个诺顿, 它把所有的 ZwXXX 都给 Hook, 而且在 service.exe 注入了监视线程,作用是防止主进程被关闭.
不说别的了,免得思路被打断了.


下面以 Hook ZwDeviceIoControlFile 为例说明一下:

例如下面的 ring0 级代码:

VOID HookStart( void )
{
    if( !IsHooked )
    {
        RealZwDeviceIoControlFile = SYSCALL( ZwDeviceIoControlFile );

        SYSCALL( ZwDeviceIoControlFile ) = (PVOID) HookZwDeviceIoControlFile;

        IsHooked = TRUE;
    }
}

你能想象这样的代码能取得 ZwDeviceIoControlFile 在 SSDT 中的位置吗?
现在再让我们看看反汇编代码:

.text:00010381                 mov     eax, ds:ZwDeviceIoControlFile   ; 保存 ZwDeviceIoControlFile 地址到 eax
.text:00010386                 mov     ecx, ssdt                                          ; 取得 ssdt 的地址, 保存到 ecx
.text:0001038C                 push    esi
.text:0001038D                 mov     edx, [eax+1]              ; 取得 ZwDeviceIoControlFile 在 SSDT 中的位置, 参看
                                                                                             ; 该函数反汇编后的代码 B838000000    MOV EAX,      00000038,  eax+1 的效果是跳过了B8, 指向了38000000。[eax+1] 的值自然就是 00000038 (NOTE: Little-Endian).现在 edx 值为 00000038.

.text:00010390                 mov     esi, [ecx]                      ; 取得 SSDT 的地址 ==> esi

.text:00010392                 mov     edx, [esi+edx*4]         ; 保存 ZwDeviceIoControlFile 真正的函数地址
.text:00010395                 pop     esi
.text:00010396                 mov     dword_10814, edx

.text:0001039C                 mov     eax, [eax+1]                ; ZwDeviceIoControlFile 函数在 SSDT 的位置 ===> eax
.text:0001039F                 mov     ecx, [ecx]                      ; SSDT 地址


.text:000103A1                 mov     dword ptr [ecx+eax*4], offset sub_1030E    ; 用我们自己新的函数替换
                                                                                  ; ZwDeviceIoControlFile 在SSDT位置中的数值


OK!! ,现在已经在 dword_10814 保存了正确的 ZwDeviceIoControlFile 地址, 并把我们自己的函数 dword_10814 替换了ZwDeviceIoControlFile , 到此完成!


下面是 ZwDeviceIoControlFile的反汇编代码, 可以简单的在windbg 中用 "u ZwDeviceIoControlFile" 得到反汇编代码

00400BC6: B838000000               MOV EAX, 00000038
00400BCB: 8D542404                   LEA EDX, [ESP+04]
00400BCF: CD2E                           INT 2E
00400BD1: C22800                       RETN 0028

入口点加1,便是系统调用号.


 

你可能感兴趣的:(c,汇编,hook)