原文链接:
“ 通过删除杀软或EDR的“创建进程通知回调”、“创建线程通知回调”、“加载镜像通知回调”、“注册表通知回调”,极大的消弱杀软或EDR的动态查杀能力。”
本文属于以下文章和项目的复现和升华。
文章:
(https://mp.weixin.qq.com/s/jva2d8nLz6ti8fLTR0O-wQ)
https://br-sn.github.io/Removing-Kernel-Callbacks-Using-Signed-Drivers/
项目:
https://github.com/br-sn/CheekyBlinder
https://github.com/lawiet47/STFUEDR
01
—
杀软或EDR内核回调简介
Windows x64 系统中,由于 PatchGuard 的限制,杀软或EDR正常情况下,几乎不能通过 hook 的方式,完成其对恶意软件的监控和查杀。那怎么办呢?别急,微软为我们提供了其他的方法,完成此类功能,那就是系统回调机制。比如本文提到的“创建进程通知回调”、“创建线程通知回调”、“加载镜像通知回调”、“注册表通知回调”等等。
在恶意软件和杀软 攻与防的对抗中,二者经过激烈的较量,完成了螺旋式的上升变革,给我们的感觉是,杀软越来越强大了,我们的网络环境越来越安全了。
02
—
删除杀软回调项目简介
github 上有两个比较经典的项目,可以完成删除杀软回调的功能,项目如下所示:
https://github.com/br-sn/CheekyBlinder
https://github.com/lawiet47/STFUEDR
这些项目主要完成了三大功能:
利用合法驱动读取或修改内核数据;
寻找“创建进程通知回调”、“创建线程通知回调”、“加载镜像通知回调”、“注册表通知回调”内核数组地址;
将杀软或EDR驱动对应的回调数组中的某个元素,置 0 或删除;
这里需要注意的是,“创建进程通知回调”、“创建线程通知回调”、“加载镜像通知回调”是正常的数组,而“注册表通知回调”是一个双向循环链表。
下面简单介绍一下,上述四大回调数组内核地址的寻找方法和删除杀软回调的方法。
使用工具:windbg preview
系统环境:Windows 1809 x64
03
—
创建进程回调数组定位
// 1. 由 PsSetCreateProcessNotifyRoutine 定位 nt!PspSetCreateProcessNotifyRoutine 地址
0: kd> uf PsSetCreateProcessNotifyRoutine
nt!PsSetCreateProcessNotifyRoutine:
fffff802`6ca90570 4883ec28 sub rsp,28h
fffff802`6ca90574 8ac2 mov al,dl
fffff802`6ca90576 33d2 xor edx,edx
fffff802`6ca90578 84c0 test al,al
fffff802`6ca9057a 0f95c2 setne dl
fffff802`6ca9057d e80e010000 call nt!PspSetCreateProcessNotifyRoutine (fffff802`6ca90690)
fffff802`6ca90582 4883c428 add rsp,28h
fffff802`6ca90586 c3 ret
// 2. 定位 nt!PspCreateProcessNotifyRoutine 数组地址
0: kd> uf nt!PspSetCreateProcessNotifyRoutine
nt!PspSetCreateProcessNotifyRoutine:
fffff802`6ca90690 48895c2408 mov qword ptr [rsp+8],rbx
fffff802`6ca90695 48896c2410 mov qword ptr [rsp+10h],rbp
fffff802`6ca9069a 4889742418 mov qword ptr [rsp+18h],rsi
fffff802`6ca9069f 57 push rdi
fffff802`6ca906a0 4154 push r12
fffff802`6ca906a2 4155 push r13
fffff802`6ca906a4 4156 push r14
fffff802`6ca906a6 4157 push r15
... ...
nt!PspSetCreateProcessNotifyRoutine+0x49:
fffff802`6ca906d9 488bd7 mov rdx,rdi
fffff802`6ca906dc 498bcf mov rcx,r15
fffff802`6ca906df e8a4000000 call nt!ExAllocateCallBack (fffff802`6ca90788)
fffff802`6ca906e4 488bf8 mov rdi,rax
fffff802`6ca906e7 4885c0 test rax,rax
fffff802`6ca906ea 0f845b890c00 je nt!PspSetCreateProcessNotifyRoutine+0xc89bb (fffff802`6cb5904b) Branch
nt!PspSetCreateProcessNotifyRoutine+0x60:
fffff802`6ca906f0 33db xor ebx,ebx
fffff802`6ca906f2 4c8d2d375dddff lea r13,[nt!PspCreateProcessNotifyRoutine (fffff802`6c866430)]
nt!PspSetCreateProcessNotifyRoutine+0x69:
fffff802`6ca906f9 488d0cdd00000000 lea rcx,[rbx*8]
fffff802`6ca90701 4533c0 xor r8d,r8d
fffff802`6ca90704 4903cd add rcx,r13
fffff802`6ca90707 488bd7 mov rdx,rdi
fffff802`6ca9070a e86dd5aeff call nt!ExCompareExchangeCallBack (fffff802`6c57dc7c)
fffff802`6ca9070f 84c0 test al,al
fffff802`6ca90711 750c jne nt!PspSetCreateProcessNotifyRoutine+0x8f (fffff802`6ca9071f) Branch
// 3. 显示回调数组
0: kd> dq fffff802`6c866430
fffff802`6c866430 ffffbb83`fc851a8f ffffbb83`fc9febaf
fffff802`6c866440 ffffbb83`fe0e8b7f ffffbb83`fe0e8def
fffff802`6c866450 ffffbb83`fe413f0f ffffbb83`fe43612f
fffff802`6c866460 ffffbb83`fe436bdf ffffbb83`fc9feccf
fffff802`6c866470 ffffbb83`fe4366cf ffffbb83`fe436b7f
fffff802`6c866480 ffffbb83`fe436f3f ffffbb83`fe52133f
fffff802`6c866490 ffffbb83`fe521f6f ffffbb83`fe4be96f
fffff802`6c8664a0 ffffbb84`01737c3f 00000000`00000000
0: kd> dq
fffff802`6c8664b0 00000000`00000000 00000000`00000000
fffff802`6c8664c0 00000000`00000000 00000000`00000000
fffff802`6c8664d0 00000000`00000000 00000000`00000000
fffff802`6c8664e0 00000000`00000000 00000000`00000000
fffff802`6c8664f0 00000000`00000000 00000000`00000000
fffff802`6c866500 00000000`00000000 00000000`00000000
fffff802`6c866510 00000000`00000000 00000000`00000000
fffff802`6c866520 00000000`00000000 00000000`00000000
// 4. 取出回调数组第一个数据
0: kd> dq (ffffbb83`fc851a8f>>4)<<4
ffffbb83`fc851a80 00000000`00000020 fffff800`704d8230
ffffbb83`fc851a90 00000000`00000000 00000000`00000000
ffffbb83`fc851aa0 6e497350`02030000 00000000`00000000
ffffbb83`fc851ab0 00000000`00100010 ffffbb83`fc851ac0
ffffbb83`fc851ac0 00690067`00650052 00790072`00740073
ffffbb83`fc851ad0 6e496c41`02030000 00000000`00000000
ffffbb83`fc851ae0 00000001`00060000 ffffbb83`fc851ae8
ffffbb83`fc851af0 ffffbb83`fc851ae8 00790072`00740073
// 5. 上述数据中第 2 个 8 字节 指针(回调函数) 所在模块
0: kd> lm a fffff800`704d8230
Browse full module list
start end module name
fffff800`704b0000 fffff800`70505000 360qpesv64 (no symbols)
04
—
创建线程回调数组定位
方法一:
// 1. 由 PsSetCreateThreadNotifyRoutine 定位 nt!PspSetCreateThreadNotifyRoutine 地址
0: kd> uf PsSetCreateThreadNotifyRoutine
nt!PsSetCreateThreadNotifyRoutine:
fffff805`2e2a4350 4883ec28 sub rsp,28h
fffff805`2e2a4354 33d2 xor edx,edx
fffff805`2e2a4356 e865000000 call nt!PspSetCreateThreadNotifyRoutine (fffff805`2e2a43c0)
fffff805`2e2a435b 4883c428 add rsp,28h
fffff805`2e2a435f c3 ret
// 2. 定位 nt!PspCreateThreadNotifyRoutine 数组地址
0: kd> uf nt!PspSetCreateThreadNotifyRoutine
nt!PspSetCreateThreadNotifyRoutine:
fffff805`2e2a43c0 48895c2408 mov qword ptr [rsp+8],rbx
fffff805`2e2a43c5 4889742410 mov qword ptr [rsp+10h],rsi
fffff805`2e2a43ca 57 push rdi
fffff805`2e2a43cb 4883ec20 sub rsp,20h
fffff805`2e2a43cf 8bf2 mov esi,edx
fffff805`2e2a43d1 8bd2 mov edx,edx
fffff805`2e2a43d3 e8b0030000 call nt!ExAllocateCallBack (fffff805`2e2a4788)
fffff805`2e2a43d8 488bf8 mov rdi,rax
fffff805`2e2a43db 4885c0 test rax,rax
fffff805`2e2a43de 0f842e8b0c00 je nt!PspSetCreateThreadNotifyRoutine+0xc8b52 (fffff805`2e36cf12) Branch
nt!PspSetCreateThreadNotifyRoutine+0x24:
fffff805`2e2a43e4 33db xor ebx,ebx
nt!PspSetCreateThreadNotifyRoutine+0x26:
fffff805`2e2a43e6 488d0d435cddff lea rcx,[nt!PspCreateThreadNotifyRoutine (fffff805`2e07a030)]
fffff805`2e2a43ed 4533c0 xor r8d,r8d
fffff805`2e2a43f0 488d0cd9 lea rcx,[rcx+rbx*8]
fffff805`2e2a43f4 488bd7 mov rdx,rdi
fffff805`2e2a43f7 e880d8aeff call nt!ExCompareExchangeCallBack (fffff805`2dd91c7c)
fffff805`2e2a43fc 84c0 test al,al
fffff805`2e2a43fe 7436 je nt!PspSetCreateThreadNotifyRoutine+0x76 (fffff805`2e2a4436) Branch
nt!PspSetCreateThreadNotifyRoutine+0x40:
fffff805`2e2a4400 40f6c601 test sil,1
fffff805`2e2a4404 0f85128b0c00 jne nt!PspSetCreateThreadNotifyRoutine+0xc8b5c (fffff805`2e36cf1c) Branch
// 3. 显示回调数组
0: kd> dq nt!PspCreateThreadNotifyRoutine
fffff805`2e07a030 ffffbb8f`d044ab7f ffffbb8f`d368fdbf
fffff805`2e07a040 00000000`00000000 00000000`00000000
fffff805`2e07a050 00000000`00000000 00000000`00000000
fffff805`2e07a060 00000000`00000000 00000000`00000000
fffff805`2e07a070 00000000`00000000 00000000`00000000
fffff805`2e07a080 00000000`00000000 00000000`00000000
fffff805`2e07a090 00000000`00000000 00000000`00000000
fffff805`2e07a0a0 00000000`00000000 00000000`00000000
// 4. 取出回调数组第一个数据
0: kd> dq (ffffbb8f`d044ab7f>>4)<<4
ffffbb8f`d044ab70 00000000`00000020 fffff805`2ecdd72c
ffffbb8f`d044ab80 00000000`00000000 e8f10366`0081e800
ffffbb8f`d044ab90 72724d46`02030000 66d18b66`00218c0f
ffffbb8f`d044aba0 ffffbb8f`cee83200 ffffbb8f`cee831f0
ffffbb8f`d044abb0 00000002`00000040 c82b66c4`eb586643
ffffbb8f`d044abc0 20206f49`02032b00 8a67c92b`66c3c02b
ffffbb8f`d044abd0 00690072`0044005c 005c0072`00650076
ffffbb8f`d044abe0 00610072`006d0076 006b0073`00640077
// 5. 上述数据中 第 2 个 8字节 指针(回调函数) 所在模块
0: kd> lm a fffff805`2ecdd72c
Browse full module list
start end module name
fffff805`2ecb0000 fffff805`2ed93000 360FsFlt (deferred)
方法二:
// 1. 由 PsRemoveCreateThreadNotifyRoutine 定位 nt!PspCreateThreadNotifyRoutine 数组地址
0: kd> uf PsRemoveCreateThreadNotifyRoutine
nt!PsRemoveCreateThreadNotifyRoutine:
fffff805`2e42d460 48895c2408 mov qword ptr [rsp+8],rbx
fffff805`2e42d465 48896c2410 mov qword ptr [rsp+10h],rbp
fffff805`2e42d46a 4889742418 mov qword ptr [rsp+18h],rsi
fffff805`2e42d46f 57 push rdi
fffff805`2e42d470 4156 push r14
fffff805`2e42d472 4157 push r15
fffff805`2e42d474 4883ec20 sub rsp,20h
fffff805`2e42d478 65488b342588010000 mov rsi,qword ptr gs:[188h]
fffff805`2e42d481 4183cfff or r15d,0FFFFFFFFh
fffff805`2e42d485 4c8bf1 mov r14,rcx
fffff805`2e42d488 664401bee4010000 add word ptr [rsi+1E4h],r15w
fffff805`2e42d490 33ff xor edi,edi
nt!PsRemoveCreateThreadNotifyRoutine+0x32:
fffff805`2e42d492 488d0d97cbc4ff lea rcx,[nt!PspCreateThreadNotifyRoutine (fffff805`2e07a030)]
fffff805`2e42d499 488d2cf9 lea rbp,[rcx+rdi*8]
fffff805`2e42d49d 488bcd mov rcx,rbp
fffff805`2e42d4a0 e81b4286ff call nt!ExReferenceCallBackBlock (fffff805`2dc916c0)
fffff805`2e42d4a5 488bd8 mov rbx,rax
fffff805`2e42d4a8 4885c0 test rax,rax
fffff805`2e42d4ab 7429 je nt!PsRemoveCreateThreadNotifyRoutine+0x76 (fffff805`2e42d4d6) Branch
nt!PsRemoveCreateThreadNotifyRoutine+0x4d:
fffff805`2e42d4ad 488bc8 mov rcx,rax
fffff805`2e42d4b0 e8cb4286ff call nt!ExGetCallBackBlockRoutine (fffff805`2dc91780)
fffff805`2e42d4b5 493bc6 cmp rax,r14
fffff805`2e42d4b8 7511 jne nt!PsRemoveCreateThreadNotifyRoutine+0x6b (fffff805`2e42d4cb) Branch
05
—
加载镜像回调数组定位
方法一:
// 1. 由 PsSetLoadImageNotifyRoutine 定位 nt!PsSetLoadImageNotifyRoutineEx 地址
0: kd> uf PsSetLoadImageNotifyRoutine
nt!PsSetLoadImageNotifyRoutine:
fffff805`2e2a4370 4883ec28 sub rsp,28h
fffff805`2e2a4374 33d2 xor edx,edx
fffff805`2e2a4376 e8d5000000 call nt!PsSetLoadImageNotifyRoutineEx (fffff805`2e2a4450)
fffff805`2e2a437b 4883c428 add rsp,28h
fffff805`2e2a437f c3 ret
// 2. 定位 nt!PspLoadImageNotifyRoutine 数组地址
0: kd> uf nt!PsSetLoadImageNotifyRoutineEx
nt!PsSetLoadImageNotifyRoutineEx:
fffff805`2e2a4450 48895c2418 mov qword ptr [rsp+18h],rbx
fffff805`2e2a4455 4889742420 mov qword ptr [rsp+20h],rsi
fffff805`2e2a445a 57 push rdi
fffff805`2e2a445b 4883ec70 sub rsp,70h
fffff805`2e2a445f 488b058a37d8ff mov rax,qword ptr [nt!_security_cookie (fffff805`2e027bf0)]
fffff805`2e2a4466 4833c4 xor rax,rsp
fffff805`2e2a4469 4889442460 mov qword ptr [rsp+60h],rax
fffff805`2e2a446e 488bf1 mov rsi,rcx
fffff805`2e2a4471 48f7c2feffffff test rdx,0FFFFFFFFFFFFFFFEh
fffff805`2e2a4478 0f85c28a0c00 jne nt!PsSetLoadImageNotifyRoutineEx+0xc8af0 (fffff805`2e36cf40) Branch
nt!PsSetLoadImageNotifyRoutineEx+0x2e:
fffff805`2e2a447e e805030000 call nt!ExAllocateCallBack (fffff805`2e2a4788)
fffff805`2e2a4483 488bf8 mov rdi,rax
fffff805`2e2a4486 4885c0 test rax,rax
fffff805`2e2a4489 0f84c58a0c00 je nt!PsSetLoadImageNotifyRoutineEx+0xc8b04 (fffff805`2e36cf54) Branch
nt!PsSetLoadImageNotifyRoutineEx+0x3f:
fffff805`2e2a448f 33db xor ebx,ebx
nt!PsSetLoadImageNotifyRoutineEx+0x41:
fffff805`2e2a4491 488d0d985dddff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff805`2e07a230)]
fffff805`2e2a4498 4533c0 xor r8d,r8d
fffff805`2e2a449b 488d0cd9 lea rcx,[rcx+rbx*8]
fffff805`2e2a449f 488bd7 mov rdx,rdi
fffff805`2e2a44a2 e8d5d7aeff call nt!ExCompareExchangeCallBack (fffff805`2dd91c7c)
fffff805`2e2a44a7 84c0 test al,al
fffff805`2e2a44a9 0f849f000000 je nt!PsSetLoadImageNotifyRoutineEx+0xfe (fffff805`2e2a454e) Branch
// 3. 显示回调数组
0: kd> dq nt!PspLoadImageNotifyRoutine
fffff805`2e07a230 ffffbb8f`ceef9bdf ffffbb8f`d044a6ff
fffff805`2e07a240 ffffbb8f`d055fa8f ffffbb8f`d055fc6f
fffff805`2e07a250 00000000`00000000 00000000`00000000
fffff805`2e07a260 00000000`00000000 00000000`00000000
fffff805`2e07a270 00000000`00000000 00000000`00000000
fffff805`2e07a280 00000000`00000000 00000000`00000000
fffff805`2e07a290 00000000`00000000 00000000`00000000
fffff805`2e07a2a0 00000000`00000000 00000000`00000000
// 4. 取出回调数组第一个数据
0: kd> dq (ffffbb8f`ceef9bdf>>4)<<4
ffffbb8f`ceef9bd0 00000000`00000020 fffff805`317e37a4
ffffbb8f`ceef9be0 00000000`00000000 ffffbb8f`ceef9be0
ffffbb8f`ceef9bf0 434f444e`02030000 00000000`00000001
ffffbb8f`ceef9c00 ffffbb8f`d387b8c0 ffffbb8f`d387b8c0
ffffbb8f`ceef9c10 00000002`00000040 00000000`00000001
ffffbb8f`ceef9c20 20206f49`02030000 a2aba245`696ddc74
ffffbb8f`ceef9c30 00690072`0044005c 005c0072`00650076
ffffbb8f`ceef9c40 00550041`00450050 00000000`00480054
// 5. 上述数据中 第 2 个 8 字节指针(回调函数) 所在模块
0: kd> lm a fffff805`317e37a4
Browse full module list
start end module name
fffff805`317d0000 fffff805`317fb000 DsArk64 (deferred)
方法二:
// 1. 由 PsRemoveLoadImageNotifyRoutine 定位 nt!PspLoadImageNotifyRoutine 数组地址
0: kd> uf PsRemoveLoadImageNotifyRoutine
nt!PsRemoveLoadImageNotifyRoutine:
fffff805`2e42d560 48895c2408 mov qword ptr [rsp+8],rbx
fffff805`2e42d565 48896c2410 mov qword ptr [rsp+10h],rbp
fffff805`2e42d56a 4889742418 mov qword ptr [rsp+18h],rsi
fffff805`2e42d56f 57 push rdi
fffff805`2e42d570 4156 push r14
fffff805`2e42d572 4157 push r15
fffff805`2e42d574 4883ec20 sub rsp,20h
fffff805`2e42d578 65488b342588010000 mov rsi,qword ptr gs:[188h]
fffff805`2e42d581 4183cfff or r15d,0FFFFFFFFh
fffff805`2e42d585 4c8bf1 mov r14,rcx
fffff805`2e42d588 664401bee4010000 add word ptr [rsi+1E4h],r15w
fffff805`2e42d590 33ff xor edi,edi
nt!PsRemoveLoadImageNotifyRoutine+0x32:
fffff805`2e42d592 488d0d97ccc4ff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff805`2e07a230)]
fffff805`2e42d599 488d2cf9 lea rbp,[rcx+rdi*8]
fffff805`2e42d59d 488bcd mov rcx,rbp
fffff805`2e42d5a0 e81b4186ff call nt!ExReferenceCallBackBlock (fffff805`2dc916c0)
fffff805`2e42d5a5 488bd8 mov rbx,rax
fffff805`2e42d5a8 4885c0 test rax,rax
fffff805`2e42d5ab 7429 je nt!PsRemoveLoadImageNotifyRoutine+0x76 (fffff805`2e42d5d6) Branch
nt!PsRemoveLoadImageNotifyRoutine+0x4d:
fffff805`2e42d5ad 488bc8 mov rcx,rax
fffff805`2e42d5b0 e8cb4186ff call nt!ExGetCallBackBlockRoutine (fffff805`2dc91780)
fffff805`2e42d5b5 493bc6 cmp rax,r14
fffff805`2e42d5b8 7511 jne nt!PsRemoveLoadImageNotifyRoutine+0x6b (fffff805`2e42d5cb) Branch
06
—
注册表通知回调数组定位
// 仅 CmUnRegisterCallback 可以定位
// 1. 由 CmUnRegisterCallback 定位 nt!CallbackListHead 链表地址
0: kd> uf CmUnRegisterCallback
nt!CmUnRegisterCallback:
fffff805`2e38bd50 4c8bdc mov r11,rsp
fffff805`2e38bd53 53 push rbx
fffff805`2e38bd54 56 push rsi
fffff805`2e38bd55 57 push rdi
fffff805`2e38bd56 4154 push r12
fffff805`2e38bd58 4155 push r13
fffff805`2e38bd5a 4156 push r14
fffff805`2e38bd5c 4157 push r15
fffff805`2e38bd5e 4881ec80000000 sub rsp,80h
fffff805`2e38bd65 488bd9 mov rbx,rcx
fffff805`2e38bd68 be0d0000c0 mov esi,0C000000Dh
fffff805`2e38bd6d 89b424d8000000 mov dword ptr [rsp+0D8h],esi
fffff805`2e38bd74 33c0 xor eax,eax
fffff805`2e38bd76 498943b0 mov qword ptr [r11-50h],rax
fffff805`2e38bd7a 498943b8 mov qword ptr [r11-48h],rax
fffff805`2e38bd7e 498943c0 mov qword ptr [r11-40h],rax
fffff805`2e38bd82 49214380 and qword ptr [r11-80h],rax
fffff805`2e38bd86 65488b042588010000 mov rax,qword ptr gs:[188h]
fffff805`2e38bd8f 4183ccff or r12d,0FFFFFFFFh
fffff805`2e38bd93 664401a0e4010000 add word ptr [rax+1E4h],r12w
fffff805`2e38bd9b 33d2 xor edx,edx
fffff805`2e38bd9d 4c8d35ecf3ccff lea r14,[nt!CmpCallbackListLock (fffff805`2e05b190)]
fffff805`2e38bda4 498bce mov rcx,r14
fffff805`2e38bda7 e894f094ff call nt!ExAcquirePushLockExclusiveEx (fffff805`2dcdae40)
fffff805`2e38bdac 41bf00000080 mov r15d,80000000h
nt!CmUnRegisterCallback+0x62:
fffff805`2e38bdb2 4533c0 xor r8d,r8d
fffff805`2e38bdb5 488d542438 lea rdx,[rsp+38h]
fffff805`2e38bdba 488d0ddff3ccff lea rcx,[nt!CallbackListHead (fffff805`2e05b1a0)]
fffff805`2e38bdc1 e82a94e1ff call nt!CmListGetNextElement (fffff805`2e1a51f0)
fffff805`2e38bdc6 488bf8 mov rdi,rax
fffff805`2e38bdc9 4889442440 mov qword ptr [rsp+40h],rax
fffff805`2e38bdce 4885c0 test rax,rax
fffff805`2e38bdd1 0f84cf000000 je nt!CmUnRegisterCallback+0x156 (fffff805`2e38bea6) Branch
// 2. 显示 CMREG_CALLBACK 结构(nt!CallbackListHead)
0: kd> dq nt!CallbackListHead
fffff805`2e05b1a0 ffff9705`3572b420 ffff9705`3572ba20
fffff805`2e05b1b0 00000000`00000000 01d9e206`c817750c
fffff805`2e05b1c0 fffff805`2e05b1c0 fffff805`2e05b1c0
fffff805`2e05b1d0 00000000`00000000 00000000`00000000
fffff805`2e05b1e0 00000000`00060001 fffff805`2e05b1e8
fffff805`2e05b1f0 fffff805`2e05b1e8 00000000`00000000
fffff805`2e05b200 00000000`00060001 fffff805`2e05b208
fffff805`2e05b210 fffff805`2e05b208 00000000`00000000
// 3. 显示 nt!CallbackListHead 下一个结点
0: kd> dq ffff9705`3572ba20
ffff9705`3572ba20 fffff805`2e05b1a0 ffff9705`35449660
ffff9705`3572ba30 00000000`00000000 01d9e206`c817750b
ffff9705`3572ba40 00000000`00000000 fffff805`3015c728
ffff9705`3572ba50 00000000`000c000c ffff9705`3572a530
ffff9705`3572ba60 ffff9705`3572ba60 ffff9705`3572ba60
ffff9705`3572ba70 74705041`03060000 00000000`00000000
ffff9705`3572ba80 ffff9705`35729ae0 00000000`00000000
ffff9705`3572ba90 00000000`00000000 00000000`00000000
// 4. 偏移 0x28 位置 的 8 字节指针(回调函数)所在模块
0: kd> lm a fffff805`3015c728
Browse full module list
start end module name
fffff805`30150000 fffff805`301a5000 360qpesv64 (deferred)
07
—
删除杀软回调的方法
删除上述四大系统回调的方法被分为两类,“创建进程通知回调”、“创建线程通知回调”、“加载镜像通知回调”被分为一类,为数组类;“注册表通知回调”被分为一类,为双向循环链表类,以下简称链表类。
数组类删除方法是:找到驱动对应数组中的元素,将该元素内核地址赋值为 0;
链表类删除方法是:找到驱动对应的链表中的结点,利用数据结构中双向循环链表删除结点的方法,删除杀软驱动对应的结点。
这里需要注意,数组类中:
“创建进程通知回调”、“创建线程通知回调”,在 win7 及以上的 个人系统和 Server 系统中,通常情况下,数组大小为 64 个元素;而“加载镜像通知回调”中,通常情况下,win10 全系列及以上,数组大小为 64 个元素,win7-7601、win8-9200、win8.1-9600系统中,可能为 8 个或 64 个元素,为不定值,相关资料可以参考微软官方文档,解决方法是,通过 nt!PspLoadImageNotifyRoutineCount 确定当前注册回调个数。
08
—
删除杀软回调效果
09
—
备注
如果,需要该项目 Windows 全版本兼容,则需要将所有版本的特征码一一找出进行总结适配,下面有一个github项目可以节省你很多时间。
https://github.com/bigbang95/ntoskrnl
10
—
参考链接
(https://mp.weixin.qq.com/s/jva2d8nLz6ti8fLTR0O-wQ)
https://br-sn.github.io/Removing-Kernel-Callbacks-Using-Signed-Drivers/
项目:
https://github.com/br-sn/CheekyBlinder
https://github.com/lawiet47/STFUEDR
11
—
声明
本文所述方法,仅供安全研究使用。凡擅自用于违法用途,将被追究法律责任。其违法行为均与本人无关。特此声明!