Demo中的例子是找 PspTerminateProcess, 基于WinXp的.
虚拟机是Win7X86家庭普通版, ring0中没有这个API.
kd> u PspTerminateProcess Couldn't resolve error at 'PspTerminateProcess'
kd> x nt!*terminate* 83f090cd nt!KeTerminateThread = <no type information> 8404736f nt!NtTerminateJobObject = <no type information> 84140ac2 nt!SeUnregisterLogonSessionTerminatedRoutine = <no type information> 83e54220 nt!_imp__ClfsTerminateReadLog = <no type information> 8405d7e8 nt!PsTerminateSystemThread = <no type information> 83e90428 nt!ZwTerminateJobObject = <no type information> 840a2fe7 nt!PspTerminateThreadByPointer = <no type information> 840afbf1 nt!PspTerminateAllThreads = <no type information> 83f5ff1d nt!SmKmStoreTerminateWorker = <no type information> 83ebaddf nt!MiTerminateWsle = <no type information> 840e58d9 nt!PsTerminateProcess = <no type information> 8413209c nt!NtRegisterThreadTerminatePort = <no type information> 840af9bf nt!NtTerminateProcess = <no type information> 83f6a23e nt!InbvPortTerminate = <no type information> 840cd334 nt!NtTerminateThread = <no type information> 83e8fd5c nt!ZwRegisterThreadTerminatePort = <no type information> 83e9043c nt!ZwTerminateProcess = <no type information> 83f5698b nt!SMKM_STORE_MGR<SM_TRAITS>::SmStoreTerminate = <no type information> 83fe75fb nt!SeRegisterLogonSessionTerminatedRoutine = <no type information> 83e627e5 nt!ClfsTerminateReadLog = <no type information> 83e90450 nt!ZwTerminateThread = <no type information> 840473c6 nt!PspTerminateAllProcessesInJob = <no type information>
kd> uf nt!PsTerminateProcess nt!PsTerminateProcess: 840e58d9 8bff mov edi,edi 840e58db 55 push ebp 840e58dc 8bec mov ebp,esp 840e58de 51 push ecx 840e58df 51 push ecx 840e58e0 53 push ebx 840e58e1 56 push esi 840e58e2 648b3524010000 mov esi,dword ptr fs:[124h] 840e58e9 66ff8e84000000 dec word ptr [esi+84h] 840e58f0 57 push edi 840e58f1 c745fc01000000 mov dword ptr [ebp-4],1 840e58f8 6a08 push 8 840e58fa 5a pop edx 840e58fb 8db970020000 lea edi,[ecx+270h] 840e5901 8b07 mov eax,dword ptr [edi] nt!PsTerminateProcess+0x2a: 840e5903 8bd8 mov ebx,eax 840e5905 0bda or ebx,edx 840e5907 f00fb11f lock cmpxchg dword ptr [edi],ebx 840e590b 75f6 jne nt!PsTerminateProcess+0x2a (840e5903) nt!PsTerminateProcess+0x34: 840e590d 84c2 test dl,al 840e590f 7409 je nt!PsTerminateProcess+0x41 (840e591a) nt!PsTerminateProcess+0x38: 840e5911 c745fc03000000 mov dword ptr [ebp-4],3 840e5918 eb0e jmp nt!PsTerminateProcess+0x4f (840e5928) nt!PsTerminateProcess+0x41: 840e591a a900000040 test eax,40000000h 840e591f 7407 je nt!PsTerminateProcess+0x4f (840e5928) nt!PsTerminateProcess+0x48: 840e5921 c745fc05000000 mov dword ptr [ebp-4],5 nt!PsTerminateProcess+0x4f: 840e5928 ff75fc push dword ptr [ebp-4] 840e592b ff7508 push dword ptr [ebp+8] 840e592e 56 push esi 840e592f 51 push ecx 840e5930 e8bca2fcff call nt!PspTerminateAllThreads (840afbf1) 840e5935 8bf8 mov edi,eax 840e5937 66ff8684000000 inc word ptr [esi+84h] 840e593e 0fb78684000000 movzx eax,word ptr [esi+84h] 840e5945 6685c0 test ax,ax 840e5948 7516 jne nt!PsTerminateProcess+0x87 (840e5960) nt!PsTerminateProcess+0x71: 840e594a 8d4640 lea eax,[esi+40h] 840e594d 3900 cmp dword ptr [eax],eax 840e594f 740f je nt!PsTerminateProcess+0x87 (840e5960) nt!PsTerminateProcess+0x78: 840e5951 6683be8600000000 cmp word ptr [esi+86h],0 840e5959 7505 jne nt!PsTerminateProcess+0x87 (840e5960) nt!PsTerminateProcess+0x82: 840e595b e8395bd9ff call nt!KiCheckForKernelApcDelivery (83e7b499) nt!PsTerminateProcess+0x87: 840e5960 8bc7 mov eax,edi 840e5962 5f pop edi 840e5963 5e pop esi 840e5964 5b pop ebx 840e5965 c9 leave 840e5966 c20400 ret 4
取API特征码
kd> dd nt!PsTerminateProcess L4 840e58d9 8b55ff8b 535151ec 358b6456 00000124
/** kd> dd nt!PsTerminateProcess L4 840e58d9 8b55ff8b 535151ec 358b6456 00000124 */ ULONG ulApiSignature_PsTerminateProcess[] = {0x8b55ff8b, 0x535151ec, 0x358b6456, 0x00000124};
NTSTATUS PsTerminateProcess( IN OUT PEPROCESS pEProcessHandle, IN NTSTATUS exitStatus);
在驱动层代码中找ApiSignature封装了一个函数.
BOOLEAN MmIsAddressValid_Util(ULONG ulMemAddr) { /// 地址有效才去操作, MmIsAddressValid只能检测到一个字节. /// 这样检测4次好使, 原来读无效的内存地址被忽略 size_t nIndex = 0; for (nIndex = 0; nIndex < sizeof(ULONG); nIndex++) { if (!MmIsAddressValid((BYTE *)ulMemAddr + nIndex)) return FALSE; } return TRUE; } BOOLEAN FindApiSignature(ULONG ulMemAddr, ULONG * pulApiSignature, size_t nCntApiSignature) { BOOLEAN bRc = FALSE; size_t nIndex = 0; /// 找到的API特征码的内容个数, 如果等于nCntApiSignature, 说明完全匹配特征码 size_t nFindCnt = 0; if (NULL == pulApiSignature) return FALSE; for (nIndex = 0; nIndex < nCntApiSignature; nIndex++) { if ((!MmIsAddressValid_Util(ulMemAddr)) || (*((ULONG *)ulMemAddr + nIndex) != *(pulApiSignature + nIndex))) { break; } nFindCnt ++; } bRc = (nFindCnt == nCntApiSignature); if (bRc) DbgPrint("find Api Signature\r\n"); return bRc; }
for (ulIndex = curAddr; ulIndex < (ntosknlEndAddr - sizeof(ulApiSignature)); ulIndex++) { if (FindApiSignature(ulIndex, ulApiSignature, sizeof(ulApiSignature) / sizeof(ULONG))) { retAddr=ulIndex; DbgPrint("GetFunctionAddressFromKernelMemory adress is:%x",retAddr); KeLowerIrql(irqlOld); return (PVOID)retAddr; } }
实验发现: 用16Bytes的特征码不行, Win7X86下要32Bytes的特征码才靠谱.
ULONG ulApiSignature[] = { 0x8b55ff8b, 0x535151ec, 0x358b6456, 0x00000124, 0x848eff66, 0x57000000, 0x01fc45c7, 0x6a000000};