The Windows operating system has the most shares and attracts the highest attention for most malware authors. It’s actually quite easy to write ransomware and have it cause some irrevocable blind damage to the host machine. It is quite a lot harder, though, to author a sophisticated piece of software that can damage the victim on multiple levels. This blog details my findings navigating through the Windows malware titled openme.exe that not only encrypts sensitive information on the victim machine but is also capable of data exfiltration and subjecting the victim to Command and Control (C2) server.
In this write-up, the Windows malware titled OpenMe.exe will be used as a demonstration to test the malware analysis methodology taught by SANS FOR610 class.
The malware can be downloaded Hybrid Analysis.
DISCLAIMER: This is very much a live malware. Experiment at your own peril.
Hybrid Analysis has a good automated breakdown. Windows, however, has the privilege of having the widest range of artifact collection tools. It would be wise to proceed first without the use of automation.
The most basic form of analysis is to dump the binary’s strings and see what goes:
The string dump was not very fruitful. There was no trace of any HTTP request capabilities or any hosts at all. Most of what was mentioned was regarding
AstroBurn Lite is not registered and other “trial version” strings.
A few things stand out: -
TerminateProcess: Could be used to control or spawn new processes -
TlsSetValue: Could be used thwart debugging. -
IsDebuggerPresent: Anti-debugging checks
There is a possibility some of those imports ended up in the binary since it was statically compiled. For now, not much can be said about the binary. The next step should give us more info.
We’ll need to set up an analysis environment before executing the program. The setup I’m using is as follows:
A Windows virtual machine was connected to an analysis virtual machine, running Ubuntu 18.04. Since this is a Windows malware, there was no need for the Ubuntu victim machine. What we’re really looking for here is to understand the behaviour of the network.
About 2 minutes after the malware was launched, all the user’s file were encrypted with a
.osiris extension. The background image of the victim machine changed to show an address to a BitCoin wallet an email to contact the malware author to get the decryption key.
As for the network side, we’ve discovered the following request that was sent to an ominous
The payload of the request contains the victim’s internal IP address, the computer name, and an encrypted
p= blob. The request also seems to be repeated every 300 seconds.
It is quite interesting that we did not find any internet imports or cryptography imports when it is evident that the malware used both. This could be an indicator that the malware is, indeed, packed.
Malware is often packed. It produces a version of the executable that is smaller in size and more difficult to analyze for the malware analyst. The malware analyst will still be able to work with a packed version for a behavioral analysis but in many cases, the unpacked version will be necessary to perform static analysis.
Most packers program their unpacking stubs to unpack the real malware in memory. If that is the case, they’ll need to invoke a function to reserve a block of memory with read-write-execute permissions. VirtualProtect is usually reserved for that type of action.
We can get more granular with that theory. wincrypt.h does not have too many functions to encrypt data. Actually, there is one specific one that must be used to actually go through the encryption, CryptEncrypt.
It would be a good step forward to trace the execution of
VirtualProtect in the next step.
Most debuggers allow the putting a breakpoint on a Windows import without actually knowing if it exists in the codebase. x64dbg and Immunity Debugger both allow for such a functionality.
After setting a breakpoint to
VirtualProtect and re-running the malware, we discover that a new
0x04230000 memory region was about to be protected with
ERW permissions: Execute-Read-Write:
We’ll have to leave the binary finish the unpacking process to get any meaningful output from that
0x04230000 memory region. A good way forward is to set a breakpoint at a location that the fully-unpacked binary could use.
CryptEncrypt, for example.
Setting the breakpoint and continuing the execution, we actually do hit
CryptEncrypt was not in the original imports dump. The assumption here is that the packed malware has finished unpacking and
CryptEncrypt was executed, in memory, from the packed malware. We can verify this easily by examining the return address located in the stack and seeing the memory region that the call to
CryptEncrypt was made from:
Tracing the executor of
CryptEncrypt reveals that it came from the memory region
0x04230000. The same memory region that had the ERW permissions. Furthermore, we can see that the header of that memory region spells out
MZ: the file magic of the unpacked PE binary.
0x04230000 memory region will yield unpacked binary. Rerunning strings on the unpacked binary will give us a better view of the real functionality of the binary:
CryptEncrypt import is quite visible now. Scrolling a bit further down should reveal the
HttpSendRequest import that was used to communicate and send the decryption keys to
Further analysis of the unpacked binary reveals that the purpose of the communication every 300 seconds to
brb.3dtuts.by is also to get execution instructions from that server. The binary would accept instructions such as
peels, which will
sleep respectively. Actually, the analysis machine could just send back
peels 99999999 as a response to silence the ransomware functionality for 3.17 years since the encryption functionality occurs after the server request.