USER32!__ClientLoadLibrary定位

本文深入探讨了在Windows环境下,通过修改TEB结构中的KernelCallbackTable表实现库注入的技术细节,包括如何利用__ClientLoadLibrary函数加载指定DLL,并通过FixupCallbackPointers函数调整回调指针以实现恶意功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

保护软件一般都直接用新的函数指针替换CallBack表中__ClientLoadLibrary对应的位置

对于Ring3的应用程序,fs:[0]的地址指向的是TEB结构,这个结构的开头是一个NT_TIB结构,NT_TIB结构的0x18偏移处是一个Self指针,指向这个结构自身,也就是指向TEB结构的开头。
TEB结构的0x30偏移是一个指向PEB的指针。PEB又是一个结构,这个结构的0x2偏移处是一个UChar,名叫BeingDebugged,当进程被调试时,此值为1,未被调试时此值为0

因此以下代码逐行执行后的结果:
mov eax,dword ptr fs:[18h];eax=TEB的指针
mov eax,dword ptr [eax+30h];eax=PEB的指针
movzx eax,byte ptr [eax+2h];eax=PEB.BeingDebugged(byte扩展为dword)

TEB和PEB结构的详细内容可以在windbg内核调试状态下使用dt _TEB、dt _PEB命令来察看。

[cpp]  view plain copy
  1. 0:000> x user32!*__ClientLoadLibr*  
  2. 77d28023 USER32!__ClientLoadLibrary = <no type information>  


可以看出TEB结构的0x30偏移是一个指向PEB的指针

[cpp]  view plain copy
  1. 0:001> dt _TEB @$teb  
  2. testDemo!_TEB  
  3.    +0x000 NtTib            : _NT_TIB  
  4.    +0x01c EnvironmentPointer : (null)   
  5.    +0x020 ClientId         : _CLIENT_ID  
  6.    +0x028 ActiveRpcHandle  : (null)   
  7.    +0x02c ThreadLocalStoragePointer : (null)   
  8.    +0x030 ProcessEnvironmentBlock : 0x7ffdd000 _PEB  

而KernelCallbackTable表在PEB的ox2c处:

[cpp]  view plain copy
  1. 0:001> dt _PEB @$peb  
  2. testDemo!_PEB  
  3.    +0x000 InheritedAddressSpace : 0 ''  
  4.    +0x001 ReadImageFileExecOptions : 0 ''  
  5.    +0x002 BeingDebugged    : 0x1 ''  
  6.    +0x003 SpareBool        : 0 ''  
  7.    +0x004 Mutant           : 0xffffffff   
  8.    +0x008 ImageBaseAddress : 0x00400000   
  9.    +0x00c Ldr              : 0x00251ea0 _PEB_LDR_DATA  
  10.    +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS  
  11.    +0x014 SubSystemData    : (null)   
  12.    +0x018 ProcessHeap      : 0x00150000   
  13.    +0x01c FastPebLock      : 0x7c99d600 _RTL_CRITICAL_SECTION  
  14.    +0x020 SparePtr1        : 0x7c921000   
  15.    +0x024 SparePtr2        : 0x7c9210e0   
  16.    +0x028 EnvironmentUpdateCount : 1  
  17.    +0x02c KernelCallbackTable : 0x77d12970   


不同版本的window系统KernelCallbackTable函数列表位置不同:以下是XPSP3的:

[cpp]  view plain copy
  1. 0:001> r @$peb  
  2. $peb=7ffdd000  
  3. 0:001> dds 0x77d12970   
  4. 77d12970  77d27f3c USER32!__fnCOPYDATA  
  5. 77d12974  77d587b3 USER32!__fnCOPYGLOBALDATA  
  6. 77d12978  77d28ec8 USER32!__fnDWORD  
  7. 77d1297c  77d2b149 USER32!__fnNCDESTROY  
  8. 77d12980  77d5876c USER32!__fnDWORDOPTINLPMSG  
  9. 77d12984  77d5896d USER32!__fnINOUTDRAG  
  10. 77d12988  77d3b84d USER32!__fnGETTEXTLENGTHS  
  11. 77d1298c  77d58c42 USER32!__fnINCNTOUTSTRING  
  12. 77d12990  77d285c1 USER32!__fnINCNTOUTSTRINGNULL  
  13. 77d12994  77d58b0f USER32!__fnINLPCOMPAREITEMSTRUCT  
  14. 77d12998  77d2ce26 USER32!__fnINLPCREATESTRUCT  
  15. 77d1299c  77d58b4d USER32!__fnINLPDELETEITEMSTRUCT  
  16. 77d129a0  77d4feec USER32!__fnINLPDRAWITEMSTRUCT  
  17. 77d129a4  77d58b8b USER32!__fnINLPHELPINFOSTRUCT  
  18. 77d129a8  77d58b8b USER32!__fnINLPHELPINFOSTRUCT  
  19. 77d129ac  77d589ad USER32!__fnINLPMDICREATESTRUCT  
  20. 77d129b0  77d4f65c USER32!__fnINOUTLPMEASUREITEMSTRUCT  
  21. 77d129b4  77d2be16 USER32!__fnINLPWINDOWPOS  
  22. 77d129b8  77d2d063 USER32!__fnINOUTLPPOINT5  
  23. 77d129bc  77d2bd0d USER32!__fnINOUTLPSCROLLINFO  
  24. 77d129c0  77d3e285 USER32!__fnINOUTLPRECT  
  25. 77d129c4  77d2bf4c USER32!__fnINOUTNCCALCSIZE  
  26. 77d129c8  77d2bd0d USER32!__fnINOUTLPSCROLLINFO  
  27. 77d129cc  77d589ff USER32!__fnINPAINTCLIPBRD  
  28. 77d129d0  77d58a66 USER32!__fnINSIZECLIPBRD  
  29. 77d129d4  77d30d41 USER32!__fnINDESTROYCLIPBRD  
  30. 77d129d8  77d2aca1 USER32!__fnINSTRINGNULL  
  31. 77d129dc  77d2aca1 USER32!__fnINSTRINGNULL  
  32. 77d129e0  77d1e68c USER32!__fnINDEVICECHANGE  
  33. 77d129e4  77d58cd7 USER32!__fnINOUTNEXTMENU  
  34. 77d129e8  77d593f5 USER32!__fnLOGONNOTIFY  
  35. 77d129ec  77d58728 USER32!__fnOUTDWORDDWORD  
  36. 0:001> dds 77d129ec    
  37. 77d129ec  77d58728 USER32!__fnOUTDWORDDWORD  
  38. 77d129f0  77d58728 USER32!__fnOUTDWORDDWORD  
  39. 77d129f4  77d586e5 USER32!__fnOUTDWORDINDWORD  
  40. 77d129f8  77d58acc USER32!__fnOUTLPRECT  
  41. 77d129fc  77d285c1 USER32!__fnINCNTOUTSTRINGNULL  
  42. 77d12a00  77d58b8b USER32!__fnINLPHELPINFOSTRUCT  
  43. 77d12a04  77d285c1 USER32!__fnINCNTOUTSTRINGNULL  
  44. 77d12a08  77d5882b USER32!__fnSENTDDEMSG  
  45. 77d12a0c  77d2c2f5 USER32!__fnINOUTSTYLECHANGE  
  46. 77d12a10  77d30214 USER32!__fnHkINDWORD  
  47. 77d12a14  77d4f92a USER32!__fnHkINLPCBTACTIVATESTRUCT  
  48. 77d12a18  77d4f86c USER32!__fnHkINLPCBTCREATESTRUCT  
  49. 77d12a1c  77d58dce USER32!__fnHkINLPDEBUGHOOKSTRUCT  
  50. 77d12a20  77d316a3 USER32!__fnHkINLPMOUSEHOOKSTRUCTEX  
  51. 77d12a24  77d58d54 USER32!__fnHkINLPKBDLLHOOKSTRUCT  
  52. 77d12a28  77d58d91 USER32!__fnHkINLPMSLLHOOKSTRUCT  
  53. 77d12a2c  77d278ab USER32!__fnHkINLPMSG  
  54. 77d12a30  77d58d17 USER32!__fnHkINLPRECT  
  55. 77d12a34  77d4f065 USER32!__fnHkOPTINLPEVENTMSG  
  56. 77d12a38  77d58eb9 USER32!__ClientCopyDDEIn1  
  57. 77d12a3c  77d58efb USER32!__ClientCopyDDEIn2  
  58. 77d12a40  77d58f5e USER32!__ClientCopyDDEOut1  
  59. 77d12a44  77d58f2d USER32!__ClientCopyDDEOut2  
  60. 77d12a48  77d2eb09 USER32!__ClientCopyImage  
  61. 77d12a4c  77d58f92 USER32!__ClientEventCallback  
  62. 77d12a50  77d319f6 USER32!__ClientFindMnemChar  
  63. 77d12a54  77d228f3 USER32!__ClientFontSweep  
  64. 77d12a58  77d58e4c USER32!__ClientFreeDDEHandle  
  65. 77d12a5c  77d282ff USER32!__ClientFreeLibrary  
  66. 77d12a60  77d1f4b2 USER32!__ClientGetCharsetInfo  
  67. 77d12a64  77d58e83 USER32!__ClientGetDDEFlags  
  68. 77d12a68  77d58fdc USER32!__ClientGetDDEHookData  
  69. 0:001> dds 77d12a68    
  70. 77d12a68  77d58fdc USER32!__ClientGetDDEHookData  
  71. 77d12a6c  77d4f9f5 USER32!__ClientGetListboxString  
  72. 77d12a70  77d1ec46 USER32!__ClientGetMessageMPH  
  73. 77d12a74  77d216eb USER32!__ClientLoadImage  
  74. 77d12a78  77d28023 USER32!__ClientLoadLibrary  
  75. 77d12a7c  77d2ec03 USER32!__ClientLoadMenu  
  76. 77d12a80  77d1ee0d USER32!__ClientLoadLocalT1Fonts  
  77. 77d12a84  77d209e4 USER32!__ClientLoadRemoteT1Fonts  
  78. 77d12a88  77d5907b USER32!__ClientPSMTextOut  
  79. 77d12a8c  77d590d1 USER32!__ClientLpkDrawTextEx  
  80. 77d12a90  77d59135 USER32!__ClientExtTextOutW  
  81. 77d12a94  77d5919a USER32!__ClientGetTextExtentPointW  
  82. 77d12a98  77d59019 USER32!__ClientCharToWchar  
  83. 77d12a9c  77d1ed14 USER32!__ClientAddFontResourceW  
  84. 77d12aa0  77d1a13e USER32!__ClientThreadSetup  
  85. 77d12aa4  77d59253 USER32!__ClientDeliverUserApc  
  86. 77d12aa8  77d591f1 USER32!__ClientNoMemoryPopup  
  87. 77d12aac  77d2a740 USER32!__ClientMonitorEnumProc  
  88. 77d12ab0  77d5944a USER32!__ClientCallWinEventProc  
  89. 77d12ab4  77d58e15 USER32!__ClientWaitMessageExMPH  
  90. 77d12ab8  77d2cf8e USER32!__ClientWOWGetProcModule  
  91. 77d12abc  77d5948d USER32!__ClientWOWTask16SchedNotify  
  92. 77d12ac0  77d59266 USER32!__ClientImmLoadLayout  
  93. 77d12ac4  77d592c2 USER32!__ClientImmProcessKey  
  94. 77d12ac8  77d59302 USER32!__fnIMECONTROL  
  95. 77d12acc  77d58896 USER32!__fnINWPARAMDBCSCHAR  
  96. 77d12ad0  77d3b84d USER32!__fnGETTEXTLENGTHS  
  97. 77d12ad4  77d58bdc USER32!__fnINLPKDRAWSWITCHWND  
  98. 77d12ad8  77d21805 USER32!__ClientLoadStringW  
  99. 77d12adc  77d65827 USER32!__ClientLoadOLE  
  100. 77d12ae0  77d65704 USER32!__ClientRegisterDragDrop  
  101. 77d12ae4  77d65743 USER32!__ClientRevokeDragDrop  
  102. 0:001> dds 77d12ae4    
  103. 77d12ae4  77d65743 USER32!__ClientRevokeDragDrop  
  104. 77d12ae8  77d593b2 USER32!__fnINOUTMENUGETOBJECT  
  105. 77d12aec  77d303f7 USER32!__ClientPrinterThunk  
  106. 77d12af0  77d594cc USER32!__fnOUTLPCOMBOBOXINFO  
  107. 77d12af4  77d5950c USER32!__fnOUTLPSCROLLBARINFO  


我们可以找到__ClientLoadLibrary函数对应的位置:

[cpp]  view plain copy
  1. 77d12a78  77d28023 USER32!__ClientLoadLibrary  

相对于KernelCallbackTable的起始位置77d12970偏移为0x108,保护软件一般是直接把这一行的77d28023换成自己的函数地址,然后判断传入参数,合法就在自己函数中跳回USER32!__ClientLoadLibrary

下面有一篇http://hi.baidu.com/_achillis/blog/item/1f137c8000c54bd3bd3e1eec.html

 

摘了一篇文章快照:(自己加点理解)

Anti SetWindowsHookEx DLL injection made possible :D Read on.

After spending some time reversing the user32 internals, I discovered this undocumented function. This function is responsible to load the SetWindowsHookEx() registered DLL into your process. This blog will only focus on usermode, where the actual DLL loading takes place.

user32.__ClientLoadLibrary(lpHook)

This function takes only 1 argument, a pointer to an undocumented structure allocated in process stack. It holds the path of the DLL, pointer to notification function and some yet to be known data.

[cpp]  view plain copy
  1. typedef struct  
  2. {  
  3.     DWORD unknow_0;                 // 0x00  
  4.     DWORD unknow_4;                 // 0x04  
  5.     DWORD nCount;                   // 0x08  
  6.     DWORD unknow_c;                 // 0x0C  
  7.     DWORD offCbKPtrs;               // 0x10  
  8.     DWORD bFixed;                   // 0x14  
  9.     UNICODE_STRING lpDllPath;       // 0x18  
  10.     DWORD lpfnNotiy;                // 0x20  
  11. }USERHOOK;  


 

At the beginning of function, it checks for _USERHOOK.nCount and _USERHOOK.bFixed value. Then it calls toFixupCallbackPointers.

user32.FixupCallbackPointers(lpHook)

It takes only 1 argument, the same argument passed to __ClientLoadLibrary. This function “fix up” the pointers in a pretty interesting way. First it locate the address of callback pointers.

lpCbkPtrs = lpHook + offCbkPtrs

Then it loops through the a list of pointers and fix it up by resolving the offset to actual address.

newaddress = lpHook + offset

After fixing up all the pointers, we return to __ClientLoadLibrary and then it calls to InitUserApiHook.

一般都是自己写FixupCallbackPointers:(其实后dumpbin一看,就会发现这个函数不是导出函数,所以没法直接调用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值