一种Object hook的思路和实现过程

 作 者: sudami
时 间: 2008-08-08,20:34
链 接: http://bbs.pediy.com/showthread.php?t=70329

<一种Object hook的思路和实现过程>
 
作者:sudami [sudami@163.com]
时间:2008/08/08 
主题:NtClose相关逆向
关键词:Object/type/hook/OkayToCloseProcedure
 
------------------------------------------------------
    本来不准备写出来污染眼球的,因为最终没有完全实现.但觉得思路可行,之前也没人具分析过,于是匆匆的写点儿文章,给大家提供些资料参考,也许有兴趣的同学能够进一步的深入...
写的很菜,老鸟飘过  . =.=|
 
    今天上午在坛子看到一帖,关于 "抹掉所有进程中自己的Handle",来防止炉子的LzOpenProcess,防dump等作用.主要思路就是NtClose;其实那个古老的RK-- FUTO_enhanced的code中已经实现的更加完善. 抽点儿时间想了想,于是就有了下面的一些分析:
 
lkd> u NtClose
nt!NtClose:
8056f9e9 8bff  mov  edi, edi
8056f9eb 55  push  ebp
8056f9ec 8bec  mov  ebp, esp
8056f9ee 64a124010000  mov  eax, dword  ptr  fs:[00000124h]
8056f9f4 0fbe8040010000  movsx  eax, byte  ptr [ eax+140h]
8056f9fb 6a00  push 0  ;比WRK中多一个参数
8056f9fd 50  push  eax
8056f9fe ff7508  push  dword  ptr [ ebp+8]
8056fa01 e85bffffff  call nt!ObpCloseHandle (8056f961)
;ObpCloseHandle(Handle, KeGetCurrentThread()->PreviousMode, 0);
 
8056fa06 5d  pop  ebp
8056fa07 c20400  ret 4
8056fa0a 90  nop
8056fa0b 90  nop
8056fa0c 90  nop
8056fa0d 90  nop
8056fa0e 90  nop
-------------------------------------------------------------------
lkd> u ObpCloseHandle l 20
nt!ObpCloseHandle:
8056f96c c645ff00  mov  byte  ptr [ ebp-1],0
8056f970 64a124010000  mov  eax, dword  ptr  fs:[00000124h]
8056f976 8b4d08  mov  ecx, dword  ptr [ ebp+8]  ;ecx = Handle
8056f979 8bf0  mov  esi, eax
8056f97b 8b5e44  mov  ebx, dword  ptr [ esi+44h]  ;ebx = PsGetCurrentProcess();
8056f97e b800000080  mov  eax,80000000h
8056f983 23c8  and  ecx, eax
8056f985 3bc8  cmp  ecx, eax
;/* Check if we're dealing with a kernel handle */
;#define KERNEL_HANDLE_FLAG (1 << ((sizeof(HANDLE) * 8) - 1))
; return (BOOLEAN)((ULONG_PTR)Handle & KERNEL_HANDLE_FLAG);
 
8056f987 0f84ccf00000  je nt!ObpCloseHandle+0x28 (8057ea59)  ; -->Is a kernel handle
8056f98d 8bbbc4000000  mov  edi, dword  ptr [ ebx+0C4h] 
;edi = HandleTable = Process->ObjectTable;
;其他的判断会跳到这里
 
8056f993 ff7508  push  dword  ptr [ ebp+8]  ;
8056f996 ff8ed4000000  dec  dword  ptr [ esi+0D4h] ;/* Disable Kernel APCs */
;Thread->KernelApcDisable--; 
8056f99c 57  push  edi
8056f99d e88bf6ffff  call nt!ExMapHandleToPointer (8056f02d)
;eax = HandleTableEntry = ExMapHandleToPointer(HandleTable, Handle);
8056f9a2 85c0  test  eax, eax
8056f9a4 0f844e210200  je nt!ObpCloseHandle+0xbc (80591af8)  ;-->failed,很多处理...
8056f9aa ff7510  push  dword  ptr [ ebp+10h]  ;比WRK中多一个参数
8056f9ad 6a00  push 0
8056f9af ff750c  push  dword  ptr [ ebp+0Ch]
8056f9b2 ff7508  push  dword  ptr [ ebp+8]
8056f9b5 50  push  eax
8056f9b6 57  push  edi
8056f9b7 e853000000  call nt!ObpCloseHandleTableEntry (8056fa0f)
; /* Now close the entry */
;ObpCloseHandleTableEntry( HandleTable,HandleTableEntry,Handle,
; AccessMode,FALSE,0 );
8056f9bc ff86d4000000  inc  dword  ptr [ esi+0D4h] ;/* Enable Kernel APCs */ 
;Thread->KernelApcDisable++; 
 
-------------------------------------------------------------------
lkd> u 8057ea59 l 20  ;-->Is a kernel handle
nt!ObpCloseHandle+0x28:
8057ea59 807d0c00  cmp  byte  ptr [ ebp+0Ch],0
8057ea5d 0f852a0fffff  jne nt!ObpCloseHandle+0x5c (8056f98d)
8057ea63 837d08fe  cmp  dword  ptr [ ebp+8],0FFFFFFFEh
8057ea67 0f84200fffff  je nt!ObpCloseHandle+0x5c (8056f98d)
8057ea6d 837d08ff  cmp  dword  ptr [ ebp+8],0FFFFFFFFh
8057ea71 0f84160fffff  je nt!ObpCloseHandle+0x5c (8056f98d)
8057ea77 314508  xor  dword  ptr [ ebp+8], eax
;#define ObKernelHandleToHandle(Handle) /
; (HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG)
;Handle = ObKernelHandleToHandle(Handle);
 
8057ea7a a154965680  mov  eax, dword  ptr [nt!PsInitialSystemProcess (80569654)]
8057ea7f 3bd8  cmp  ebx, eax
;/* Check if we're not in the system process */
8057ea81 8b3d388c5680  mov  edi, dword  ptr [nt!ObpKernelHandleTable (80568c38)]
8057ea87 0f84060fffff  je nt!ObpCloseHandle+0x62 (8056f993)
8057ea8d 8d4de4  lea  ecx,[ ebp-1Ch]
8057ea90 51  push  ecx
8057ea91 50  push  eax
8057ea92 e8fe8af7ff  call nt!KeStackAttachProcess (804f7595)
8057ea97 c645ff01  mov  byte  ptr [ ebp-1],1
8057ea9b e9f30effff  jmp nt!ObpCloseHandle+0x62 (8056f993) ;attach到system进程后跳回去
--------------------------------------------------------------
 
;继续进到ObpCloseHandleTableEntry函数中:
nt!ObpCloseHandleTableEntry:
8056fa17 8b7d0c  mov  edi, dword  ptr [ ebp+0Ch]
8056fa1a 8b37  mov  esi, dword  ptr [ edi]
8056fa1c 83e6f8  and  esi,0FFFFFFF8h
;esi = ObjectHeader = ObpGetHandleObject(HandleEntry);
;#define ObpGetHandleObject(x) /
; ((POBJECT_HEADER)((ULONG_PTR)x->Object & ~OBJ_HANDLE_ATTRIBUTES))
 
8056fa1f 8b4e08  mov  ecx, dword  ptr [ esi+8]
;nt!_OBJECT_HEADER +0x008 Type : Ptr32 _OBJECT_TYPE
;ecx = ObjectType = ObjectHeader->Type;
8056fa22 83b9a800000000  cmp  dword  ptr [ ecx+0A8h],0
; nt!_OBJECT_TYPE +0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER
; nt!_OBJECT_TYPE_INITIALIZER +0x048 OkayToCloseProcedure
;
8056fa29 8d5618  lea  edx,[ esi+18h]  ; edx=Body=&ObjectHeader->Body;
8056fa2c 894dfc  mov  dword  ptr [ ebp-4], ecx
8056fa2f 89550c  mov  dword  ptr [ ebp+0Ch], edx
8056fa32 0f85e4ab0100  jne nt!ObpCloseHandleTableEntry+0x25 (8058a61c)
;-->正是跳到我们关心的地方.
 
------------------------------------------------------------------------
lkd> u 8058a61c
nt!ObpCloseHandleTableEntry+0x25:
8058a61c 64a124010000  mov  eax, dword  ptr  fs:[00000124h]
8058a622 ff7514  push  dword  ptr [ ebp+14h]  ;AccessMode
8058a625 ff7510  push  dword  ptr [ ebp+10h]  ;Handle
8058a628 52  push  edx  ;Body
8058a629 ff7044  push  dword  ptr [ eax+44h]  ;PsGetCurrentProcess()
8058a62c ff91a8000000  call  dword  ptr [ ecx+0A8h]
; if (!ObjectType->TypeInfo.OkayToCloseProcedure(
; PsGetCurrentProcess(),Body,Handle,AccessMode)) {
; /* 让其返回denny,直接拒绝关我们的句柄 */
; return STATUS_HANDLE_NOT_CLOSABLE;
; }
;
; ---- 要做手脚 ----
;典型的Object hook(MJ0011以前写过一篇文章,即是关于这个的[干涉注册表的hook];
;想必MJ跟踪了这些类似函数的流程,发现了这种隐蔽的hook)
;替换掉这个函数,在我们的fake函数中做处理,是我们自己要保护的handle,就拒绝之
; sudami[sudami@163.com] 2008/08/08
;
8058a632 84c0  test  al, al
8058a634 0f85fe53feff  jne nt!ObpCloseHandleTableEntry+0x52 (8056fa38)
8058a63a e929490700  jmp nt!ObpCloseHandleTableEntry+0x3f (805fef68)  ; --->
8058a63f c3  ret
--------------------------------------------------------------------
lkd> u 805fef68 l 10
nt!ObpCloseHandleTableEntry+0x3f:
805fef68 57  push  edi
805fef69 ff7508  push  dword  ptr [ ebp+8]
805fef6c e802d7f6ff  call nt!ExUnlockHandleTableEntry (8056c673)
805fef71 b8350200c0  mov  eax,0C0000235h
; #define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS)0xC0000235)
805fef76 e9260bf7ff  jmp nt!ObpCloseHandleTableEntry+0x158 (8056faa1)
 
lkd> u 8056faa1 l 10
nt!ObpCloseHandleTableEntry+0x158:
8056faa1 5f  pop  edi
8056faa2 5e  pop  esi
8056faa3 c9  leave
8056faa4 c21800  ret 18h
 
---------------------------------------------------------------------
ps:或者你可以进到 ExDestroyHandle函数中,从这里思考其他思路
--> ExpLookupHandleTableEntry-->InterlockedExchangePointer(&HandleTableEntry->Object, NULL);
 
/
继续原来的话题;关键就是patch掉那个函数,看看它的原型:
 
typedef NTSTATUS
(NTAPI * OB_OKAYTOCLOSE_METHOD)(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN HANDLE Handle,
IN KPROCESSOR_MODE AccessMode
);
 
在fake函数中:
引用:
 
1. 处理参数2 - Object;若其type是进程/线程,且和我们关心的相匹配,return 0;
2. 处理参数3 - Handle;ObRefenceObjectByHanlde得到EPROCESS,判断之
 
以上思路具体实现后,便可以防止被其他程序关闭自身句柄.作用如下:
    1. 文件保护 -- 若部分ARK尝试关掉你进程的所有句柄后,删除你的"站炕"文件
[yykingking牛的那种站炕],即使发IRP,也会failed.
    2. 进程相关 -- 可能恶意程序想关掉CSRSS中的自身句柄,来防止被dump;你可以用此种方式保护之
    3. [...]
 
部分关键code如下:

//安装HOOK
void InstallHook()
{
    NTSTATUS status;
     PVOID CureentProcess;
    CureentProcess = ( PVOID)PsGetCurrentProcess();

     __asm
    {
         push  eax
         mov  eax,CureentProcess
         mov  eax,[ eax-0x10]
         mov EprocessObjectType, eax
         pop  eax
    }

    DbgPrint( "Eprocess Object Type :%08x /n" , EprocessObjectType );
    Old_OkayToCloseProcedure = EprocessObjectType->TypeInfo.OkayToCloseProcedure;
    DbgPrint( "Eprocess OkayToCloseProcedure routine :%08x /n ", Old_OkayToCloseProcedure );
    DbgPrint( "DeleteProcedure routine :%08x /n "
                EprocessObjectType->TypeInfo.DeleteProcedure);
     if (!MmIsAddressValid(Old_OkayToCloseProcedure)) {
        DbgPrint( "!MmIsAddressValid");
         return ;
    }
    EprocessObjectType->TypeInfo.OkayToCloseProcedure = fake_OkayToCloseProcedure;
    g_bObjectHook =  TRUE;
     return ;
}

NTSTATUS
fake_OkayToCloseProcedure(    
    PEPROCESS Process OPTIONAL,
     PVOID Object,
     HANDLE Handle,
    KPROCESSOR_MODE AccessCheckMode
    )
{
    NTSTATUS stat ;
     PVOID ProcessObject;
    
    stat = ObReferenceObjectByHandle(Handle,
        GENERIC_READ,
         NULL,
        KernelMode,
        &ProcessObject,
        0);
     if (!NT_SUCCESS( stat )) {
        dbg( "ObReferenceObjectByHandle failed!/n");
         goto _orig_;
    }
     // 若操作的对象是我们关心的进程,且是其他进程在操作
     // 拒绝之
     if ( ( DWORD)g_target_eprocess == ( DWORD)ProcessObject &&
        ( DWORD)g_target_eprocess != ( DWORD)Process ) {
        DbgPrint( "%d :denny it /n", ( DWORD)Process);
         return 0 ;
    }
    
     ///
_orig_:
     __asm
    {
         push  eax
         movzx  eax, AccessCheckMode
         push  eax
         push Handle
         push Object
         push Process
         call Old_OkayToCloseProcedure
         mov stat,  eax
         pop  eax
    } 
     return stat ;

 
名称:  1.jpg
查看次数: 464
文件大小:  41.1 KB
名称:  2.jpg
查看次数: 466
文件大小:  39.4 KB
名称:  3.jpg
查看次数: 466
文件大小:  25.3 KB
名称:  4.jpg
查看次数: 466
文件大小:  20.7 KB
名称:  5.jpg
查看次数: 466
文件大小:  21.5 KB
名称:  6.jpg
查看次数: 464
文件大小:  42.7 KB
名称:  7.jpg
查看次数: 464
文件大小:  30.7 KB
名称:  8.jpg
查看次数: 465
文件大小:  15.5 KB
名称:  9.jpg
查看次数: 463
文件大小:  35.5 KB
名称:  10.jpg
查看次数: 460
文件大小:  25.5 KB
名称:  11.jpg
查看次数: 460
文件大小:  16.2 KB
名称:  12.jpg
查看次数: 461
文件大小:  40.7 KB
名称:  13.jpg
查看次数: 459
文件大小:  7.3 KB
 
附件是完整的object type hook的源码 和 调试笔记
上传的附件
文件类型: txtNtClose相关逆向.txt (2008-08-08 20:33, 10.7 KB, 89 次下载)
文件类型: rarsudami.ObjectHook.code.rar (2008-08-08 20:33, 14.3 KB, 86 次下载)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值