欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]浅析****安全卫士hook"框架"

[原创]浅析****安全卫士hook"框架"

昨日闲着无聊 随手下了个****安全卫士, 想简单看看其功能大概什么样, 随后就发现了些有趣的东西.
本篇就写下其最有毒的 hook”框架”,
软件主程序版本: 1.6.0.8746   ==> 官网最新版
****port.sys: 1.6.0.547
****cport.sys 1.6.0.547

nt!KiFastCallEntry+0xb8:

8053e618 33db            xor     ebx,ebx

8053e61a 0b99700f0000    or      ebx,dword ptr [ecx+0F70h]

8053e620 740a            je      nt!KiFastCallEntry+0xcc (8053e62c)

8053e622 52              push    edx

8053e623 50              push    eax

8053e624 ff1564405580    call    dword ptr [nt!KeGdiFlushUserBatch (80554064)]

8053e62a 58              pop     eax   //> service number

8053e62b 5a              pop     edx  //> argument address

8053e62c e857acd605      call    862a9288  //> ****hook point

8053e631 e88bf28b5f      call    dfdfd8c1

8053e636 cd0e            int     0Eh

8053e638 c9              leave

8053e639 8a0c18          mov     cl,byte ptr [eax+ebx]

8053e63c 8b3f            mov     edi,dword ptr [edi]

8053e63e 8b1c87          mov     ebx,dword ptr [edi+eax*4]

8053e641 e9524fe705      jmp     863b3598   //>360 hook point

8053e646 8bfc            mov     edi,esp

8053e648 3b35549a5580    cmp     esi,dword ptr [nt!MmUserProbeAddress (80559a54)]

8053e64e 0f83a8010000    jae     nt!KiSystemCallExit2+0x9f (8053e7fc)

8053e654 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

8053e656 ffd3            call    ebx

8053e658 8be5            mov     esp,ebp

8053e65a 8b0d24f1dfff    mov     ecx,dword ptr ds:[0FFDFF124h]

8053e660 8b553c          mov     edx,dword ptr [ebp+3Ch]

8053e663 899134010000    mov     dword ptr [ecx+134h],edx

!chkimg nt -d

8053e62c-8053e631  6 bytes - nt!KiFastCallEntry+cc (+0x3b634)

[ ff 05 38 f6 df ff:e8 57 ac d6 05 e8 ]

8053e636-8053e637  2 bytes - nt!KiFastCallEntry+d6 (+0x0a)

[ 0c 33:cd 0e ]


通过上面可以看到在****的挂钩点在常规杀软的前面(360 Q管 金山 百度等), 在该点上其寄存器eax ebx保存的系统服务号 ecx保存表的索引 edx保存的是参数地址 edi保存系统服务表地址.
框架实现在 ****port.sys和****Cport.sys中,这两个在功能上类似360的hookport和360selfprotect 即前者实现框架后者注册过滤函数.
当我满怀兴奋的心情祭出IDA打开****port.sys和****Cport.sys时, 发现我伟大的F5居然不能用. 直接看反汇编 然后瞬间爆炸,满眼的花指令 连shllcode派发函数都是花指令 乱序长度不一 本想写个idc脚本去了 但是实在太多变形就放弃了, 但是不影响我们分析.基本花指令格式如下:

cmp     reg, 77584BBh

jnz     reloc_handle  //>跳到重定位处理流程

...junk code

  

reloc_handle

        push    eax  //> 这两个指令 随机可有可无

        call    $+5

  mov     eax, true_handle  //>真实地址

  mov     [esp+2Ch+var_2C], eax  //>修改返回地址

  mov     eax, edx

  retn


//> 看下其shellcode
kd> dt nt!_pool_header 862a9288-8
   +0x000 PreviousSize     : 0y000000110 (0x6)
   +0x000 PoolIndex        : 0y0000000 (0)
   +0x002 BlockSize        : 0y000100111 (0x27)
   +0x002 PoolType         : 0y0000101 (0x5)
   +0x000 Ulong1           : 0xa270006
   +0x004 ProcessBilled    : 0x73747562 _EPROCESS
   +0x004 PoolTag          : 0x73747562
   +0x004 AllocatorBackTraceIndex : 0x7562
   +0x006 PoolTagHash      : 0x7374
kd> .formats 0x73747562
Evaluate expression:
  Hex:     73747562
  Decimal: 1937012066
  Octal:   16335072542
  Binary:  01110011 01110100 01110101 01100010
  Chars:   stub
  Time:    Tue May 20 10:54:26 2031
  Float:   low 1.9368e+031 high 0
  Double:  9.57011e-315
//>其kifastcall挂钩点代理函数如下

kd> uf  862a9288     

862a9288 50              push    eax

862a9289 52              push    edx

862a928a 51              push    ecx

862a928b 8bd4            mov     edx,esp

862a928d b8a06442f7      mov     eax,offset ****Port+0x4a0 (f74264a0) //> 跳转地址

862a9292 91              xchg    eax,ecx

862a9293 81f9bb847507    cmp     ecx,77584BBh

862a9299 0f85ec000000    jne     862a938b

862a929f b923000000      mov     ecx,23h

862a92a4 6a30            push    30h

862a92a6 0fa1            pop     fs

862a92a8 668ed9          mov     ds,cx

862a92ab 668ec1          mov     es,cx

862a92ae 648b0d40000000  mov     ecx,dword ptr fs:[40h]

862a92b5 8b6104          mov     esp,dword ptr [ecx+4]

862a92b8 6a23            push    23h

862a92ba 52              push    edx

862a92bb 9c              pushfd

862a92bc 6a02            push    2

862a92be 83c208          add     edx,8

862a92c1 9d              popfd

862a92c2 804c240102      or      byte ptr [esp+1],2

862a92c7 6a1b            push    1Bh

862a92c9 3eff350403dfff  push    dword ptr ds:[0FFDF0304h]

862a92d0 6a00            push    0

862a92d2 55              push    ebp

862a92d3 53              push    ebx

862a92d4 56              push    esi

862a92d5 57              push    edi

862a92d6 648b1d1c000000  mov     ebx,dword ptr fs:[1Ch]

862a92dd 6a3b            push    3Bh

862a92df 8bb324010000    mov     esi,dword ptr [ebx+124h]

862a92e5 ff33            push    dword ptr [ebx]

862a92e7 c703ffffffff    mov     dword ptr [ebx],0FFFFFFFFh

862a92ed 8b6e18          mov     ebp,dword ptr [esi+18h]

862a92f0 6a01            push    1

862a92f2 83ec48          sub     esp,48h

862a92f5 81ed9c020000    sub     ebp,29Ch

862a92fb c6864001000001  mov     byte ptr [esi+140h],1

862a9302 3bec            cmp     ebp,esp

862a9304 83652c00        and     dword ptr [ebp+2Ch],0

862a9308 f6462cff        test    byte ptr [esi+2Ch],0FFh

862a930c 89ae34010000    mov     dword ptr [esi+134h],ebp

862a9312 8b5d60          mov     ebx,dword ptr [ebp+60h]

862a9315 8b7d68          mov     edi,dword ptr [ebp+68h]

862a9318 89550c          mov     dword ptr [ebp+0Ch],edx

862a931b c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h

862a9322 895d00          mov     dword ptr [ebp],ebx

862a9325 897d04          mov     dword ptr [ebp+4],edi

862a9328 fb              sti

862a9329 8bf8            mov     edi,eax

862a932b c1ef08          shr     edi,8

862a932e 83e730          and     edi,30h

862a9331 8bcf            mov     ecx,edi

862a9333 03bee0000000    add     edi,dword ptr [esi+0E0h]

862a9339 8bd8            mov     ebx,eax

862a933b 25ff0f0000      and     eax,0FFFh

862a9340 3b4708          cmp     eax,dword ptr [edi+8]

862a9343 83f910          cmp     ecx,10h

862a9346 648b0d18000000  mov     ecx,dword ptr fs:[18h]

862a934d 33db            xor     ebx,ebx

862a934f 0b99700f0000    or      ebx,dword ptr [ecx+0F70h]

862a9355 52              push    edx

862a9356 50              push    eax

862a9357 58              pop     eax

862a9358 5a              pop     edx

862a9359 64ff0538060000  inc     dword ptr fs:[638h]

862a9360 8bf2            mov     esi,edx

862a9362 8b5f0c          mov     ebx,dword ptr [edi+0Ch]

862a9365 33c9            xor     ecx,ecx

862a9367 8a0c18          mov     cl,byte ptr [eax+ebx]

862a936a 8b3f            mov     edi,dword ptr [edi]

862a936c 8b1c87          mov     ebx,dword ptr [edi+eax*4]

862a936f 2be1            sub     esp,ecx

862a9371 c1e902          shr     ecx,2

862a9374 8bfc            mov     edi,esp

862a9376 8be5            mov     esp,ebp

862a9378 648b0d24010000  mov     ecx,dword ptr fs:[124h]

862a937f 8b553c          mov     edx,dword ptr [ebp+3Ch]

862a9382 899134010000    mov     dword ptr [ecx+134h],edx

862a9388 5e              pop     esi

862a9389 5f              pop     edi

862a938a 5b              pop     ebx

862a938b 894a0c          mov     dword ptr [edx+0Ch],ecx  //>修改返回地址配合ret

862a938e 8bc1            mov     eax,ecx

862a9390 8bd3            mov     edx,ebx

862a9392 59              pop     ecx

862a9393 5a              pop     edx

862a9394 58              pop     eax

862a9395 c3              ret


该函数去掉花指令其实就是实现了一个jmp指令 jmp ****Port+0x4a0 (f74264a0)
****port的挂钩点寻找是通过rdmsr指令读取SYSENTER_EIP_MSR(0x176)寄存器的值 来找到kifastcallentry的地址进而匹配特征码进程挂钩如下图:



下面贴出 最关键的处理简化流程



简单来讲流程如下: 在驱动初始化时会通过解析PE 来获取两份纯净的服务函数表(ssdt 和 shadow ssdt),过滤函数表没有任何数据结构只是一个函数指针数组, 与服务号对应 如果该服务号有过滤函数则数组元素非空, 如果没有过滤函数则数组元素值填0, 派发例程通过判断改值是否为0 判断有无过滤函数. 如果有过滤函数则调用过滤函数, 如果没有过滤函数则调用纯净的服务函数。如下图:
系统调用-->kifastcallentry-->****dispatch-->判断服务表是ssdt还是shadowssdt-->根据服务号和对应表 找到相应的过滤函数以及对应的纯净NT函数-->进行派发调用如果过滤函数非空则调用过滤函数否则调用纯净Nt服务
至此 “框架”就到此结束。
其中该驱动对 
84h NtPlugPlayControl
3f  NewNtDeleteKey
41  NewNtDeleteValueKey
f7  NewNtSetValueKey
c0  NewNtRenameKey
b1  NewNtQueryValueKey
这6个调用是单独处理 但是代码逻辑还是跟框架一样,所以应该是后期做优化没去掉该处代码.
那么问题来了 为何是有毒的hook”框架”呢,
细看一下派发流程:
1.不管过不过滤 最终都会调用 纯净服务函数  穿透ssdt hook.
2.如果其他软件是通过ssdt hook 返回地址来找挂钩点的话 装了**** 直接导致找不到挂钩点,因为调用不会走到代理函数里面去(可以通过rdsmr 或者idt 0x2e去寻找).
3.接管nt派发调用 即真正的调用服务函数不会在nt 的原始派发代码里 而是****port.sys写死在自己的代码里.(即跳过nt 本身的call ebx 在自己的代码里call ebx(高版本系统是call edx)) ,而360 Q管金山百度等 大致钩子位置相近或者一致但是都是在系统原有派发前面挂钩(即call ebx之前挂钩) 他们的挂钩属于寄存器hook, 即修改ebx(服务函数)的值, 最终让nt 服务派发器去调用. 恰巧****在接管派发流程时 不会重走nt的服务派发流程(这里的派发是指调用服务函数 并不是全部的派发代码), 直接在自己的代码里派发 这样 就造成了除****之外的所有的杀软 需要钩子的功能全部失效.
所以这套服务派发逻辑 毒就毒在没有考虑兼容性 比如多杀软共存(感觉像是故意的~)
以xp为例 其过滤函数表如下:
SSDT:
服务号   服务名称
==================================================
2     fake_NtAccessCheckAndAuditAlarm  
11     fake_NtAdjustPrivilegesToken     
17     fake_NtAllocateVirtualMemory 
19     fake_NewNtAssignProcessToJobObject
25    fake_NtClose
31    fake_NtConnectPort
37    fake_NtCreateFile
41     fake_NewNtCreateKey
43     fake_NtCreateMutant
45     fake_NtCreatePagingFile
48     fake_NtCreateProcessEx
50    fake_NtCreateSection
52     fake_NtCreateSymbolicLinkObject
53      fake_NtCreateThread
57      fake_NtDebugActiveProcess
62     fake_NtDeleteFile
63      fake_NtDeleteKey 
65     fake_NtDeleteValueKey
66    fake_NtDeviceIoControlFile
67       fake_ZwDisplayString
68     fake_NtDuplicateObject
71    fake_NtEnumerateKey
73    fake_NtEnumerateValueKey 
83    fake_ZwFreeVirtualMemory
84    fake_NtFsControlFile
93    fake_NtInitiatePowerAction
97     fake_NtLoadDriver
105    fake_NtMakeTemporaryObject
116    fake_NtOpenFile
119    fake_NtOpenKey
122    fake_NtOpenProcess
125     fake_NtOpenSection
127    fake_NtOpenSymbolicLinkObject
128     fake_NtOpenThread
132    fake_NtPlugPlayControl
137    fake_NtProtectVirtualMemory
160    fake_NtQueryKey
177    fake_NtQueryValueKey
178     fake_NtQueryVirtualMemory
180     fake_NtQueueApcThread
182     fake_NewNtRaiseHardError
192      fake_NtRenameKey
193     fake_NtReplaceKey
200    fake_NtRequestWaitReplyPort
204     fake_NtRestoreKey
210   fake_NtSecureConnectPort
213    fake_NtSetContextThread
224    fake_NtSetInformationFile
228   fake_NtSetInformationProcess
237    fake_NtSetSecurityObject
240     fake_NtSetSystemInformation
241     fake_NtSetSystemPowerState
242     fake_NtSetSystemTime
244    fake_NtSetTimer
247    fake_NtSetValueKey
249    fake_NtShutdownSystem
253    fake_NtSuspendProcess
254    fake_NtSuspendThread
255    fake_NtSystemDebugControl
256    fake_NtTerminateJobObject
257    fake_NtTerminateProcess
258      fake_NtTerminateThread
259     fake_NtTestAlert
262     fake_NtUnloadDriver
267    fake_NtUnmapViewOfSection
274     fake_NtWriteFile
277     fake_NtWriteVirtualMemory
ShadowSSDT
服务号  服务名称
=========================================================
310    fake_NtUserBlockInput
319    fake_NtUserCallHwndParamLock
330      fake_NtUserClipCursor
355    fake_NtUserDestroyWindow
383     fake_NtUserGetAsyncKeyState
414   fake_NtUserGetKeyboardState
416     fake_NtUserGetKeyState
427     fake_NtUserGetRawInputBuffer
428     fake_NtUserGetRawInputData
460     fake_NtUserMessageCall
465     fake_NtUserMoveWindow
475     fake_NtUserPostMessage
476     fake_NtUserPostThreadMessage
502   fake_NtUserSendInput
517    fake_NtUserSetImeInfoEx
529   fake_NtUserSetParent
544    fake_NtUserSetWindowLong
545   fake_NtUserSetWindowPlacement
546    fake_NtUserSetWindowPos
547    fake_NtUserSetWindowRgn
549    fake_NtUserSetWindowsHookEx
552   fake_NtUserSetWinEventHook
555    fake_NtUserShowWindow
556    fake_NtUserShowWindowAsync
559    fake_NtUserSystemParametersInfo
581    fake_NtUserSetLayeredWindowAttributes
写的比较匆忙 如有问题欢迎指正~
图如果看不清, 请下载文档查看 或者点击图片放大 
****hook分析.doc

驱动文件
****driver.rar

上传的附件 1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
****hook分析.doc
****driver.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功