Inject Your Code to a Portable Executable File

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

0 Preface

You might demand to comprehend the ways a virus program injects its procedure into the interior of a portable executable file and corrupts it, or you are interested in implementing a packer or a protector to encrypt the data of your portable executable (PE) file. This article is committed to represent a brief discussion to realize the performance that is accomplished by EXE tools or some kinds of mal-ware.

You can employ this article’s source code to create your custom EXE builder. It could be used to make an EXE protector in the right way, or with the wrong intention, to spread a virus. However, my purpose of writing this article has been the first application, so I will not be responsible for the immoral usage of these methods.

1 Prerequisites

There are no specific mandatory prerequisites to follow the topics in this article. If you are familiar with a debugger and also the portable file format, I suggest you to drop to Sections 2 and 3; the whole of these sections has been made for people who don’t have any knowledge regarding the EXE file format or debuggers.

2 Portable Executable File Format

The Portable Executable file format was defined to provide the best way for the Windows Operating System to execute code and also to store the essential data that is needed to run a program—for example constant data, variable data, import library links, and resource data. It consists of MS-DOS file information, Windows NT file information, Section Headers, and Section images, as shown in Table 1.

2.1 The MS-DOS data

These data let you remember the first days of developing the Windows Operating System. You were at the beginning of a way to achieve a complete Operating System such as Windows NT 3.51 (I mean, Win3.1, Win95, Win98 were not perfect OSs). The MS-DOS data causes that your executable file to have the performance inside MS-DOS and the MS-DOS Stub program lets it display: “This program can not be run in MS-DOS mode” or “This program can be run only in Windows mode”, or some things like these comments when you try to run a Windows EXE file inside MS-DOS 6.0, where there is no footstep of Windows. Thus, this data is reserved for the code to indicate these comments in the MS-DOS operating system. The most interesting part of the MS-DOS data is “MZ“! Can you believe, it refers to the name of “Mark Zbikowski“, one of the first Microsoft programmers?

To me, only the offset of the PE signature in the MS-DOS data is important, so I can use it to find the position of the Windows NT data. I just recommend that you take a look at Table 1, and then observe the structure of IMAGE_DOS_HEADER in the <winnt.h> header in the <Microsoft Visual Studio .net path>\VC7\PlatformSDK\include\ folder or the <Microsoft Visual Studio 6.0 path>\VC98\include\ folder. I do not know why the Microsoft team has forgotten to provide some comment about this structure in the MSDN library!


typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header “MZ”
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in
// paragraphs
WORD e_minalloc; // Minimum extra paragraphs
// needed
WORD e_maxalloc; // Maximum extra paragraphs
// needed
WORD e_ss; // Initial (relative) SS
// value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS
// value
WORD e_lfarlc; // File address of relocation
// table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier
// (for e_oeminfo)
WORD e_oeminfo; // OEM information;
// e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of the new
// exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

e_lfanew is the offset that refers to the position of the Windows NT data. I have provided a program to obtain the header information from an EXE file and to display it to you. To use the program, just try:

PE Viewer

This sample is useful for the whole of this article.

Table 1: Portable Executable file format structure






































































































MS-DOS
information
IMAGE_DOS_
HEADER
DOS EXE Signature
00000000  ASCII “MZ”
00000002 DW 0090
00000004 DW 0003
00000006 DW 0000
00000008 DW 0004
0000000A DW 0000
0000000C DW FFFF
0000000E DW 0000
00000010 DW 00B8
00000012 DW 0000
00000014 DW 0000
00000016 DW 0000
00000018 DW 0040
0000001A DW 0000
0000001C DB 00
b&
b&
0000003B DB 00
0000003C DD 000000F0
DOS_PartPag
DOS_PageCnt
DOS_ReloCnt
DOS_HdrSize
DOS_MinMem
DOS_MaxMem
DOS_ReloSS
DOS_ExeSP
DOS_ChkSum
DOS_ExeIPP
DOS_ReloCS
DOS_TablOff
DOS_Overlay
b&
Reserved words
b&
Offset to PE signature
MS-DOS Stub
Program
00000040  ..B:..B4.C
!B8\LC
!This program canno
00000060 t be run in DOS mode.
…$…….
Windows NT
information

IMAGE_
NT_HEADERS

Signature PE signature (PE)
000000F0  ASCII “PE”
IMAGE_
FILE_HEADER
Machine
000000F4  DW 014C
000000F6 DW 0003
000000F8 DD 3B7D8410
000000FC DD 00000000
00000100 DD 00000000
00000104 DW 00E0
00000106 DW 010F
NumberOfSections
TimeDateStamp
PointerToSymbolTable
NumberOfSymbols
SizeOfOptionalHeader
Characteristics
IMAGE_
OPTIONAL_
HEADER32
MagicNumber
00000108  DW 010B
0000010A DB 07
0000010B DB 00
0000010C DD 00012800
00000110 DD 00009C00
00000114 DD 00000000
00000118 DD 00012475
0000011C DD 00001000
00000120 DD 00014000
00000124 DD 01000000
00000128 DD 00001000
0000012C DD 00000200
00000130 DW 0005
00000132 DW 0001
00000134 DW 0005
00000136 DW 0001
00000138 DW 0004
0000013A DW 0000
0000013C DD 00000000
00000140 DD 0001F000
00000144 DD 00000400
00000148 DD 0001D7FC
0000014C DW 0002
0000014E DW 8000
00000150 DD 00040000
00000154 DD 00001000
00000158 DD 00100000
0000015C DD 00001000
00000160 DD 00000000
00000164 DD 00000010

MajorLinkerVersion
MinorLinkerVersion
SizeOfCode
SizeOfInitializedData
SizeOfUninitializedData
AddressOfEntryPoint
BaseOfCode
BaseOfData
ImageBase
SectionAlignment
FileAlignment
MajorOSVersion
MinorOSVersion
MajorImageVersion
MinorImageVersion
MajorSubsystemVersion
MinorSubsystemVersion
Reserved
SizeOfImage
SizeOfHeaders
CheckSum
Subsystem
DLLCharacteristics
SizeOfStackReserve
SizeOfStackCommit
SizeOfHeapReserve
SizeOfHeapCommit
LoaderFlags
NumberOfRvaAndSizes
IMAGE_
DATA_DIRECTORY[16]
Export Table
Import Table
Resource Table
Exception Table
Certificate File
Relocation Table
Debug Data
Architecture Data
Global Ptr
TLS Table
Load Config Table
Bound Import Table
Import Address Table
Delay Import Descriptor
COM+ Runtime Header
Reserved
Sections
information
IMAGE_
SECTION_
HEADER[0]
Name[8]
000001E8  ASCII“.text”
000001F0 DD 000126B0
000001F4 DD 00001000
000001F8 DD 00012800
000001FC DD 00000400
00000200 DD 00000000
00000204 DD 00000000
00000208 DW 0000
0000020A DW 0000
0000020C DD 60000020
CODE|EXECUTE|READ
VirtualSize
VirtualAddress
SizeOfRawData
PointerToRawData
PointerToRelocations
PointerToLineNumbers
NumberOfRelocations
NumberOfLineNumbers
Characteristics
b&
b&
b&
IMAGE_
SECTION_
HEADER[n]
00000210  ASCII“.data”; SECTION
00000218 DD 0000101C ; VirtualSize = 0x101C
0000021C DD 00014000 ; VirtualAddress = 0x14000
00000220 DD 00000A00 ; SizeOfRawData = 0xA00
00000224 DD 00012C00 ; PointerToRawData = 0x12C00
00000228 DD 00000000 ; PointerToRelocations = 0x0
0000022C DD 00000000 ; PointerToLineNumbers = 0x0
00000230 DW 0000 ; NumberOfRelocations = 0x0
00000232 DW 0000 ; NumberOfLineNumbers = 0x0
00000234 DD C0000040 ; Characteristics =
INITIALIZED_DATA|READ|WRITE
00000238 ASCII“.rsrc”; SECTION
00000240 DD 00008960 ; VirtualSize = 0x8960
00000244 DD 00016000 ; VirtualAddress = 0x16000
00000248 DD 00008A00 ; SizeOfRawData = 0x8A00
0000024C DD 00013600 ; PointerToRawData = 0x13600
00000250 DD 00000000 ; PointerToRelocations = 0x0
00000254 DD 00000000 ; PointerToLineNumbers = 0x0
00000258 DW 0000 ; NumberOfRelocations = 0x0
0000025A DW 0000 ; NumberOfLineNumbers = 0x0
0000025C DD 40000040 ; Characteristics =
INITIALIZED_DATA|READ
SECTION[0]
00000400  EA 22 DD 77 D7 23 DD 77  C*”C.wC.#C.w
00000408 9A 18 DD 77 00 00 00 00 E!.C.w….
00000410 2E 1E C7 77 83 1D C7 77 ..C.wF..C.w
00000418 FF 1E C7 77 00 00 00 00 C?.C.w….
00000420 93 9F E7 77 D8 05 E8 77 b.E8C’wC..C(w
00000428 FD A5 E7 77 AD A9 E9 77 C=B%C’w&shy;B)C)w
00000430 A3 36 E7 77 03 38 E7 77 B#6C’w.8C’w
00000438 41 E3 E6 77 60 8D E7 77 AC#C&w`B
C’w
00000440 E6 1B E6 77 2B 2A E7 77 C&.C&w+*C’w
00000448 7A 17 E6 77 79 C8 E6 77 z.C&wyC.C&w
00000450 14 1B E7 77 C1 30 E7 77 ..C’wC.0C’w
b&
b&
b&
b&
SECTION[n]
b&
0001BF00 63 00 2E 00 63 00 68 00 c…c.h.
0001BF08 6D 00 0A 00 43 00 61 00 m…C.a.
0001BF10 6C 00 63 00 75 00 6C 00 l.c.u.l.
0001BF18 61 00 74 00 6F 00 72 00 a.t.o.r.
0001BF20 11 00 4E 00 6F 00 74 00 ..N.o.t.
0001BF28 20 00 45 00 6E 00 6F 00 .E.n.o.
0001BF30 75 00 67 00 68 00 20 00 u.g.h. .
0001BF38 4D 00 65 00 6D 00 6F 00 M.e.m.o.
0001BF40 72 00 79 00 00 00 00 00 r.y…..
0001BF48 00 00 00 00 00 00 00 00 ……..
0001BF50 00 00 00 00 00 00 00 00 ……..
0001BF58 00 00 00 00 00 00 00 00 ……..
0001BF60 00 00 00 00 00 00 00 00 ……..
0001BF68 00 00 00 00 00 00 00 00 ……..
0001BF70 00 00 00 00 00 00 00 00 ……..
0001BF78 00 00 00 00 00 00 00 00 ……..

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read