Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
| ;;;;MMMMMMMMMMMMMMMMMMMMMWNXK0kxdooodddooloxO0KNWMMMMMMMMMMMMMMMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMWXOxl:;'... ...';;,,'.....;oxOKNWMMMMMMMMMMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMWXOdlc:;;;:cc::;,',lxxxxo:,....,,,:lkKWMMMMMMMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMN0dc:::loxkO0OOkxxdl:cdOOOOxoc;',lc'..';lkXWMMMMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMNkc'...';ldkkO0Oxdoc:;,,;::::cclc,:xxc,',,'';dKWMMMMMMMMMMMM | |
| ;;;;MMMMMMMMW0l,...,coddooolc;,'.... ..... .,;,cdxdl:cc,'..,dXMMMMMMMMMMM | |
| ;;;;MMMMMMMNx;....cdxdddol:;;;::cccc::::;;'.''...':looddl;'...:kNMMMMMMMMM | |
| ;;;;MMMMMMNd'...'cddxdoc::codxOO000OOOOkkxdlll,....,coxxxo:'...'oXMMMMMMMM | |
| ;;;;MMMMMNd'. .colll;,,:lddxkkdlc;;;;:::loodxo:,,'',cddxxdc,....lXMMMMMMM | |
| ;;;;MMMMNd. 'okxdl'.':looooc;'''''.......';ldddl::;,;oxxxd:'....lXMMMMMM | |
| ;;;;MMMMO, .,d0Oko' .,lddl;'',:looollll:,....;oddxo:'.,oxxxo:'....oNMMMMM | |
| ;;;;MMMWd....;xOkx; .,oOx;..;ccc:cc:;;:codc'..'lxkxc'..;oxxxl'....,kWMMMM | |
| ;;;;MMMNo....;xOkd' .:xOl'':oc;:;;:::;'.'lx:. 'oxxl,..'cdddl;'....lXMMMM | |
| ;;;;MMMXc....:xxxo. .:xkl',ll;;;,::;,;:,.,oo'. .:ddl,...,oodoc,....,OMMMM | |
| ;;;;MMMXc....,dkkd' .,oOx;,:oc,,,;;'':c,.'lo' .;ddo;...,odddl'....'xWMMM | |
| ;;;;MMMNo.. ,xOkd; ..:kOo;,:lc;,,,;:;,..:dc.. .cxxd;...,odddc'.....oNMMM | |
| ;;;;MMMWk' .,oxxdo' ..,lxkdc,,;:::::,'',cdd;...,dxkl'...cddxd:'.....oNMMM | |
| ;;;;MMMMXc....,lkkko'....,lxkxl;,''',;lodo:'...'lxxo,. 'odddo;......dWMMM | |
| ;;;;MMMMMKc....,oOOkd:. ..,:looooooolc:,... .'lddl,. .cooddc,.....,OWMMM | |
| ;;;;MMMMMWKc. .,okkkxl;.. ........... ..;cll:. .:oddxo;......cKMMMM | |
| ;;;;MMMMMMMXl....'cdxdlodl;'.. ...;col:;'. .:oodxo:......,kWMMMM | |
| ;;;;MMMMMMMMNx;....';;coxkxdol:;''',;:ccldxxxo:'....;loodxo:'......oNMMMMM | |
| ;;;;MMMMMMMMMWKd;......,cddddkkdl::ccllolc:,'.....,coodxxo:''.....cKMMMMMM | |
| ;;;;MMMMMMMMMMMWXxc,.. ..',;cloo:'',,,,'.......';:cclooc,'......:0WMMMMMM | |
| ;;;;MMMMMMMMMMMMMMN0d:.. .......,;,. .... ...,;,,;:::;'........;OWMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMWN0xl:,......';,'......,,'''',,,'..........cKWMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMMMMMWXK0Okxxkkdcc:::::::,'........... ..:KMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xool::clll:;,''........':kWMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXOxoc:;;;::::;,,'',cdONMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xdl:;;,,,;:ok0NMMMMMMMMMMMMM | |
| ;;;;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXKK000KNWMMMMMMMMMMMMMMMM | |
| ;;;;----------------------------------------------------------------------; | |
| ;;;; x86 Message Box Shellcode ; | |
| ;;;;----------------------------------------------------------------------; | |
| ;;;; Author: Forrest Orr - 2020 ; | |
| ;;;;----------------------------------------------------------------------; | |
| ;;;; Contact: forrest.orr@protonmail.com ; | |
| ;;;;----------------------------------------------------------------------; | |
| ;;;; Licensed under GNU GPLv3 ; | |
| ;;;;______________________________________________________________________; | |
| ;;;; ## Features ; | |
| ;;;; ; | |
| ;;;; ~ Dynamic module base resolution via name hash ; | |
| ;;;; ~ Dynamic export address resolution via name hash ; | |
| ;;;; ~ Export forwarding support ; | |
| ;;;; ~ Stable and tested on any version of Windows 7, 8.1 or 10 ; | |
| ;;;;______________________________________________________________________; | |
| ;%Define DEBUG | |
| %Ifdef DEBUG | |
| Global _MessageBox32 | |
| %Endif | |
| %Include "..\Include\Windows.inc" | |
| Bits 32 | |
| Section .text | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;;; MessageBoxA ;;; | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| _MessageBox32: | |
| Push Ebp | |
| Mov Ebp, Esp | |
| Push 000D4E88h ; Kernel32.dll string hash. The hashing algorithm is case insensitive (forced uppercase) | |
| Call GetModuleBase32 | |
| Push 000d5786h ; LoadLibraryA | |
| Push Eax | |
| Call ResolveExportAddress32 | |
| Push '32' | |
| Push 'User' | |
| Push Esp | |
| Call Eax | |
| Push 0006b81ah ; MessageBoxA | |
| Push Eax | |
| Call ResolveExportAddress32 | |
| Push 'd' | |
| Push 'pwne' | |
| Mov Ecx, Esp | |
| Push 'net' | |
| Push 'orr.' | |
| Push 'est-' | |
| Push 'forr' | |
| Push 'www.' | |
| Mov Edx, Esp | |
| Push 0 | |
| Push Edx | |
| Push Ecx | |
| Push 0 | |
| Call Eax | |
| Mov Esp, Ebp | |
| Pop Ebp | |
| Ret | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;;; GetModuleBase32 ;;; | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ArgdwNameHash Equ 08h | |
| GetModuleBase32: ; First parameter = the string hash of the target module base name (not full path) | |
| Push Ebp | |
| Mov Ebp, Esp | |
| Push Edi ; Walk through the load order module list in the PEB by flink until either the initial module in the list (Ntdll.dll) is reached again, or a NULL entry is identified. | |
| Push Esi | |
| Mov Esi, TIB32.pPEB | |
| FS Lodsd | |
| Mov Eax, Dword [Eax + PEB32.pLDRData] | |
| Mov Edi, Dword [Eax + PEB_LDR_DATA32.pInLoadOrderModuleList] | |
| Mov Esi, Edi ; Esi will be my moving module entry pointer, while Edi will be a static reference to the initial load order module (should always be Ntdll.dll) | |
| Xor Eax, Eax ; If the list pointer is invalid, we still need to return 0. | |
| Jmp GetModuleBase32.CheckValidModuleEntry ; Since Esi and Edi will be equal when the loop begins, skip the Ntdll check on the first iteration. | |
| .CheckNextModuleEntry: ; Esi = current module, Edi = Ntdll module. Eax will be the module base after loop exits, assuming it was ever found | |
| Cmp Edi, Esi | |
| Je GetModuleBase32.FinalModuleEntry | |
| .CheckValidModuleEntry: | |
| Test Esi, Esi | |
| Jz GetModuleBase32.FinalModuleEntry | |
| Lea Ebx, Dword [Esi + LDR_MODULE32.usBaseDllName] | |
| Test Ebx, Ebx | |
| Jz GetModuleBase32.LoadNextModuleEntry | |
| Mov Ecx, Dword [Ebx + UNICODE_STRING32.Buffer] | |
| Test Ecx, Ecx | |
| Jz GetModuleBase32.LoadNextModuleEntry | |
| Push 1 ; Unicode string boolean | |
| Push Ecx | |
| Call GetStringHash32 | |
| Cmp Eax, Dword [Ebp + ArgdwNameHash] | |
| Je GetModuleBase32.FoundTargetModule | |
| .LoadNextModuleEntry: | |
| Xor Eax, Eax ; This will ensure we return 0 in the event the target module is not found. | |
| Mov Esi, Dword [Esi + LDR_MODULE32.LoadOrderFlink] | |
| Jmp GetModuleBase32.CheckNextModuleEntry | |
| .FoundTargetModule: | |
| Mov Eax, Dword [Esi + LDR_MODULE32.pBase] | |
| .FinalModuleEntry: | |
| Pop Esi | |
| Pop Edi | |
| Mov Esp, Ebp | |
| Pop Ebp | |
| Retn 04h | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;;; ResolveExportAddress32 ;;; | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| Arg_pModuleBase32 Equ 08h | |
| Arg_dwFunctionHash Equ 0Ch | |
| pImageExportTable Equ -04h | |
| pModuleBase32 Equ -08h | |
| pImageOptionalHeader32 Equ -0Ch | |
| pImageFileHeader32 Equ -10h | |
| pdwAddressOfNames32 Equ -14h | |
| pdwAddressOfFunctions32 Equ -18h | |
| pwAddressOfNameOEdinals32 Equ -1Ch | |
| dwNumberOfAttemptedHashes Equ -20h | |
| pForwardedModuleBase Equ -24h | |
| dwFunctionAddress Equ -28h | |
| pFunctionName32 Equ -2Ch | |
| dwExportTableSize Equ -30h | |
| ForwardedFunctionName Equ -130h ; 100h is 256, clean multiple of 4 for stack alignment. | |
| ForwardedModuleName Equ -230h | |
| StackSize Equ 230h | |
| ResolveExportAddress32: | |
| Bits 32 | |
| Push Ebp | |
| Mov Ebp, Esp | |
| Sub Esp, StackSize | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Mov Dword [Ebp + pModuleBase32], Eax | |
| Mov Edx, Dword [Ebp + pModuleBase32] | |
| Add Eax, Dword [Edx + IMAGE_DOS_HEADER.e_lfanew] | |
| Add Eax, 4 | |
| Mov Dword [Ebp + pImageFileHeader32], Eax | |
| Add Eax, IMAGE_FILE_HEADER_size | |
| Mov Dword [Ebp + pImageOptionalHeader32], Eax | |
| Mov Edx, Eax | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Edx + IMAGE_OPTIONAL_HEADER32.DataDirectory] | |
| Mov Ecx, Dword [Edx + IMAGE_OPTIONAL_HEADER32.DataDirectory + 4] ; Size field in first data directory (export address table) | |
| Mov Dword [Ebp + dwExportTableSize], Ecx | |
| Mov Dword [Ebp + pImageExportTable], Eax | |
| Mov Edx, Eax | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Edx + IMAGE_EXPORT_DIRECTORY.AddressOfNames] | |
| Mov Dword [Ebp + pdwAddressOfNames32], Eax | |
| Mov Edx, Dword [Ebp + pImageExportTable] | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Edx + IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals] | |
| Mov Dword [Ebp + pwAddressOfNameOEdinals32], Eax | |
| Mov Edx, Dword [Ebp + pImageExportTable] | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Edx + IMAGE_EXPORT_DIRECTORY.AddressOfFunctions] | |
| Mov Dword [Ebp + pdwAddressOfFunctions32], Eax | |
| Xor Eax, Eax | |
| Mov Dword [Ebp + dwNumberOfAttemptedHashes], Eax | |
| Mov Dword [Ebp + dwFunctionAddress], Eax ; Initialize to 0 for failed status | |
| .GetFunctionName: | |
| Mov Eax, Dword [Ebp + pImageExportTable] | |
| Mov Eax, Dword [Eax + IMAGE_EXPORT_DIRECTORY.NumberOfNames] | |
| Cmp Eax, Dword [Ebp + dwNumberOfAttemptedHashes] | |
| Jbe ResolveExportAddress32.ReturnHash | |
| Mov Eax, Dword [Ebp + dwNumberOfAttemptedHashes] | |
| Lea Ecx, Dword [Eax * 4] | |
| Mov Edx, Dword [Ebp + pdwAddressOfNames32] | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Ecx + Edx] | |
| Mov Dword [Ebp + pFunctionName32], Eax | |
| Push 0 ; Exports are always ANSI, never Unicode. | |
| Push Eax | |
| Call GetStringHash32 | |
| Cmp Eax, Dword [Ebp + Arg_dwFunctionHash] | |
| Jnz ResolveExportAddress32.NextFunctionName | |
| Mov Eax, Dword [Ebp + dwNumberOfAttemptedHashes] | |
| Lea Edx, Dword [Eax + Eax] | |
| Mov Eax, Dword [Ebp + pwAddressOfNameOEdinals32] | |
| Movzx Eax, Word [Edx + Eax] | |
| Lea Ecx, Dword [Eax * 4] | |
| Mov Edx, Dword [Ebp + pdwAddressOfFunctions32] | |
| Mov Eax, Dword [Ebp + Arg_pModuleBase32] | |
| Add Eax, Dword [Ecx + Edx] | |
| Mov Dword [Ebp + dwFunctionAddress], Eax ; We've resolved the address of the target function. However this may be a forwarder string, not code. Check and see if the address is within the export table to determine this. | |
| Mov Ecx, Dword [Ebp + pImageExportTable] | |
| Mov Edx, Ecx | |
| Add Edx, Dword [Ebp + dwExportTableSize] | |
| Cmp Eax, Ecx | |
| Jl ResolveExportAddress32.ReturnHash ; Function address below the start of the EAT? If so it's a legit function. | |
| Cmp Eax, Edx | |
| Jge ResolveExportAddress32.ReturnHash ; Function address above the end of the EAT? If so it's a legit function in this context. | |
| Mov Dword [Ebp + dwFunctionAddress], 0 ; The function address falls within the EAT. We can assume that it is a forwarder. Extract the module/function name: <Module name (no extension)>.<Function name> | |
| Xor Ecx, Ecx ; Forwarder string counter | |
| Lea Ebx, Dword [Ebp + ForwardedModuleName] ; Initially the buffer register will point to the module name since this field comes first. | |
| .ExtractForwarder: | |
| Mov Dl, Byte [Eax + Ecx] | |
| Cmp Dl, 0 | |
| Je ResolveExportAddress32.ResolveForwarder | |
| Cmp Dl, '.' | |
| Jne ResolveExportAddress32.NextForwarderByte | |
| Mov Dword [Ebx], '.dll' ; The module name in a forwarder will not include a .dll extension. Add it so that we can generate a name hash which may match a module in the PEB loader list. | |
| Add Ebx, 4 | |
| Mov Byte [Ebx], 0 ; Finalize module name string with null terminator | |
| Lea Ebx, Dword [Ebp + ForwardedFunctionName] ; Switch the buffer register and begin building the function string | |
| Inc Ecx ; Skip the '.' seperator | |
| Jmp ResolveExportAddress32.ExtractForwarder | |
| .NextForwarderByte: | |
| Mov Byte [Ebx], Dl | |
| Inc Ecx | |
| Inc Ebx | |
| Jmp ResolveExportAddress32.ExtractForwarder | |
| .ResolveForwarder: | |
| Mov Byte [Ebx], 0 ; Finalize the function name string with a null terminator. | |
| ;Lea Edx, Dword [Ebp + ForwardedFunctionName] | |
| Lea Ebx, Dword [Ebp + ForwardedModuleName] ; Initially the buffer register will point to the module name since this field comes first. | |
| Push 0 | |
| Push Ebx | |
| Call GetStringHash32 | |
| Push Eax | |
| Call GetModuleBase32 | |
| Test Eax, Eax | |
| Jz ResolveExportAddress32.ReturnHash ; Failed to find the forwarded module in the PEB loader list. This could be because it is an API set (and these will never be in the list) or a module which simply has not been loaded yet. | |
| Mov Dword [Ebp + pForwardedModuleBase], Eax | |
| Push 0 | |
| Lea Edx, Dword [Ebp + ForwardedFunctionName] | |
| Push Edx | |
| Call GetStringHash32 | |
| Push Eax | |
| Push Dword [Ebp + pForwardedModuleBase] | |
| Call ResolveExportAddress32 | |
| Mov Dword [Ebp + dwFunctionAddress], Eax | |
| Jmp ResolveExportAddress32.ReturnHash | |
| .NextFunctionName: | |
| Lea Eax, Dword [Ebp + dwNumberOfAttemptedHashes] | |
| Inc Dword [Eax] | |
| Jmp ResolveExportAddress32.GetFunctionName | |
| .ReturnHash: | |
| Mov Eax, Dword [Ebp + dwFunctionAddress] | |
| Mov Esp, Ebp | |
| Pop Ebp | |
| Retn 08h | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;;; GetStringHash32 ;;; | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| Arg_pTargetStr Equ 08h | |
| Arg_bUnicode Equ 0Ch | |
| GetStringHash32: ; First parameter = pointer to string, second parameter = boolean yes unicode or no unicode | |
| Push Ebp | |
| Mov Ebp, Esp | |
| Push Edi | |
| Mov Ecx, Dword [Ebp + Arg_pTargetStr] | |
| Mov Edi, Dword [Ebp + Arg_bUnicode] | |
| Xor Ebx, Ebx | |
| .HashNextByte: | |
| Cmp Byte [Ecx], 0 | |
| Je GetStringHash32.HashGenerated | |
| Movzx Eax, Byte [Ecx] | |
| Or Al, 60h | |
| Movzx Edx, Al | |
| Add Ebx, Edx | |
| Shl Ebx, 1 | |
| Inc Ecx | |
| Test Edi, Edi | |
| Jz GetStringHash32.HashNextByte | |
| Inc Ecx ; Skip an extra byte if this is a unicode string | |
| Jmp GetStringHash32.HashNextByte | |
| .HashGenerated: | |
| Mov Eax, Ebx | |
| Pop Edi | |
| Mov Esp, Ebp | |
| Pop Ebp | |
| Retn 08h | |
| End: |