Automating The Analysis Of An AutoIT Script That Wraps A Remcos RAT
Threat actors usually depend on some sort of a first stager to drop their malware, one good candidate for this mission is AutoIT scripts because of their capabilities of interacting with COM objects, calling DLLs’ functions, and simulating user interactions.
In this story, we’ll discuss some important tips for analyzing AutoIT malware and we’ll apply those tips to a real-world sample from the wild. We’ll also write a couple of python scripts to automate the analysis and to extract and decrypt the config of the Remcos agent.
Delivery
AutoIT scripts can be delivered in two ways:
- An
au3
script, which requires AutoIT to be either installed on the system or it could be shipped with the script. - The script could be compiled with the interpreter itself as a standalone executable. In this case, we’d need to extract the script from the exe file using either
Exe2Aut
orMyAut2Exe
.
Important Functions
Like any other scripting language, there are some specific functions and macros that malware authors could use to perform their nefarious tasks, the following is a list of the functions that are prone to be abused by malware authors:
DllCall()
DllStructCreate()
DllStructGetPtr()
DllCallAddress()
IsAdmin()
ObjCreate()
ObjectGet()
BinaryToString()
StringToBinary()
Binary()
BinaryLen()
AutoItSetOption()
EnvGet()
Eval()
Execute()
InetGet()
ProcessList()
RegRead()
RegWrite()
FileRead()
FileWrite()
ShellExecute()
ShellExecuteWait()
Run()
RunAs()
Sleep()
StringReverse()
TCPSend()
TCPRecv()
UDPSend()
UDPRecv()
And here is a list of macros that could be abused by malware authors:
@AppDataCommonDir
@AppDataDir
@AutoItExe
@AutoItPID
@AutoItX64
@CommonFilesDir
@ComputerName
@ComSpec
@CPUArch
@DesktopCommonDir
@DesktopDir
@DocumentsCommonDir
@FavoritesCommonDir
@FavoritesDir
@HomeDrive
@HomePath
@HomeShare
@LocalAppDataDir
@OSArch
@ProgramFilesDir
@ProgramsCommonDir
@ProgramsDir
@ScriptDir
@ScriptFullPath
@ScriptName
@StartMenuCommonDir
@StartMenuDir
@StartupCommonDir
@StartupDir
@SystemDir
@TempDir
@UserName
@UserProfileDir
@WindowsDir
Refer to the AutoIT documentation to understand what each function and macro does, links in the references section.
Example From The Wild
During one of the incidents that I have engaged with, I found a Remcos agent that has been delivered as a UPX packed binary wrapped inside an AutoIT script. The script has been delivered separately from the interpreter alongside a batch script that glues everything together and executes the script.
Sogni.tmp
This script starts by adding MZ
to a file named Mia.exe.com
then, it copies the contents of another file called Dai.tmp
to the same file, theDai.tmp
file contains the AutoIT interpreter without MZ
at the beginning. This trick usually being done to bypass the security controls that inspect the files with the MZ
header.
Then a file named Arteria.tmp
will be passed to the interpreter to be run. The Arteria.tmp
is the file that contains the malicious AutoIT script.
Arteria.tmp
By examining that script, we can see that it is being obfuscated with four techniques:
- A custom-written obfuscator has been applied.
- Declaring switch cases inside a loop that will only be executed once.
- Wired variable and function names.
- Declaring functions and variables that are never being used.
Identifying the De-obfuscation Function
De-obfuscating the malware is very crucial to have a successful analysis, mostly, the de-obfuscation function is the function that is being called the most, in this case, a function called faBwnHc
is the function that is being called the most and it’s not an AutoIT function (custom written) so this is the most suspected function.
To make it harder for analysts, the function itself applies the same obfuscation techniques 2, 3, and 4 that have been mentioned previously so, we need to defeat them in order to understand how to deobfuscate the rest of the script.
Defeating unnecessary loops and switch cases:
The loops and the switch cases always have the same pattern as follows:
<variable1> = number1 ; a number that determines the switch case
<variable2> = number2 ; a not used variable
Do ; the start of the loop
switch variable1 ; start of the switch cases
case numberX
statements
case numberY
statements
...
case number1 ; the case that contains the statements
statements ; that will get executed.
ExitLoop ; to exit the loop so, it runs only once
case numberZ
statements
EndSwitch
Until numberW
Next
So, for defeating this technique, we have to remove the unnecessary code. The following python function has been written for that purpose:
After running this function and saving the returned semi de-obfuscated script, we’ll get a clearer view of the script’s deobfuscation function.
Defeating a custom written obfuscator:
By manually going through the function to further understand what it does, we can see the following:
It accepts two arguments, the first one is a string of numbers separated by dots however, the second argument is just a number. The function splits the first string then it loops over the numbers list and subtracts the second argument from each number, then it converts the result to a character and concatenates those characters into a string, that string will be the de-obfuscated string.
A python function has been written to follow the same de-obfuscation technique.
And another function that automates the deobfuscation by looping over all the function calls and replacing them with the deobfuscated string
Once the script gets de-obfuscated, we can have a clearer idea of what is going on.
Defeating the unnecessary declared variables and functions:
The malware author has stuffed the script with so many unused functions and variables, to defeat this obfuscation technique, a python script has been written to tokenize the script and remove the unused declared functions and variables as follows:
Defeating the weird named variables and functions:
Now, we need to manually go through the script to understand what it does so we can rename the variables and the functions with meaningful names.
Buffer Decompression
The function that is originally called ZsMuinqqKkZyNasdzfRZygWqdvdbo
is responsible for decompressing a buffer that was originally being compressed with an inflating compression,
Killing Switches
For evading AV sandboxes, the malware checks the computer name and halts if the computer name is one of the known names that AV products use, for example: tz
which is being used by Bitdefender
, NfZtFbPfH
which is being used by Kaspersky
, and ELICZ
which is being used by AVG
. It also halts if it found a file named aaa_TouchMeNot_.txt
under the C:\
directory, mostly is trick is being used to avoid self-infection and to evade Defender AV Emulators.
Anti Analysis
The function that is originally named YlNhpDElbjgxIsNhKUV
, applies an anti-analysis technique where it gets the number of milliseconds that have elapsed since the system was started then it sleeps for a number of milliseconds and it recalculates the number of milliseconds that have elapsed again, then it calculates that delta and exits if the difference is either bigger than the delta + 500
or smaller than the delta — 500
.
Process Hollowing
The function that is originally called wJKkYYrSKDWGKUxnJpLSngpYQJY
takes a binary buffer and a command line that points to the path of the same process to be spawned by passing the command line to CreateProcessW
.
It calls the function that was originally named iIGEjbvuSPKbstetiETZTXUzxISkJG
for calling NtUnmapViewOfSection
to hollow out the contents of the spawned process then it calls the functions that were originally named oRnvqSVbsowWGStGmLJnlz
and YRZhNmLxfZ
to call VirtualAllocExNuma
to allocate a new memory region inside the hollowed process.
Then, it calls WriteProcessMemory
to write the binary buffer.
It calls VirtualProtectEx
to add the execution permission to the newly created region.
Then, it calls SetThreadContext
to point the thread’s entry point to the newly created section, finally, it calls NtAlertResumeThread
to resume the suspended thread.
Dynamically dumping the injected buffer
After we understood how it injects the buffer, let’s dynamically dump it out to continue our analysis.
Firstly, let’s hollow out the contents of the anti-analysis function so it wouldn’t bother us.
Now, let's open the AutoIT interpreter in x32dbg and adjust the command line to pass the script as an argument and reload.
Set a breakpoint on IsDebuggerPresent
, WriteProcessMemory
, and NtAlertResumeThread
.
Since it is an AutoIT script, it will call IsDebuggerPresent
to check whether the script is being debugged or not. Once the breakpoint hits, follow the instructions until you get to the memory location where it holds the BeingDebugged
flag in the PEB
then, change the flag to 0
so if by any chance there is any other check it fails.
Once the CreateProcessW
’s breakpoint hits, change the arguments of the function to change the create flag to 4
to create the process in a suspended mode.
Then, attach another debugger to the newly created process. make sure that the same breakpoints are being set and resume the process.
Once resumed, it will hit on the CreatePricessW
with a creation flag of 4
.
After running the debugger again, it’ll hit on the VirtualAllocExNuma
, by checking the first parameter which is a handle to the process in which it allocates a region of memory, we can see it’s a handle to the lastly created process.
The second parameter reveals that it allocates the memory in the 0x400000
base address.
By inspecting the allocated memory via Process Hacker and we can see it’s empty as of now.
Once we let the WriteProcessMemory
function runs, it will write the buffer into that region of memory, which appears to be an executable.
Now, we can hit the save button to dump the buffer on the disk.
By checking dumped file via PE-Bear, it appears to be a UPX packed binary and the Section headers need to be fixed.
For fixing the headers, we need to make the raw addresses point to the same location as the virtual addresses, and we need to recalculate the raw size respectively.
We also need to make sure that the base image points to the same base where we dumped the binary, which is correct in this case.
Once we fix the headers, the import table will be fixed and populated automatically.
As an anti-packing technique, the author has set the optional header’s checksum to 0
, so we can’t unpack it using the UPX binary, however, we still can unpack it manually.
The UPX packed binaries have two sections, UPX0
, AND UPX1
. The UPX1
section has the unpacking routine and once it runs, it writes the unpacked binary into the UPX0
section so, we can add an execution hardware breakpoint on the UPX0
section, once this breakpoint hits, that means that the binary has been fully unpacked and the execution flow has been transferred to the newly unpacked binary.
Open the UPX packed binary in x32dbg, get to the UPX0
section in the memory map, and follow that section in dump.
Then, set an execution hardware breakpoint on that section.
Once the breakpoint hits, we can check the strings, and we can see that it’s a Remcos RAT agent version 3.3.2 Light.
Let’s use Scylla
plugin to dump the unpacked binary.
Then, use the Scylla
plugin again to fix the dumped binary.
It’ll show you a box to select the dumped file, and it will create another file with the same name prefixed with SCY
.
Remcos agents store its config file in the resources in a file called SETTINGS
, that file is encrypted with RC4, so let’s open the remcos agent in PEStudio and dump out the config file.
Remcos configs have the following pattern, the first byte is the key length followed by the key itself, then the encrypted data which is the agent’s configuration.
So, by opening the configuration file in a hex editor, we can see that the key length here is 14 bytes.
Finally, we can use CyberChef for decrypting the configuration file and get the C2 address.
A python script has been written to automate the config extraction and decryption.
Thanks for reading, I’d appreciate your comments and feedback. 😊
References
- https://github.com/AmgdGocha/AutoIT-Remcos
- https://github.com/fossabot/myAut2Exe
- http://domoticx.com/autoit3-decompiler-exe2aut/
- http://www.thefoolonthehill.net/drupal/AutoIt%20Debugger
- https://www.autoitscript.com/forum/topic/192960-isn-autoit-studio/
- https://www.autoitscript.com/autoit3/docs/macros.htm
- https://www.autoitscript.com/autoit3/docs/functions.htm
- https://www.autoitscript.com/autoit3/docs/keywords.htm
- https://malshare.com/sample.php?action=detail&hash=d7fc2b593eac64ff4a46ba9f5864d875be3cb13ec8ef0327d781c5cd1e29b4ac