Unpacking Ramnit

Working on this Sample


Static Analysis

-> Basic Threat Intel

This Sample does loads of stuff, we got a hint that it might be a Ramnit Trojan. Ramnit is a Famous Banker Malware Family.


-> Basic Static Analysis

In addition to high entropy[1], the Sample is detected with a resource as an AutoIt Script[1``], which Malware loves a lot being easy/small to automate the WindowsGUI tasks and other Windows general scripting purposes.

Also another interesting section .text [1```]with a very high entropy and suspicious characteristics such as being Writable/Executable, with the execution Entry-Point starting from there. So now we want to run the Sample in a Debugger to dynamically unpack it and dump the actual payload off of this mess.


Dynamically Unpacking the Sample

1→

Jumping to User Code and checking the Memory Map[1`] , we find ourselves inside that suspicious section detected .text at the Basic Static Analysis step.

Setting up breakpoints[1``] at VirtualAlloc()/ VirtualProtect()/ CreateProcesInternalW() in case the binary decides to spawn another process and continue executing from there.

The Code Starts with pushad which is an assembly instruction used to save/push registers and most commonly used for using the registers in the unpacking process without changing the original registers' values, with a later call to popad that would restore the registers to their original state. So we can follow this sequence and look for a good jump to some code [ jmp eax : in this case ]and continue from there and see if it gets us anywhere, but we are interested on how it uses Process Injection to inject the Unpacked Payload so we will focus on that.

2→

Once hitting Run[F9], we find a file being dropped Zeichnungen Mustermgr.exe[2`].

Noticing the full path to the dropped file that's been pushed to the stack[2``], and if we walked through the disassembly, we find the malware will query the system to deduce the ComputerName()/ CurrentWorkingDir() ..etc to construct the full path to which the file will be dropped. but since we do not really care about how it performs this, we won't look at that deeply now.

3→

We also hit the breakpoint at CreateProcessInternalW() with the path to the file been dropped[3`], we would now set a breakpoint on NtResumeThread() to catch the process before it resumes, and a breakpoint on WriteProcessMemory() to see if there is any data being written.[3``]

Continuing on with Run[F9], we instantly hit the breakpoint on NtResumeThread(),[3```]. Opening ProcessHacher or Procexp we find a child process spawned with the name of the file being dropped Zeichnungen Mustermgr.exe.

4→

Opening a new debugger to attach to the new process with the name Zeichnungen Mustermgr.exe****.

5→

Continuing on Run[F9] from NtResumeThread(), we can see a popup window about it being an AutoIt script, we will leave this open for now and check the debugger window attached with Zeichnungen Mustermgr.exe****.

NOTE: if we closed the popup window, the process will exit leaving the dropped file on disk, So we can choose between leaving the main process and attaching a new debugger window on Zeichnungen Mustermgr.exe, Or we can close the main process and debug the dropped file normally like we do, either way from here on all next debugging steps are same.


-> Debugging the Dropped File/ Spawned Child Process

6→

For Zeichnungen Mustermgr.exe we would want to put the same breakpoints as before: VirtualAlloc()/ VirtualProtect()/**** CreateProcessInternalW()/**** WriteProcessMemory().

On Running, the first thing we hit is VirtualAlloc(), On execute till return we follow the memory address in Dump1 and run, we see pretty much shellcode being written in the dump which what definitely will unpack/ decrypt the actual executable.

Continuing on we notice two calls to VirtualAlloc(), with two allocated region of memory that are only filled after returning from last call to VirtualAlloc().[6`], Both Dumps are filled with the exact executable[6``].

7→

Right now we could save this binary directly from the Dump Window, or if we have ProcessHacker/ Procex open, navigate to Zeichnungen Mustermgr.exe and dump the memory at the memory address of Dump3 before its being mapped.

Dump3 is just larger in size that Dump2, maybe that's why I choose it?, you can check Dump2 and analyze it to see if both are the same or not.


Analyzing the Dumped Binary

1→

Performing Basic Static Analysis, we find the dump is UPX packed with high entropy, which is quit straightforward as most Malware using AutoIt scripts often compress it with UPX.

2→

Now we can automatically unpack the dump with a simple upx -d <upxpacked.exe> command.

For the UPX part we can still use Generic Unpacking and fire the dumped binary in a debugger and set breakpoints on VirtualAlloc()/ VirtualProtect(), or find code patterns like [popad | pushad] and continue from there. This Sample used Custom Packing which was interesting, for more information about Packers, Check Malware Unpacking from The REM-Essential Series.

Last updated