Recently I wrote a piece of malware for a memory forensics course I was teaching at Southern Oregon University. My intention was to write a sample that correlated with the back end of the courses, GUI artifacts, persistence the usage of IDA. I decided that I wanted to obfuscate the majority of Windows API calls I needed to use using shellcode tactics. An old colleague had introduced me to these techniques and I wanted to implement them again for my students as I had had already introduced them to shellcode techniques such as parsing the PEB and PE space to resolve functions, and wanted to give them a challenge. I utilized the technique of hashing function names with ROR13, extracting Kernel32’s base address from the PEB and loading additional libraries with LoadLibraryA.
Because I choose to write the malware in C++ performing inline assembly was easy.
Firstly, I wrote three inline assembly functions that I could use throughout my malware to find the base address of kernel32, hashing a string, and resolve exports by enumerating the IMAGE_EXPORT_DIRECTORY in the PE header.
Next I wrote a function to hash a string using a form of ROR13.
Lastly I wrote in inline assembler the logic to parse through the PEB of a library once I had its base address to resolve the base address of a function while also utilizing the above hashing function.
From there, function pointers can be utilized to call Windows API functions. Because these functions will be obfuscated, new typedefs will need to be created that return and take in the correct Windows API types.
For example, the Windows API call CreateMutexEx appears as follows
This function will be used to create a named Mutex to ensure the malware is only running one instance of itself on an infected machine.
In order to implement this function obfuscated, the below typedef will be used
Now that the function prototype is known the address of it must be resolved. To do this, the base address of Kernel32 must be discovered, the function hashed and the function resolved.
To obtain the base address of Kenrel32 simply call FindKernel32().
The ROR13 hash of a function, CreateMutexA, must also be resolved. To obtain a hash you can call the hashString() function or use the below python script
In order to resolve this function by hash, a call to findSymbolByHash will be made with the address of kernel32 and the ror13 hash.
CreateMutexExA can now be called
Any API call from Kernel32 can now be used in an obfuscated manner. Calls from other modules can also be used with a call to LoadLibraryA.
Using the same methods above, the address of LoadLibraryA can be discovered at runtime.
Just call getLibrary() with the name of the module that needs to be loaded.
Now calls can be made into findSymbolByHash with user32BaseAddr and a function hash from that module.
As shown, utilizing shellcode techniques in C++ is relatively straight forward once the supporting functions are written.