Some time ago I have found out that Emotet malware is a huge problem especially when it comes to malspam – lots of phishing mails contain Emotet downloader in various formats. I happened to analyze one the them and you can see my anaysis there. I have also prepared tracker under tracker.malwaredancer.com which presents Emotet C2 proxy servers on the world map. The problem seems to be quite big. That is why I wanted to have a look into Emotet sample. I got mine from https://app.any.run.
At first I wanted to load it into Ida Pro for static analysis, but I stuck since Ida failed to follow EIP – probably some anti-debugging solution was used to stop me from playing with it.
Dynamic analysis
I had no other option, but to run in in the VM with debugger attached. Since I feel pretty comfortable with OllyDBG I loaded the sample into it. At first I have found out that input the first input argument is compared to some strings which looks like a hash or something – without process was create another copy of the binary under C:\WIndows\System32\loopadraw.exe path.
lstrcmp() was used in this case to compare string provided as input argument. If it was not provided then two things happened: GetTickCount() was called to check if this machine is kind of fresh after reboot – if that is true then sample became dormant, it exited with exit code 0. Whenever you provided the correct input argument – “–8cc854c5” then it started procedure of checking it was run from C:\WIndows\System32\ directory and if the binary from which it is called has proper name – in this case it would be loopadraw.exe
While I have started to analyze this sample many times I fall into the situation that when process was forked and binary C:\Windows\System32\loopadraw.exe was created and then started – of course the process that I was debugging was terminated and only the forked one was trying to reach C2 server. Also it is worth to mention that Emotet tries to identify if it was run from the place that it expects to hide in the System32 directory or it is some other path. If it is not System32 dir then it will remove the binary just after it copy itself into system dir.
So do I handled those forking? I set breakpoint on VirtualAlloc calls and then I got to the point where I have seen some PE file being loaded into memory. So I have dumped the whole structure from the memory and luckily it was PE32 executable with all relevant sections. Nothing interestring when it comes to the imports sections.
[0x0040bb5a]> ii
[Imports]
1 0x0040d000 NONE FUNC KERNEL32.dll_IsProcessorFeaturePresent
Only IsProcessFeaturePresent function from kernel32.dll was explicitly imported. So I have get back to the dynamic analysis.
First interesting thing is GetTickCount call. So whenever my VM restarted because of installing updates I could not start unpacked sample at all. It stayed dormant. This was done because of GetTickCount() call and then comparing its result to the the hardcoded value.
Whenever I see “PE” string on the stack I am pretty sure that my sample is trying to unpack its internal payload into the memory. I have dumped this PE32 executable and luckily I got working PE32 executable. So now I am able to load it separately into OllyDBG and start analyzing this payload.
How to hide system calls?
Since I have not found any relevant imports I thought there is some trick used there to call system functions and I was right. Since kernel32.dll library is already loaded into process memory because of imported IsProcessorFeaturePresent() function other symbols from the same library can be used in the code.
One by one, you can see that lots of libraries are loaded using LoadLibrary() calls and functions that are called within those libraries. From my point of view, the most interesting part is the one responsible for network communication with CnC servers. You can see below that IP address is being picked up from the list and then connection is being established to this server.
C2 communication
Also you can see below how the request to the server is being prepared. The server endpoint is being randomly picked from the dictionary.
And another server and endpoint was prepared on the second run since first server did not respond.
I guess it will not respond at all because all Emotet infrastructure seems to be offline. Only C2 proxy server are alive but they are pointing to another chain of real CnC servers which are currently down form nearly a month.
Then below you can see http request which was send to C2 server.
Referrer seems to look like the legit one, we will have Base64 encoded binary data. Also you can see that the request is send via POST method.
So the question is what is inside the request that is send to C2 server?
DRvcFuRsJYWBg=EsT35zIooPiwgahGoqOnYdxxb1DVFLeDVv+oYCDLuUs3phcpNqn0ntJou7oXJVlgF5qS6C3CTLij2XA+ywhwxXeQNybYMgiQ9YAIMCoV5WMpBi8pyfwmVMyO80T6MtHJ7+VSc1Tp02bPY8q0bsHeEYD/Kh+s5RQU+TKm4WKJfoJ5TlqQTwsXb1nTZjgkOcYbF0vjpntxaQ5IWO7gzw6fWxQrUhiue1pcsJqm/TZal7rbM/g/LlndoPO7IdzYDdFzFMPUXLFqFX3f0x9XR8nSTVxs6kz/MAGYYCJoJWOuB6AzduG8ineWA6jsN/hhFKNlseb0op8OduNr0//vWhGsvA4zz8nihDiq79bBS8P/9m0i1gwJqNhPre31lBof/aVVHUepmU8AOpRD9/X+0zYLw0wNTPa0ZK/TkODBcE2n00X1QLo2B8P+ikwPbghvU1Aski9+mEXtK9XFRQ2oe1LdpR9qH5ixZdb4goWe9y5SnzF9iTMS
Emotet C2 server reques
I have tried to decode this request, but inside seems to be some kind of binary data. Based on other research related to Emotet I thought it could be Protocol Buffer message, but online protocol buffer decoder could not fully processes this message. So maybe this is not the thing? I will try to cover it in the next writeup.