Just a short blog entry to save this info for the history.
We investigated originally two different pieces of duqu payload. One contained resource 302 with a compressed .zdata section, the other contained the to-be-injected code without compression. The injector-loader is the same for the two versions, then how does it find if .zdata should be loaded?
Here is the trick from netp 301 resource:
.text:10001220                 mov     ecx, 5A4Dh
.text:10001225                 cmp     [eax], cx
.text:10001228                 jnz     loc_100012CD
.text:1000122E                 mov     ecx, [eax+3Ch]
.text:10001231                 add     ecx, eax
.text:10001233                 cmp     dword ptr [ecx], 4550h
.text:10001239                 jnz     loc_100012CD
First it checks for “MZ” header, then it check “PE” signature.
Now,
.text:1000123F                 movzx   edx, word ptr [ecx+6] ; number of sections in PE File (5)
.text:10001243                 cmp     dx, 3
.text:10001247                 jbe     loc_100012CD
.text:1000124D                 movzx   esi, word ptr [ecx+14h] ; pointer to symbol table
.text:10001251                 movzx   edx, dx
.text:10001254                 imul    edx, 28h        ; each section entry in section table- 40 byte
.text:10001257                 add     edx, ecx
.text:10001259                 lea     edi, [esi+edx-38h] ; the section before the last section (zdata) + offset
.text:1000125D                 test    edi, edi
.text:1000125F                 jz      short loc_100012CD
.text:10001261                 cmp     dword ptr [edi+1Ch], 0BC395587h ; zdata magic PE Header  NumberOfRelocations is abused
.text:10001268                 jnz     short loc_100012CD
.text:1000126A                 cmp     dword ptr [edi+8], 2Ch ; some check on physical size
.text:1000126E                 jb      short loc_100012CD
As you can see, it calculates the exact place for the end of the section table then moves back to the entry before the last (this is .zdata info). Then it checks for a magic number 0xBC395587 which is stored in “NumberOfReloctions” value.
.text:10001270                 mov     esi, [edi+0Ch]
.text:10001273                 add     esi, eax
.text:10001275                 cmp     dword ptr [esi], 0D139120Eh
.text:1000127B                 jnz     short loc_100012CD
Finally it checks the first 4 bytes of the .zdata section against 0xD139120e.