domenica 12 novembre 2017

Shed - Inspect .NET malware like a Sir

When I start to analyze a new malware, there are some initial tasks that provide a lot of useful information to speedup the analysis. Two of them are of particular interest, the extraction of the embedded strings and the dumping of packed binaries. Unfortunately those information are often obfuscated or not so easy to retrieve. In this article I'll present a new tool which is able to analyze .NET programs in order to extract those information in an easy way. Its name is Shed.

You can find the full source code of the project and an already compiled binary in this Github project.

Introduction

The idea behind this tool is to make the extraction of strings that reside in memory easier and also to dump dynamically loaded binaries. I'll show you how to use Shed in order to analyze a well know .NET RAT malware.

Dump the Heap

When a new object is created, it is saved in the managed heap. This memory area is managed by the .NET runtime, more specifically by the Garbage Collector. It is its responsibility to free unused memory when needed. This specific behavior is very handy for an analyst, since the Garbage Collector will not reclaim the memory if not necessary. In this way we have a good amount of time to inspect the heap and to dump useful objects, like strings or byte array.

Thanks to the powerful Reflection capability provided by .NET, for each stored object we can extract the type and also all associated fields. In this way we can reconstruct the memory representation of complex class that can provide useful insight about the inner working of the malware.

Modules dump

Another interesting aspect when analyzing a malware is the ability to dump dynamically loaded Assemblies. This case is pretty common, since most of the .NET malware store the main Assembly in some kind of encrypted form and load it only at runtime.

It already exists a very useful tool that allow you to dump dynamically loaded Assemblies which is MegaDumper, but since it is not open source (on GitHub you can find a decompiled version) and I have never wrote a PE dumper, I decided to create my own tool :)

In order to dump an Assembly we have to dump the related PE file from memory. This operation can be pretty challenging, a lot depends on how the malware was protected.

A naive approach is identifying the start of the PE file and starting from there read

PE->SizeOfImage

bytes. The main problem with this approach is that by now most of the malware use Process Hollowing ([1]) to inject its content in a newly created process. This implies that the PE is not mapped in a contiguous memory area, making the read operation not possible.

A better strategy is to parse the PE header and reconstruct the binary by reading all sections from memory.

One important aspect to consider when dump a .NET Assembly is to fix the PE Entry Point. Let us analyze the Entry Point of a managed PE file:
[0x0043d9de]> pd 1
;-- entry0:
0x0043d9de    ff2500204000   jmp dword [sym.imp.mscoree.dll__CorExe
the code jumps to the _CorExe routine. From MSDN ([2]) we can read that:

Initializes the common language runtime (CLR), locates the managed entry point in the executable assembly's CLR header, and begins execution.

So we need to set the Entry Point of the reconstructed binary to a piece of code which jump to this function. Last missing part is to obtain the address of this function. This task can be accomplished by walking the Import Address Table and locating it.

Use cases Agent Tesla (cc518a6c63f56c4891b5e30e8cb97b26)

Let's see how to use Shed in order to analyze a real world malware, an agent Tesla sample analyzed by Forcepoint in [3].

c:\Shed>Shed.exe --timeout 2000 --exe cc518a6c63f56c4891b5e30e8cb97b26.exe
    -=[ Shed .NET program inspector ]=-
Copyright (c) 2017 Antonio Parata - @s4tan

[+] Attached to pid: 160
[+] Created runtime: v2.0.50727.5420
...
[+] [System.String] 0x278043C: 0|0|0|0|0|0|0|0|0|0|18000|1|skpehostbrowaer.exe|Temp|AXKTOimGsklqIffPCompzbSmVnpwanUmzyjRJTSpqQzJHIASyqoYDvKR|0|0|0|0|0|0|0|IWIOzYrGb|0|0|0|0|0|0|NgjBaJMqu|OEeQOTHIoxSSUapGpFWjxLNzWbe|6|0|
[+] [System.String] 0x2780610: /c echo [zoneTransfer]ZoneID = 2 > 
[+] [System.String] 0x2780668: :ZONE.identifier & exit
[+] [System.String] 0x2780748: <?xml version="1.0" encoding="UTF-16"?><Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">  <RegistrationInfo>    <Date>2014-10-25T14:27:44.8929027</Date>    <Author>[USERID]</Author>  </RegistrationInfo>  <Triggers>    <LogonTrigger>      <Enabled>true</Enabled>      <UserId>[USERID]</UserId>    </LogonTrigger>    <RegistrationTrigger>      <Enabled>false</Enabled>    </RegistrationTrigger>  </Triggers>  <Principals>    <Principal id="Author">      <UserId>[USERID]</UserId>      <LogonType>InteractiveToken</LogonType>      <RunLevel>LeastPrivilege</RunLevel>    </Principal>  </Principals>  <Settings>    <MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>    <AllowHardTerminate>false</AllowHardTerminate>    <StartWhenAvailable>true</StartWhenAvailable>    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>    <IdleSettings>      <StopOnIdleEnd>true</StopOnIdleEnd>      <RestartOnIdle>false</RestartOnIdle>    </IdleSettings>    <AllowStartOnDemand>true</AllowStartOnDemand>    <Enabled>true</Enabled>    <Hidden>false</Hidden>    <RunOnlyIfIdle>false</RunOnlyIfIdle>    <WakeToRun>false</WakeToRun>    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>    <Priority>7</Priority>  </Settings>  <Actions Context="Author">    <Exec>      <Command>[LOCATION]</Command>    </Exec>  </Actions></Task>
[+] [System.String] 0x2781308: [LOCATION]
[+] [System.String] 0x2781330: schtasks.exe

...
[+] Saved dynamic module: raobtmNqCzJjZpcUiyDwYSCM
[+] Saved dynamic module: Microsoft.VisualBasic.dll
[+] Result saved to c:\Shed\Result\160
[+] Detached
From the output we can see that a module with a weird name (raobtmNqCzJjZpcUiyDwYSCM) was dumped. This Assembly was decrypted and loaded by the first loader layer.

It is in charge for various operations and it has also a configuration string which is:

0|0|0|0|0|0|0|0|0|0|18000|1|skpehostbrowaer.exe|Temp|AXKTOimGsklqIffPCompzbSmVnpwanUmzyjRJTSpqQzJHIASyqoYDvKR|0|0|0|0|0|0|0|IWIOzYrGb|0|0|0|0|0|0|NgjBaJMqu|OEeQOTHIoxSSUapGpFWjxLNzWbe|6|0|

specify the time to sleep (18000 milliseconds) and the name to give to the real payload.

Also, it is in charge for ensuring persistence by creating a task with the XML configuration string displayed in the output. Finally, it decrypts the real payload and executes it with a .NET implementation of the RunPE technique which use Process Hollow.

This loader was already analyzed in [4]. By using Shed, we can see that we were able to retrieve a lot of useful information without too much effort.

Moving on, in order to inspect the real payload, I executed the program and waited for the spawn of a new process. After this, I ran Shed against the newly created process as showed below:
c:\Shed>Shed.exe --pid 3652
    -=[ Shed .NET program inspector ]=-
Copyright (c) 2017 Antonio Parata - @s4tan

[+] Attached to pid: 3652
[+] Created runtime: v2.0.50727.5420
...
[+] [System.String] 0x297A798: <br>VideocardName&nbsp;: 
[+] [System.String] 0x297A7DC: <br>VideocardMem&nbsp;&nbsp;: 
[+] [System.String] 0x297A82C: <br>IP Address&nbsp;&nbsp;:
...
[+] Saved dynamic module: Microsoft.VisualBasic.dll
[+] Saved dynamic module: Microsoft.JScript.dll
[+] Saved dynamic module: IELibrary
[+] Saved dynamic module: System.Security.dll
[+] Result saved to c:\Shed\Result\3652
[+] Detached
This time the output is pretty huge. Among the dumped modules the most interesting ones are:

IELibray (9759067EDF26E4A4E49B4E228C7DF81C)

It is used to interact with Internet Explorer in order to steal usernames, passwords and cookies, as can be seen by the following image:

no name (6030C0CFC40A6A69857454D5EB41D9FA)

This is the real Agent Tesla module, where we can see the routine in charge for decrypting the stored string:


Heap inspection

As already said, even if the strings are stored in encrypted form they will survive until the Garbage Collector will not reclaim the memory. If we take a look at the JSON file heap.json, we will see (apart from the enormous amount of information dumped) a lot of useful data, like the SMTP server and account used to exfiltrate data:

{
  "Address": 43845700,
  "Name": null,
  "Properties": [ ],
  "Reference": 0,
  "Type": "System.String",
  "Value": "gp4XXXXXX@zoho.com"
},
...
{
  "Address": 43864368,
  "Name": null,
  "Properties": [ ],
  "Reference": 0,
  "Type": "System.String",
  "Value": "poXXXXX8"
},
...
{
  "Address": 43871204,
  "Name": null,
  "Properties": [ ],
  "Reference": 0,
  "Type": "System.String",
  "Value": "smtp.zoho.com"
},
...

Conclusion

I hope that you enjoyed this post and that you will find Shed useful in your analysis :)

References

[1] Process Hollowing
[2] _CorExeMain Function
[3] PART TWO - CAMOUFLAGE .NETTING
[4] Unpacking yet another .NET crypter