Tools that are required for analyzing this form of malware are ollydbg/immunity debugger, Virtual machine, and a memory dumper like Lord PE. Binary First Stage The original sample is packed with a custom packer that overwrites heap memory with executable code: [c] 0012FB07 8B75 F8 MOV ESI,DWORD PTR SS:[EBP-8] 0012FB0A 8A0C30 MOV CL,BYTE PTR DS:[EAX+ESI] 0012FB0D 3A8D 70FFFFFF CMP CL,BYTE PTR SS:[EBP-90] 0012FB13 75 24 JNZ SHORT 0012FB39 0012FB15 8A4C30 01 MOV CL,BYTE PTR DS:[EAX+ESI+1] 0012FB19 3A8D 71FFFFFF CMP CL,BYTE PTR SS:[EBP-8F] 0012FB1F 75 18 JNZ SHORT 0012FB39 0012FB21 8A4C30 02 MOV CL,BYTE PTR DS:[EAX+ESI+2] 0012FB25 3A8D 72FFFFFF CMP CL,BYTE PTR SS:[EBP-8E] 0012FB2B 75 0C JNZ SHORT 0012FB39 0012FB2D 8A4C30 03 MOV CL,BYTE PTR DS:[EAX+ESI+3] 0012FB31 3A8D 73FFFFFF CMP CL,BYTE PTR SS:[EBP-8D] 0012FB37 74 0E JE SHORT 0012FB47 0012FB39 8D4F FF LEA ECX,DWORD PTR DS:[EDI-1] 0012FB3C 3BC1 CMP EAX,ECX 0012FB3E 74 70 JE SHORT 0012FBB0 0012FB40 40 INC EAX 0012FB41 3BC7 CMP EAX,EDI 0012FB43 ^72 C2 JB SHORT 0012FB07 0012FB45 EB 2A JMP SHORT 0012FB71 0012FB47 33FF XOR EDI,EDI 0012FB49 03C6 ADD EAX,ESI 0012FB4B 8A4C38 14 MOV CL,BYTE PTR DS:[EAX+EDI+14] 0012FB4F 888C3D C4C2FFFF MOV BYTE PTR SS:[EBP+EDI-3D3C],CL 0012FB56 47 INC EDI 0012FB57 81FF AC3A0000 CMP EDI,3AAC 0012FB5D ^72 EC JB SHORT 0012FB4B [/c] Further, when it jumps to that page, it creates itself in a suspended state with CREATION flags set at 0x40, which is the CREATE_SUSPENDED flag. It injects itself in that suspended process using API calls such as WriteProcessMemory and VirtualAllocEx. Second Stage In the second stage of malware, it runs inside its own image at the OEP of the image; we can see it’s trying to get EIP by the CALL POP method used by shellcodes: [c] 00400160 > $ E8 00000000 CALL ARTIC.00400165 00400165 $ 5B POP EBX 00400166 . 83EB 05 SUB EBX,5 [/c] And following that, it tries to get the base address of DLLs loaded: [c] 0040016C . 64:8B12 MOV EDX,DWORD PTR FS:[EDX] 0040016F . 8B52 0C MOV EDX,DWORD PTR DS:[EDX+C] 00400172 . 8B52 0C MOV EDX,DWORD PTR DS:[EDX+C] 00400175 . 8B12 MOV EDX,DWORD PTR DS:[EDX] 00400177 . 8B12 MOV EDX,DWORD PTR DS:[EDX] 00400179 . 8D42 18 LEA EAX,DWORD PTR DS:[EDX+18] 0040017C . 8B28 MOV EBP,DWORD PTR DS:[EAX] [/c] On-the-fly decryption is done using a one-byte xor key: [c] 004001A1 > AC LODS BYTE PTR DS:[ESI] 004001A2 . 32C2 XOR AL,DL 004001A4 . AA STOS BYTE PTR ES:[EDI] 004001A5 .^E2 FA LOOPD SHORT ARTIC.004001A1 [/c] Space is allocated on the heap to copy the decrypted region with read, write, and execute permissions: [c] 0012FFB0 004001BB »#@. /CALL to VirtualAlloc from ARTIC.004001B5 0012FFB4 00000000 …. |Address = NULL 0012FFB8 00004000 .@.. |Size = 4000 (16384.) 0012FFBC 00003000 .0.. |AllocationType = MEM_COMMIT|MEM_RESERVE 0012FFC0 00000040 @… Protect = PAGE_EXECUTE_READWRITE [/c] where the data is decompressed using a custom decompression routine: [c] 004001BB . 8983 00090000 MOV DWORD PTR DS:[EBX+900],EAX 004001C1 . 89C5 MOV EBP,EAX 004001C3 . 89C1 MOV ECX,EAX 004001C5 . 8D83 21120000 LEA EAX,DWORD PTR DS:[EBX+1221] 004001CB . E8 59010000 CALL [/c] The data happens to be a valid PE image present at the allocated heap: 00320000 4D 5A 50 00 02 00 MZP.#. The image is copied into the newly allocated heap: [c] 004001F2 . 8B4E 54 MOV ECX,DWORD PTR DS:[ESI+54] ; Size 004001F5 . 81EE 00010000 SUB ESI,100 004001FB . 89C7 MOV EDI,EAX 004001FD . FC CLD 004001FE . F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 00400200 . 61 POPAD 00400208 . 0FB64E 06 MOVZX ECX,BYTE PTR DS:[ESI+6] ; Get Number of sections 0040020C . 83F9 00 CMP ECX,0 ; if no of sections are zero 0040020F . 0F8E B7000000 JLE ARTIC.004002CC 00400215 . 81C6 F8000000 ADD ESI,0F8 0040021B > 51 PUSH ECX ; Save ECX 0040021C . 8B4E 10 MOV ECX,DWORD PTR DS:[ESI+10] ; Get Size of Raw data 0040021F . 85C9 TEST ECX,ECX 00400221 . 7E 0F JLE SHORT ARTIC.00400232 ; If Size of raw data is zero 00400223 . 56 PUSH ESI 00400224 . 8B7E 0C MOV EDI,DWORD PTR DS:[ESI+C] ; Get Virtual Address 00400227 . 01C7 ADD EDI,EAX ; Add Base + Virtual Address 00400229 . 8B76 14 MOV ESI,DWORD PTR DS:[ESI+14] ; Get Pointer to raw Data 0040022C . 01EE ADD ESI,EBP ; Goto Section Data 0040022E . FC CLD 0040022F . F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>; Copy Section Data to virtual Address 00400231 . 5E POP ESI 00400232 > 83C6 28 ADD ESI,28 ; Hop to new section header 00400235 . 59 POP ECX 00400236 .^E2 E3 LOOPD SHORT ARTIC.0040021B [/c] This code basically traverses all the sections and copies them into the desired virtual addresses, as Windows loader does . This section ends when all the sections are traversed. After loading all the sections at the desired offset address, they must be relocated at that loaded address. The code section makes use of base relocations to do it. Base relocations are define in winnt.h as: [c] typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; } IMAGE_BASE_RELOCATION; [/c] typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; VirtualAddress contains the virtual address of the blocks to be relocated. SizeofBlock is the total size of the blocks + the size of _IMAGE_BASE_RELOCATION. TypeOffset are words that immediately follow after the first four bits of it represent the type and the remaining 12 bits represent the offset from the VirtualAddress to the place where relocations are to be performed. [c] 00400239 . 60 PUSHAD 0040023A . 89C6 MOV ESI,EAX ; Mov to base 0040023C . 89EB MOV EBX,EBP ; mov to base of data 0040023E . 8B43 3C MOV EAX,DWORD PTR DS:[EBX+3C] ; move offset of pe signature 00400241 . 8D4418 18 LEA EAX,DWORD PTR DS:[EAX+EBX+18] ; Image structure 00400245 . 8B50 1C MOV EDX,DWORD PTR DS:[EAX+1C] ; Get base 00400248 . 89F3 MOV EBX,ESI 0040024A . 8B43 3C MOV EAX,DWORD PTR DS:[EBX+3C] 0040024D . 8D4418 18 LEA EAX,DWORD PTR DS:[EAX+EBX+18] ; Get Loaded Base 00400251 . 29DA SUB EDX,EBX ; Calculate Delta 00400253 . 8DB0 88000000 LEA ESI,DWORD PTR DS:[EAX+88] ; get relocation table 00400259 . 8B36 MOV ESI,DWORD PTR DS:[ESI] 0040025B . 85F6 TEST ESI,ESI 0040025D . 74 2E JE SHORT ARTIC.0040028D ; if no reloc 0040025F . 01DE ADD ESI,EBX ; get reloc section 00400261 > 833E 00 CMP DWORD PTR DS:[ESI],0 ; if no relocations present 00400264 . 74 27 JE SHORT ARTIC.0040028D 00400266 . 8B3E MOV EDI,DWORD PTR DS:[ESI] ; Get VirtualAddress 00400268 . 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+4] ; Get SizeOfBlock 0040026B . 83E9 08 SUB ECX,8 ; Sub sizeof(struct) 0040026E . D1E9 SHR ECX,1 ; Get No of Words 00400270 . 83C6 08 ADD ESI,8 ; Get TypeOffsety 00400273 . 31C0 XOR EAX,EAX 00400275 > 66:AD LODS WORD PTR DS:[ESI] ; Load TypeOffset into Eax 00400277 . A9 00300000 TEST EAX,3000 ; Check If no Relocations are present 0040027C . 74 0B JE SHORT ARTIC.00400289 0040027E . 25 FF0F0000 AND EAX,0FFF ; Strip Type for x86 it is constant 00400283 . 01D8 ADD EAX,EBX ; Add Virtual Address 00400285 . 01F8 ADD EAX,EDI ; Add Offset 00400287 . 2910 SUB DWORD PTR DS:[EAX],EDX ; Subtract Delta From DWORD 00400289 > ^E2 EA LOOPD SHORT ARTIC.00400275 ; Loop 0040028B .^EB D4 JMP SHORT ARTIC.00400261 [/c] After fixing the relocations, it finds the export address table, looks for “work” export, and resumes execution from there: [c] 0040028D > 61 POPAD 0040028E . 89C5 MOV EBP,EAX 00400290 . 8DBB 00120000 LEA EDI,DWORD PTR DS:[EBX+1200] ; add displacement 00400296 . 0380 78010000 ADD EAX,DWORD PTR DS:[EAX+178] ; Get EAT 0040029C . 8B48 14 MOV ECX,DWORD PTR DS:[EAX+14] ; Get First Exploit Offset 0040029F . 0B48 18 OR ECX,DWORD PTR DS:[EAX+18] 004002A2 . 74 28 JE SHORT ARTIC.004002CC 004002A4 . 8B70 20 MOV ESI,DWORD PTR DS:[EAX+20] 004002A7 . 01EE ADD ESI,EBP 004002A9 . 8B50 1C MOV EDX,DWORD PTR DS:[EAX+1C] 004002AC . 01EA ADD EDX,EBP 004002AE . 8B12 MOV EDX,DWORD PTR DS:[EDX] 004002B0 . 01EA ADD EDX,EBP 004002B2 . 8B0F MOV ECX,DWORD PTR DS:[EDI] 004002B4 . 8B36 MOV ESI,DWORD PTR DS:[ESI] 004002B6 . 01EE ADD ESI,EBP 004002B8 . 3B0E CMP ECX,DWORD PTR DS:[ESI] 004002BA . 75 10 JNZ SHORT ARTIC.004002CC 004002BC . 8DBB 14120000 LEA EDI,DWORD PTR DS:[EBX+1214] 004002C2 . 57 PUSH EDI 004002C3 . 8DBB 00100000 LEA EDI,DWORD PTR DS:[EBX+1000] 004002C9 . 57 PUSH EDI ; Push Path 004002CA . FFD2 CALL EDX ; Call Export Work [/c] Attackers using this method of totally implementing windows loader malwares remain stealthy by hiding their code in a legitimate process.