Unpacking Zloader

Working on this Sample


Static Analysis

-> Basic Threat Intel Analysis

We've got a possible Zloader here.


-> Basic Static Analysis

Nothing is really indicating that this sample might be packed except for some interesting strings[1`] that are usually found in a packed executable, and a strange debug path[1``]


Dynamically Unpacking the Sample

Sample: d538dfafbdf6ac115c24dbdd68c65dbef6460808dd2c4f3fc01d5e15bfc2f902.dll

1→

Since the Sample is a DLL, we might want to provide a command line to the debugger to execute with rundll32.exe, "C:\Windows\System32\rundll32.exe" C:\path\to\sample.dll,DllMain

since we are only interested in unpacking the sample, we could go through the unpacking process without running the dll with rundll32.exe.

2→

Setting the breakpoints on the usual interesting APIs VirtualAlloc()/ VirtualProtect()/CreateProcessInternalW(). On Run[F9] we hit a few calls to VirtualAlloc() with the first allocated memory possibly containing shellcode to unpack/decrypt the actual payload.

On returning from the Third Call to VirtualAlloc() we could see an obfuscated executable being written, we can see the MZ header and everything. we also hit the call to VirtualProtect() meaning that this is going to map the unpacked executable in memory.

3→

We can literally scroll down the Dump window and right after the obfuscated/compressed executable we will find a full blown executable with sections and string table and everything.

Now dump this out and we got ourselves an un-mapped unpacked _possible_ zloader and we can go ahead and analyze it.

But we will also continue following the Injection process and wait till the process either write the unpacked executable to a remote process and continue from there, or overwrite itself with the unpacked code.

we will get back to this dump later at Step9.

4→

Since we hit VirtualProtect() we know that the process is trying to map the executable to memory by changing the sections' protections. walking through the next couple of calls on VirtualProtect(), we can see the API is being called on Sections of the packed payload we're running, meaning this is might be overwriting it with the unpacked executable.

Following the Address pushed in MemoryMap we find we're inside the our packed binary in .text section, changing it's protection from PAGE_READWRITE[0x04] to PAGE_READONLY[0x02] is an indication of a .text section got overwritten to contain new code[4`].

5→

Now we are pretty sure the process will overwrite itself with the unpacked code, navigating to User Code we search for a jmp eax/reg or a push reg followed by ret .

Though we don't see a push reg somewhere, we find two ret instructions so we breakpoint on them, and step in carefully until the we get to the unpacked code.

6→

Stepping through the calls to VirtualProtect() we find the Obfuscated+Unpacked Code being moved from the dump, so the overwritting process is done, and we hit our first ret instruction.

7→

Stepping into retwe find ourselves inside an unusual subroutine[7] _probably due to the fact that this is a DLL not being run properly through rundll32.exe _ anyways following this region of memory in MemoryMap [7``] we see it's inside the memory of our packed sample.

8→

Checking the running process memory we see it's quite large, probably containing the obfuscated code+unpacking shellcode+unpacked code, we don't need all that, we're only interested in the unpacked payload. Figuring this out among the mapped regions of memory in the process is quite easy, by looking at the executable being written in the allocated region of memory in Step3 we can see 4 Sections (.text, .rdata, .data, .reloc), adding the PE header section we end up with the very first 5 sections in the process' memory being highlighted[8`] (Check out the offsets they will make sense), we go ahead and Save this into disk.

The packed binary is run with DLLLoader32_1E56.exe [8``], I can assume this probably since it's not being run normally with rundll32.exe but that's not our concern right now.

9→

Now we've got a mapped dump, we need to fix the addresses of the section headers to resolve the imports. Now comparing the two saved binaries (Dump2 from step3 and the dump from the running process) we see both are identical, Same Entry Point, Identical Section sizes and offsets[9] and Zloader-Specific Strings[9]. And this is it, the unpacked Payload we're looking for.

:: now we got a Zloader unpacked binary which we can analyze and extract it's configuration file ..etc.

Last updated