Wednesday, 13 January 2016

NanoCore and Unpacking the AutoIT Cryptor

Recently I observed a lot of .NET binaries which are being spread in the wild packed in the form of an AutoIT compiled binary. In this article, I will take one such binary as an example and explain the process of extracting and decrypting the .NET binary which is crypted using AutoIT cryptor.

It is important to note that due to the way these binaries are packed using AutoIT, a lot of AV engines are not able to flag these as malicious. Even if they flag them as malicious, they are not able to classify the malware family properly.

So, let's start!

MD5 hash: 9c02fc5ff4f58ec7f88e66ae9bd15343
Original Filename: TeamSpeak_3.19x86.exe

Please note that at the time of writing this article, only 4/54 AV engines detect the binary successfully. None of the AV engines identify the malware family correctly.

This binary is a compiled AutoIT script. We can extract its components using exe2Aut tool as shown below:


 After extracting, we get the following 4 components:

1. AutoIT Installation Script -> This is the AutoIT script which is used to install the remaining 3 components from the original binary on the system.
2. Encrypted Binary
3. AutoIT Injection Script -> This is the script which will decrypt the binary and inject it into a process based on the preconfigured values.
4. AutoIT binary used to execute the AutoIT Injection Script.

The installation script will install the components in the %appdata% path as shown below:



And below is the deobfuscated version of the Installation Script:


After installation of components, it executes the AutoIT binary by passing it the path to AutoIT script in command line parameters as shown below:

"%appdata%\CRgJbHKRdBXfJbaHcJ.exe" "%appdata%\CRgJbHKRdBXfJbaHcJE.au3" "<location of original binary>" "<complete path of original binary"

This invokes the AutoIT injection script.

Decryption of Binary
 
Now, let us look at this script and understand how it decrypts the embedded binary.

The code section shown below will read the encrypted binary and decrypt it using _Crypt_DecryptData function. This function in turn calls CryptDecrypt() API exported by advapi32.dll



The decryption key is hardcoded in the AutoIT Script. In our case, the decryption key is: "ffOQTLAAYUYVUUIUDTSL"

So, how can we decrypt the binary manually without executing the AutoIT Script?

In order to do this, we can extract the relevant sections of code from the original AutoIT Script and add few lines of code which will write the decrypted output to another file.

I used the SciTE Script Editor which comes by default with AutoIT. This editor also allows us to run the script and view the output in the console window.

In the screenshot shown below, you can see the decryption code and the console output:


Now, we have the decrypted output in the file, output.exe in %appdata% path:


Let us copy it over to our original folder for further analysis.

Also, how is the decrypted binary executed by the AutoIT Script?

After decrypting the binary, the output is stored in the variable, $IYbCRVbDeUHJTTHJE

If we check the script further, we observe that in the function, IYbCRVbDeUHJTTHJEMdEYcJgQWLc() it checks the value of a preconfigured variable, $IYbCRVbDeUHJTTH. Based on the value of this variable, it performs the following operations:

1. Executes the code using wscript.exe
2. Injects the code into %windir%\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe
3. Injects the code into %windir%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe

Below is the relevant code section:


In our case, the value of the variable is set to 2, so the code is injected into RegAsm.exe corresponding to Microsoft .NET Framework version 2.0.50727

How is the code injected?

In the function, fAUXJWVCfXPb() it stores the obfuscated shellcode which is used to perform code injection.

This shellcode could be deobfuscated easily as shown below:


Now, we can analyse the shellcode in a debugger.

The shellcode is executed by the AutoIT Script using CallWindowProcW() function exported by user32.dll. The parameter passed to the shellcode is the decrypted binary.

Injected .NET binary Analysis

When we check it with CFF explorer, we observe that this is a .NET binary. So, let's decompile it with ILSpy.


In the screenshot below we can see that the code of this .NET binary is obfuscated:


We observe in ILSpy that this .NET binary has few resources in the resource section. Most of the malicious .NET binaries will store the malicious payload encrypted in its resource section.

To get the decrypted payload, we can analyse the binary with windbg and sosex extension.

After the .NET binary decrypts the resource, it will load the decrypted assembly using Assembly.Load.

So, set a breakpoint at Assembly.Load as shown below:

!mbm *Assembly.Load*

Now, when we run the program, it will hit this breakpoint.

If we display the contents of ecx register, we observe that @ecx+4 points to the size of the binary and @ecx+8 points to the binary itself.

We can now dump the binary using the windbg command:

.writemem c:\decrypted.exe @ecx+8 L?poi(@ecx+4)

Once we have the decrypted binary, let us open it with ILSpy again. We notice that it is a NanoCore binary as shown below:


If we continue running the main binary in windbg, we will hit the breakpoint on Assembly.Load several more times. We can dump all the decrypted payloads.

Below are the list of payloads I have extracted from it. NanoCore is a framework of multiple modules which are used to steal information from a machine and perform several other malicious activities.

ClientPlugin.dll
NanoCoreStressTester.dll
NanoProtectClient.dll
SurveillanceExClientPlugin.dll
Lzma#.dll
CoreClientPlugin.dll
ManagementClientPlugin.dll
NanoCoreBase.dll
MyClientPluginNew.dll
FileBrowserClient.dll
NetworkClientPlugin.dll
SecurityClientPlugin.dll
SurveillanceClientPlugin.dll
ToolsClientPlugin.dll

So, the binary in this case is NanoCore protected with AutoIT based Cryptor and other .NET obfuscators.

Monday, 4 January 2016

DLL Loading Technique used in ZeroAccess

Recently a new variant of ZeroAccess/Sirefef trojan was shared on the kernelmode.info forum.

Link: http://www.kernelmode.info/forum/viewtopic.php?f=16&t=1713&start=510#p27513

Thanks to R136a1 (@TheEnergyStory) and EP_X0FF (@hFireF0X).

The dropper sample uses an interesting technique to load the decrypted malicious payload in memory.

Dropper sample MD5 hash: 650357c7517273946f044390bc6bb9da

The payload is stored encrypted in a PNG image in the resource section with the resource name: RCDATA as shown below:


We often see malwares storing an encrypted payload in the resource section. However, in this case it was interesting to see that the payload was encrypted inside a PNG image.

Let us look at the call trace used to decrypt the payload:

401028 => LdrFindResource_U
401045 => LdrAccessResource
40105b => Ordinal_12
4011e4 => GdiplusStartup
401202 => GdipCreateBitmapFromStream
4011f6 => GdipGetImageWidth
4011fc => GdipGetImageHeight
401208 => GdipBitmapLockBits
401133 => NtAllocateVirtualMemory
40120e => GdipBitmapUnlockBits
4011f0 => GdipDisposeImage
4011ea => GdiplusShutdown
401180 => Ordinal_517

In the call trace above we can see that the PNG image is accessed from the resource section, its width and height is calculated using APIs exported by gdiplus.dll and then loaded. The size of the memory to be allocated using NtAllocateVirtualMemory is calculated using image height and width.

Below is the code specific to decryption routine:


The decryption routine is a simple XOR decryption routine using a 4 byte key.

Now comes the interesting part. The decrypted payload is loaded in memory as a legitimate DLL. In the case of ZeroAccess, it loads the decrypted payload in the memory as a legitimate DLL, shellstyle.dll.

Let us look in depth at how it does that.

Below is the call trace specific to this technique:

27024ed => RtlAddVectoredExceptionHandler
27025c7 => ZwSetContextThread
27024a0 => RtlInitUnicodeString
270247f => LdrEnumerateLoadedModules
27024c2 => RtlEqualUnicodeString
....
2702440 => LdrLoadDll
270247f => LdrEnumerateLoadedModules
27025c7 => ZwSetContextThread
2702459 => LdrUnloadDll
270251b => RtlRemoveVectoredExceptionHandler

Below are the steps in the technique:

1. It first registers a vectored Exception Handler using RtlAddVectoredExceptionHandler. This vectored exception handler is set to be called before any other exception handler.
2. It sets the context of the thread with the Context flag set to 0x10010 which corresponds to CONTEXT_DEBUG_REGISTERS.

We can see in the screenshot below the call to ZwSetThreadContext and the corresponding CONTEXT structure in memory dump:


Now, let us look at the CONTEXT structure definition as provided in WinNT.h header file:

typedef struct _CONTEXT {
DWORD ContextFlags;
    //
    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
    // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
    // included in CONTEXT_FULL.
    //

    DWORD   Dr0;
    DWORD   Dr1;
    DWORD   Dr2;
    DWORD   Dr3;
    DWORD   Dr6;
    DWORD   Dr7;

So, based on this information we can now understand the different values set in the CONTEXT structure in screenshot above.

We see that dr3 debug register is set to 0x7c90d500 and dr7 debug register is set to 0x440. This allows the binary to set a hardware breakpoint at the address: 0x7c90d500

This address corresponds to ZwMapViewOfSection as shown below:


3. Now, the binary calls LdrLoadDll to load the legitimate system DLL, shellstyle.dll. When this DLL is being loaded into memory by the Operating System, it will internally call ZwMapViewOfSection. This results in triggering the hardware breakpoint which results in an exception that is caught by the previously registered Vectored Exception Handler.

Below we can see the Vectored Exception Handler:


In the vectored exception handler, it performs the following checks:

i) The exception code is compared with 0x80000004. This corresponds to single step exception which is triggered by the hardware breakpoint.
ii) It then compares the exception address with the address of ZwMapViewOfSection API. This is done to ensure that the exception was received from the intended source.
iii) After these checks are performed, it proceeds to modify the structures specific to Exception to modify the return address.

The return address is the value to which the control will be transferred when ZwContinue() is called.

The actual return address for ZwMapViewOfSection is: 0x7c91bd03
This value is modified to 0x00a3240a as shown below:


As a result of this, when the exception is handled and ZwContinue is called, the control is transferred to 0x00a3240a instead of 0x7c91bd03.

This way, the actual code of shellstyle.dll is not executed even though it is loaded in memory.

After this, LdrUnloadDll is called to unload shellstyle.dll.

This technique of loading the malicious payload in memory in place of a legitimate DLL even though it appears as if the actual legitimate DLL was loaded is quite interesting.