Windows Shellcoding - 2 : ShellExecuteA by Searching through loaded Dlls
In light of my previous success with handling windows API inside shellcode, I wanted to experiment more with what I had learnt.
Now I had a few ideas, the most prominent one was being able to use functions from Dlls other than kernel32.dll as that one provides a limited number of functions and even then they're easily detected by any Anti-Virus software.
So I decided to try getting ShellExecuteA to work, it is provided by shell32.dll and one application of windows which loads it is 'calc.exe'.
Attaching WinDbg onto calc.exe showed that the Dll is loaded quite far down into the list.
Now unlike the first two, i.e., kernel32.dll & ntdll.dll, this one does not consistently load in the same position.
As you can see in the image, it is preceded by BitDefender's dlls, in systems where there is no anti virus it might load earlier.
So I need a reliable way to search for it each time, so a search function should do it.
Given that the load order entry is in uppercase we have to search for uppercase shell32.dll, so with a little help from my python script (the same one from last shellcoding post) we get the uppercase little endian version to push.
With this on the stack, we follow a similar routine like the previous one, only difference being this one has a search function added.
The modules are loaded with their full pathname in the FullDllName field of LDR_DATA_TABLE_ENTRY at 0x20 from the base of the entry, and comparing that whole pathname would be really time consuming I decided to skip the the first 20 bytes they'd occupy.
I assemble it and grab the shellcode for testing if my hypothesis is correct.
So on plugging it in a code cave in x32dbg, I found a major error in my initial plan, Windows stores the names in unicode!
Now that presents a unique challenge, as in Unicode encoding, each character is followed by a null byte (\x00) and I can't save the name of the dll in UTF-16 without risking the null bytes messing with the shellcode.
The storage in UTF-16 also means I have to change the number of skipped bytes.
So I edit the ShellCode to get two bytes into EDI and skip the null byte.
I also increment EDI by two characters from the from the pathname, i.e., the byte + the null byte. I also altered the numbers of bytes to skip from 20 to 40, since I have to skip a null byte for each byte.
I get the bytecode and plug it into calc.exe again to verify if it worked.
So after two loops I successfully got the base address for shell32.dll, and then I just followed the same routine as last time.
Once I have all the addresses resolved, I search for 'ShellExecuteA' in the Name Pointer Table to get its position within the table. Then using that position I acquired its Ordinal Number and then the address of 'ShellExecuteA' was loaded into EAX using the Ordinal Number.
This part of the process was done using the same code I had from shellcoding 1, post so I will not be reposting it.
I then used the my nifty python script to generate the stack pushes for my command strings and then we push the arguments in accordance to the ShellExecuteA's documentation which you can find of Microsoft's Website.
So I push the arguments starting with the last one as the stack works on LIFO (Last in first out):
Once that is done I inject it into 'calc.exe' and run it with x32dbg.
After pushing, as you can see the arguments are in stack in the correct order and the address to ShellExecuteA in EAX.
Looking the monitoring report from procmon, it seems to have succeeded with flying colours.
The actual file below in SysWOW64, its in SysWOW64 since the 32 bit calc.exe is there and cmd just used the calling process's directory.
The full code is here, there are a few stray null bytes which I am working on to remove, the third post in this series should probably have one which is zero null bytes (hopefully!).
Comments
Post a Comment