Monday, 4 January 2016

DLL Loading Technique used in ZeroAccess

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


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.


  1. I need the sampe 650357c7517273946f044390bc6bb9da. Can you help me?

    Thank you!