Static analysis of duqu malware with metasm (stage 2) - EN

Published on 2012-05-31 14:00:00.

After the boring first stage it was difficult to motive myself for the second stage. But it somehow worth it. I thought this sample to be a keylogger because that’s what I read in different papers. But it is not, this sample is a generic hooking engine for the following api and the code is quite nice.

To follow the article please use the idb duqu.0x5098.idb.

Yet an other stager

The code start at 401A8Eh (start) which setup the exception context and transfert the control to 402C2Eh (startmain) where a thread on 402B29 (main) is started and waited. (Yes we are in the boring stuff section.) The code gets a hand on the current process, aquire debug priviledge and open the target process to hook whose pid is stored in 403024 (dwProcessId).

Then 4028Bh (injectstage3) injects the third stage in the targetted process. The injection proceed as follow.

The string sort an .nls are xor with the same algorithm as the one from stage 1. I think this file is used as a working space for the hook payloads.

Api hooking

First, the stage 3 does not knwow where it was launched thus it need to obtain it virtual address this is done by 401709h (get_VA_401709) which provides its own address via the usual callpop trick:

call $5 ; call next instruction
pop eax ; pop the return address

This provides a reference point then the other addresses are computed with respect to the address of 401709h. This is quite clean and portable. Using this 40186Dh (getVAimports) gets the address of the homemade imports.

Then 401C39h (initenv) setup the environment retrieving the local sizeofimage, sizeofstack…

Now let’s get to the interesting stuff. 401DCAh (registerhooks) registers several hooks on ntdll.dll with a nicely getting payload from the fake file


4012C9h (getviewonNTDLLDLL) firt builds the path%systemroot%\ntdll.dll and open it and map it.

Then there are six similar bunchs of code wich register hook for the six API ZwMapViewOfSection, ZwCreateSection, ZwOpenFile, ZwClose, ZwQueryAttributesFile and ZwQuerySection.

Get the local handler virtaul address via 401709h (getVA401709) as previously explained. The handlers have two branches. (i) The normal one which simply call the hook payload saved in the homemade import table. (ii) The magic branch which does not call the payload but wich save manipulate the magic file previously mapped by 401709h (getVA401709). This magic part actually hijack the hooked API to do something else, I do not clearly understand this part may be because I do not have the associated fakentdll.dll.

The export table of fake ntdll.dll is parsed to retrive the hook payload; the payload is exported with the same name as the hooked API. The export search is achieved via the same API obfuscation technique as in stage1. The payload address is registered in the homemade import table.

4017E2h (setuphook) actually set the hook with a VirtalProtect PAGE_EXECUTE_WRITECOPY and a copy of seven bytes on the hooked API:

B8 DR AD OK HO FF E0: mov eax, HOOKADDR; jmp eax