Tuesday, February 28, 2017

Debugging dotNet malware with dnSpy

What makes .Net malware different from your classical windows malware 

When building a .Net executable, source code is not compiled to object code but to an intermediate language called “MSIL” (Microsoft Intermediate Language) which uses JIT (Just-In Time) compile at execution time but the “Common Language Runtime” virtual machine.
The virtual machine (execution environment) is a bit like the Java virtual machine except that the source code can be written in different high level languages like C#, VB.Net or even PowerShell.
As a result, as it is also the case for Java, .Net executables are much easier to reverse to source code than executable written in C++, for example. Such executable must be disassembled and analysed in tools like OllyDBG/Immunity or IDA, mostly at assembly level.
PE executables generated for .Net applications are also a bit different in their “aspect” than other PE executables. For example:
  • They usually need less imports;
  • .Net resources are not stored in the resources section of the PE file.
This is visible using CFFExplorer for example:

Regular PE file
dotNet PE file
A dotNet decomplier like ILSpy is nice for non obfuscated files but dnSpy offers much more features, including a debugger. This is a must-have when dealing with advanced malware samples that use encryption like the example below.

First stage

At first sight, the malware is clearly obfuscated
Just reading the code won't allow to understand how it works.
Let's just start debugging starting with the main() function.
We can see that the various encoded strings are being processed one by one:

The result of all these decoding can be retrieved by setting a breakpoint on a return. The returned value happens to be a PE file:
It can easily be dumped:
The first stage then loads the new assembly:

Second stage

The second stage is another layer of obfuscation and protection, including functions to detect some analysis tools like wireshark and sandboxie.

Stage 2 includes a modular configuration:

The various parameters are used in different places of the code. For example, if adequate parameters are set to ‘1’, stage 2 will search for running executables such as Wireshark, Sandboxie or Fiddler and end itself if found:
Some detection is done by looking for process names:

Sandboxie is detected by searching each process for the typical sandboxie DLL name:

Other protections are available (based again on the configuration parameters):
-          Disable task manager
-          Disable CMD
-          Disable UAC

In this case, all those "protection parameters" were set to "0", so no protection is enabled.

The configuration file also holds the key that will be used to decrypt the third stage malware (another embedded resource) using the DeCrypt function:
Encoded third stage
Decoded third stage
Which is then loaded using the RunPE (process hollowing) technique:

Third stage

The third stage is a RAT with various capabilities likes keylogging and camera control.
It gets resident by setting run keys:

CnC communication parsing
File location & name

The detailed analysis of this RAT feature may be the topic of a future post.


Interestingly, a quite similar binary has been documented by malwarebyte (
So maybe the first and second stage are some kind of packer or loader used to distribute various malware.

Friday, September 9, 2016

Dumping a RAT

Sample identity

I developed a quick python script to automate sample identification. The tool is available on github at: https://github.com/strobostro/multihash/blob/master/multihash.py.

This gives the following output:

md5 hash: bfe5b75975ab8d3852a39f7b642eb681
sha1 hash: 68a14979c9a589eb1dd6f232895737e5bfaf07cd
sha256 hash: 476eabfd3c416a837141c3391a80b9227f41b120c77af6a604570721abdffc3c
ssdeep hash: 12288:vaWzgMg7v3qnCikErQohh0F4cCJ8lnyIQHWsvelqC3OdJwoO1z1NAxRTDgvsxNCV:yaHMv6CIrjInyIQd2XmJwzLNAxRniZn
VirusTotal detection rate: 37/55
[(u'Gen:Trojan.Heur.AutoIT.112', 5), (u'BKDR_SPYNET.E', 2), (u'Trojan.Win32.Bublik.dzfr', 2)]

Execution chain

This malware has a quite complicated execution chain, probably in an attempt to block debugging attempts.

First, the malware asks for admin privileges (ie. no UAC bypass):

 The malware injects into Explorer.exe and starts an iexplorer.exe process to inject into also. Injection are done in memory using calls to WriteProcessMemory.

Though not readable in detail, the following procdot screenshot gives an idea of the execution chain complexity:

In the process, the malware is copied to disk in "C:\Windows\system32\.Rem\adobe.exe". Interestingly, when run, it pretends to be an Avast installer and presents... a DHL icon.

At the end, only the injected Explorer.exe and Internet Explorer processes do the job. The IE process is monitored by the code injected in Explorer.exe and restarted when killed (through an execution of the adobe.exe file).

The presence of injected code in the process memory can be confirmed using Sysinternal's "vmmap" tool:

The same can be done in the Internet Explorer injected process.


Dumping the memory region can be done using  Task Explorer. 

Or using OllyDumpEx which provides a cleaner binary because it identifies all sections of the PE. Do not use the default settings otherwise the ImageBase will not be good and IDA will not be able to analayse the dumped DLL correctly.

Default options - check ImageBase
Modified option: "auto adjust Image Base Address"
Restoring the IAT using Imprec does not work (the memory region is not linked to a DLL file on disk) but LordPE does the trick.

IAT is rebuilt

The dumped dll has section names related to UPX:

Then the file can be loaded into IDA without issue. The difficulty here is related to the dynamic imports resolution that makes the code less simple to read.

You can correct this manually by checking whether OllyDBG resolves the calls better. This is a bit time consuming and they may be a better way using Python IDA scripts.


The malware gets resident using simple ways by:
  • copying itself on disk (in an hidden directory);
  • setting registry keys.
[extract from BSA report]
Hid file from user: C:\Users\<user>\AppData\Roaming\logs.dat
Hid file from user: C:\Windows\system32\.Rem\adobe.exe
Hid folder from user: C:\Windows\system32\.Rem

Defined registry AutoStart location created or modified: machine\software\microsoft\Active Setup\Installed Components\{F00O4LJT-V814-OU62-E55T-E52TVT61U615}\StubPath = C:\Windows\system32\.Rem\adobe.exe
Defined registry AutoStart location created or modified: machine\software\microsoft\Windows\CurrentVersion\Policies\Explorer\Run\Policies = C:\Windows\system32\.Rem\adobe.exe
Defined registry AutoStart location created or modified: machine\software\microsoft\Windows\CurrentVersion\Run\HKLM = C:\Windows\system32\.Rem\adobe.exe
Defined registry AutoStart location created or modified: user\current\software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run\Policies = C:\Windows\system32\.Rem\adobe.exe
Defined registry AutoStart location created or modified: user\current\software\Microsoft\Windows\CurrentVersion\Run\HKCU = C:\Windows\system32\.Rem\adobe.exe


Looking at the output of the "strings" command shows that the malware has a lot of features from remote control to password stealing (browser, steam, ...) to video & audio grabbing and proxy setup.

However, just blindly beleiving the "strings" output can be misleading. After having dumped to DLL, it is possible to load it into IDA and check that the strings looking like features are part of a large switch case.


This helps us confirm that the malware has at least the following functions:
  • process interaction (ex: "listarprocessos" - list processes -, "listarservicos" - list services -, "finalizarprocesso" - terminate process,...
  • window interaction (ex. "listarjanelas" - list windows -, "windowsocultar" - hide window,...)
  • webcam interaction ("webcam", leading to calls to functions such as AVICAP32.CapCreateCapureWindowA,...)
  • filemanager (ex. "filemanager|mensagens|", "filemanager|deldirallyes|", ...)
  • show/hide taskbar
  • network interection ("listarportas" - list ports, "finalizarconexao" - terminate connection),
  • ...
This sample also embed a reference the the Spy-Net RAT which is advertised with the same kind of feature.

For more information on this RAT, check out: 


The malware contacts a C&C server to get order and send information.

Heartbeats are sent to 3 ports on the C&C: TCP 80, 81 & 82.

OllyDBG offers decoding from some default structures which is nice when debugging network communications.


The communication can be validated by resolving the C&C name in our lab and opening necessary ports with fake services. The protocol used is not HTTP but encrypted text.


On the victim's side, connections to the C&C are seen using Sysinternal's "TCPView";


Keylogging is implemented through key state monitoring.

Data is stored in "C:\users\<user>\AppData\Local\Roaming\logs.dat"

Looking at the keylogger shows encrypted code.

I did not dig to much in the code itself but noticed that the stored data seem to have the same size of captured data so I decided to try a known text attack, with mixed results.

As XOR operation are often used, I tried to encode simple text (ex. 'aaaa') and checked that:
  • the output is of the same size;
  • when the output value for 'aaaa' is used as input, the resulting value in the log file is 'aaaa'
As all "a" are not encoded as the same value, the key must be made of more than 1 character. If the key repeats itself, then entering more "a" should result in a pattern.

OK, the intuition seems to be good so lets get the key be xoring the input and output values.

so the key seems to be "#$$,!+.6&$6*+&$3+6.*+6%.+.6*%

Let's check the key on another run of the malware and other input.

But this time, the key does not work. It may be a "rolling" key, not always starting at the same point so I tried all translation of the key and checked the output:

So this time the key is: 6%.+.6*%"#$$,!+.6&$6*+&$3+6.*+ (in fact the same key with a rotation).

Another run show that the key does not depend on a specific run but rolls all the time:

The log file is made of a succession of:
  • Windows name (lines starting with "####"):
  • Keystroke
Though not a real efficient approach, trying every rotation of the key reveals the recoreded keystrokes:
----LINE---- u*xWK]+Z_^WGÃ)$nMDM;HKBOX&y3&;#4+m%jjzs%qkna>,13!&?+$::0$>&6<91#5.v
^ V}`k ttpamæ Jihl f}dkn R G \OTX GAKC
C R|}x qqh}bá
 Jaef ~mfyr
[ Sans titreà
notes ]




}}c} cgmx {h `v yhc bh~oa
`eg| plh} gg aq qei zx|}}
xafa    {ime h`    fq |ol jzna|
|`{r ~luy oa fy vjt hhr`q
}}hy {tiv nf nt srd
`nc| chfq if c~
kbf fu~od
sefy gap in i{ {`t gx|x|
x`ca p``w ac lc yrh jzk`a
}e{}    wagw
li ts kni hms}y
x}gr vfg fl dq wod
`ahu qfor
ct fc vbf ghva|
|not qnbx {d t {`q zpr`a
sins ych} kf h~ ywi bts}r
this time it is not funny


Another example (same base key with some rotation):


Looking at the code however shows a different story. The XoR key found is "derived" from another key: "njkvenknvjebcddlaknvfdvjkfdskv" (same size as the XoR key above - which is thus not leaked by running a simple "strings" on the dumped PE).

Before encryption
After encryption
Value is writen to log file
I propose a python script to parse the "logs.dat" file using all possible rotation of the base XoR key but I'm sure a better solution would be to take some time to reverse the encryption function. The script checks the content of the decoded lines against a list of words; this limits the output.


Command line:
analysis# c:\Python27\python.exe decode2.py logs.dat dict.txt > output.txt
Example output:
<...extract from the output.txt file ...>
----LINE---- ####u*h,yyB@RERQW]_UNC%4xUGO(AKN6s*&;(0+u6ndvf+peln46759:2)6#: .'&67<1:"*x
matched string: Windows
[ C \Windows\system \cmd exe ]



<...extract from the output.txt file ...>

Note that the "njkvenknvjebcddlaknvfdvjkfdskv" is also used to generate the content of the network keepalives. However the "XoR key" found previously does not seem to apply.




Network IOC:
  • communications to "m0ntecrist0.co.ve" (check out: https://www.threatcrowd.org/domain.php?domain=m0ntecrist0.co.ve)
  • non HTTP communication to TCP ports 80, 81 & 82
  • containing the string "28|" 
System IoC:
  • directory named "C:\Windows\system32\.Rem"
    • continaing a file named "adobe.exe"
    • both with "SHR" attributes ("System", "Hidden" and "Read only")
  • "C:\Windows\system32\.Rem\adobe.exe" referenced in various registry autostart locations:
    • HKLM\software\microsoft\Windows\CurrentVersion\Policies\Explorer\Run\Policies
    • HKLM\software\microsoft\Windows\CurrentVersion\Run\HKLM
    • HKCU\current\software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run\Policies
    • HKCU\current\software\Microsoft\Windows\CurrentVersion\Run\HKCU
  •  Files in "c:\users\<user>\AppData\":
    • Local\Temp
      • UuU.uUu
      • XxX.xXx
    • Roaming\Logs.dat => keylogging file