[3/23] Once unzipped (pw:infected), load the file into pe-studio for quick analysis. There isn't a lot interesting here, but take note that the file a 64-bit .dll with 4 exported functions.
[4/23] Taking this into account, drag the file into x64dbg to #debug the file. Once the file is loaded, let it run until the EntryPoint is hit by pressing F9.
In my case, nothing happened if I let the malware run continue to execute past the EntryPoint.
[5/23] Instead, let the malware run from the DllRegisterServer export, since this is a common place that malware will place #malicious code.
To do this, load the file again and browse to the "Symbols" tab in x64dbg.
[6/23] Change the execution to the DllRegisterServer function
Symbols -> ModuleName -> DllRegisterServer -> Follow in Disassembler -> Set New Origin Here.
This will cause the DllRegisterServer function to be executed instead of the EntryPoint.
Do this but don't F9 yet.
[7/23]
Before continuing, we want to set a breakpoint on VirtualAlloc.
This function is used to allocate memory for large buffers of data.
- Use "bp kernelbase.VirtualAlloc" -> hit enter
- F9 or "Continue" to continue execution.
[8/23]
After hitting F9 or "Continue", you'll hit your VirtualAlloc breakpoint.
Once you've hit that breakpoint, you'll want to use the "Execute Until Return" button. (CTRL+F9)
This will continue execution until the VirtualAlloc function has completed.
[9/23]
If successful, VirtualAlloc will return an address to an empty buffer in the RAX register.
You'll want to follow this address by RAX -> Right Click -> "Follow in Dump".
If successful, you'll see a lot of 00's in the dump window.
[10/23]
Now that you have an empty buffer, you'll want to know when it's used.
You can achieve this by right clicking on the first 00 byte and selecting "Breakpoint -> Hardware, Access -> Byte". Then hit F9.
Execution will continue until the 00's are overwritten with data.
[11/23]
After continuing execution with F9, your hardware breakpoint should be hit. Valid data will now be in your buffer.
The buffer is not filled yet, so you'll want to CTRL+F9 (Execute until Return), to allow the malware to finish filling up the buffer.
[12/23] After executing until return (CTRL+F9), your buffer will be overwritten with bytes.
You'll notice some strings and the presence of the FC byte at the start. These are solid indicators that the buffer contains shellcode.
[13/23]
To confirm that the data is shellcode
Use "Follow in disassembler".
This will disassemble the bytes as and interpret them as code.
If the results look anything like this, you have shellcode on your hands. 🐚
[14/23] There are numerous ways to analyse shellcode. In this thread I'll briefly mention three.
Easy-Ish: 1. Save the buffer to a file, and run it in an emulator. 2. Save the buffer to a file, and run strings on it.
Medium-Hard: 3. Continue Execution and debug in x64dbg.
[15/23] For the first two options, you'll need to save the shellcode.
One way to do this. Select it all from the dump and use "binary -> copy".
Then:
- open a hex editor (like HxD)
- paste your data
- save to a file named "shellcode.bin"
[16/23] To use an emulator, download the speakeasy tool from Github and install it on your machine.
Then run "python run_speakeasy.py -r -a x64 -t shellcode.bin" making sure your shellcode file is in the unzipped speakeasy folder.
2/ First, locate a scheduled task containing content that you suspect to be chromeloader malware. Decode the first stage using "From Base64" and "Remove Null Bytes". This will give you the first stage loader in its #decoded form.
3/ Next, check the location of the next stage in the registry. This should be near the beginning of the code.
If you utilise API hashing in your #malware or offensive security tooling. Try rotating your API hashes. This can have a significant impact on #detection rates and improve your chances of remaining undetected by AV/EDR. See below for an example with a Bind Shell vs #Virustotal.
Since API hashing can be confusing, most attackers won't rotate their hashes with each iteration of malware. Those same hashes can be a reliable detection mechanism if you can recognize them in code.
Luckily finding these hashes isn't too difficult, just look for random hex values prior to a "call rbp".
If you're unsure whether the value is an API hash, just google it and see if you get any hits. Most of the time, identification can be a simple google search away.