Rizin
unix-like reverse engineering framework and cli tools
pe_hdr.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2008-2019 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2008-2019 inisider <inisider@gmail.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include "pe.h"
7 
8 static bool read_dos_header_aux(RzBuffer *buf, ut64 *offset, PE_(image_dos_header) * header) {
9  return rz_buf_read_le16_offset(buf, offset, &header->e_magic) &&
13  rz_buf_read_le16_offset(buf, offset, &header->e_cparhdr) &&
14  rz_buf_read_le16_offset(buf, offset, &header->e_minalloc) &&
15  rz_buf_read_le16_offset(buf, offset, &header->e_maxalloc) &&
21  rz_buf_read_le16_offset(buf, offset, &header->e_lfarlc) &&
23 }
24 
25 bool PE_(read_dos_header)(RzBuffer *buf, PE_(image_dos_header) * header) {
26  ut64 offset = 0;
28  return false;
29  }
30 
31  for (size_t i = 0; i < 4; i++) {
32  if (!rz_buf_read_le16_offset(buf, &offset, &header->e_res[i])) {
33  return false;
34  }
35  }
36 
37  if (!rz_buf_read_le16_offset(buf, &offset, &header->e_oemid)) {
38  return false;
39  }
40 
41  if (!rz_buf_read_le16_offset(buf, &offset, &header->e_oeminfo)) {
42  return false;
43  }
44 
45  for (size_t i = 0; i < 10; i++) {
46  if (!rz_buf_read_le16_offset(buf, &offset, &header->e_res2[i])) {
47  return false;
48  }
49  }
50 
51  if (!rz_buf_read_le32_offset(buf, &offset, &header->e_lfanew)) {
52  return false;
53  }
54  return true;
55 }
56 
57 static bool read_nt_headers_aux(RzBuffer *buf, ut64 *offset, PE_(image_nt_headers) * headers) {
58  return rz_buf_read_le32_offset(buf, offset, &headers->Signature) &&
59  rz_buf_read_le16_offset(buf, offset, &headers->file_header.Machine) &&
60  rz_buf_read_le16_offset(buf, offset, &headers->file_header.NumberOfSections) &&
61  rz_buf_read_le32_offset(buf, offset, &headers->file_header.TimeDateStamp) &&
62  rz_buf_read_le32_offset(buf, offset, &headers->file_header.PointerToSymbolTable) &&
63  rz_buf_read_le32_offset(buf, offset, &headers->file_header.NumberOfSymbols) &&
64  rz_buf_read_le16_offset(buf, offset, &headers->file_header.SizeOfOptionalHeader) &&
65  rz_buf_read_le16_offset(buf, offset, &headers->file_header.Characteristics) &&
66  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.Magic) &&
67  rz_buf_read8_offset(buf, offset, &headers->optional_header.MajorLinkerVersion) &&
68  rz_buf_read8_offset(buf, offset, &headers->optional_header.MinorLinkerVersion) &&
69  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfCode) &&
70  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfInitializedData) &&
71  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfUninitializedData) &&
72  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.AddressOfEntryPoint) &&
73  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.BaseOfCode) &&
74 #ifdef RZ_BIN_PE64
75  rz_buf_read_le64_offset(buf, offset, &headers->optional_header.ImageBase) &&
76 #else
77  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.BaseOfData) &&
78  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.ImageBase) &&
79 #endif
80  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SectionAlignment) &&
81  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.FileAlignment) &&
82  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MajorOperatingSystemVersion) &&
83  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MinorOperatingSystemVersion) &&
84  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MajorImageVersion) &&
85  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MinorImageVersion) &&
86  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MajorSubsystemVersion) &&
87  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.MinorSubsystemVersion) &&
88  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.Win32VersionValue) &&
89  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfImage) &&
90  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfHeaders) &&
91  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.CheckSum) &&
92  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.Subsystem) &&
93  rz_buf_read_le16_offset(buf, offset, &headers->optional_header.DllCharacteristics) &&
94 #ifdef RZ_BIN_PE64
95  rz_buf_read_le64_offset(buf, offset, &headers->optional_header.SizeOfStackReserve) &&
96  rz_buf_read_le64_offset(buf, offset, &headers->optional_header.SizeOfStackCommit) &&
97  rz_buf_read_le64_offset(buf, offset, &headers->optional_header.SizeOfHeapReserve) &&
98  rz_buf_read_le64_offset(buf, offset, &headers->optional_header.SizeOfHeapCommit) &&
99 #else
100  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfStackReserve) &&
101  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfStackCommit) &&
102  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfHeapReserve) &&
103  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.SizeOfHeapCommit) &&
104 #endif
105  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.LoaderFlags) &&
106  rz_buf_read_le32_offset(buf, offset, &headers->optional_header.NumberOfRvaAndSizes);
107 }
108 
109 bool PE_(read_nt_headers)(RzBuffer *buf, ut64 addr, PE_(image_nt_headers) * headers) {
110  ut64 offset = addr;
111  if (!read_nt_headers_aux(buf, &offset, headers)) {
112  return false;
113  }
114 
115  for (size_t i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES; i++) {
116  if (!rz_buf_read_le32_offset(buf, &offset, &headers->optional_header.DataDirectory[i].VirtualAddress) || !rz_buf_read_le32_offset(buf, &offset, &headers->optional_header.DataDirectory[i].Size)) {
117  return false;
118  }
119  }
120 
121  return true;
122 }
123 
125  if (!(bin->dos_header = malloc(sizeof(PE_(image_dos_header))))) {
126  rz_sys_perror("malloc (dos header)");
127  return false;
128  }
129  if (!PE_(read_dos_header)(bin->b, bin->dos_header)) {
130  RZ_LOG_INFO("read (dos header)\n");
131  return false;
132  }
133  sdb_num_set(bin->kv, "pe_dos_header.offset", 0, 0);
134  sdb_set(bin->kv, "pe_dos_header.format", "[2]zwwwwwwwwwwwww[4]www[10]wx"
135  " e_magic e_cblp e_cp e_crlc e_cparhdr e_minalloc e_maxalloc"
136  " e_ss e_sp e_csum e_ip e_cs e_lfarlc e_ovno e_res e_oemid"
137  " e_oeminfo e_res2 e_lfanew",
138  0);
139  if (bin->dos_header->e_lfanew > (unsigned int)bin->size) {
140  RZ_LOG_INFO("Invalid e_lfanew field\n");
141  return false;
142  }
143  if (!(bin->nt_headers = malloc(sizeof(PE_(image_nt_headers))))) {
144  rz_sys_perror("malloc (nt header)");
145  return false;
146  }
147  bin->nt_header_offset = bin->dos_header->e_lfanew;
148  if (!PE_(read_nt_headers)(bin->b, bin->dos_header->e_lfanew, bin->nt_headers)) {
149  RZ_LOG_INFO("read (nt header)\n");
150  return false;
151  }
152  sdb_set(bin->kv, "pe_magic.cparse", "enum pe_magic { IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b, IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b, IMAGE_ROM_OPTIONAL_HDR_MAGIC=0x107 };", 0);
153  sdb_set(bin->kv, "pe_subsystem.cparse", "enum pe_subsystem { IMAGE_SUBSYSTEM_UNKNOWN=0, IMAGE_SUBSYSTEM_NATIVE=1, IMAGE_SUBSYSTEM_WINDOWS_GUI=2, "
154  " IMAGE_SUBSYSTEM_WINDOWS_CUI=3, IMAGE_SUBSYSTEM_OS2_CUI=5, IMAGE_SUBSYSTEM_POSIX_CUI=7, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI=9, "
155  " IMAGE_SUBSYSTEM_EFI_APPLICATION=10, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER=11, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER=12, "
156  " IMAGE_SUBSYSTEM_EFI_ROM=13, IMAGE_SUBSYSTEM_XBOX=14, IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION=16 };",
157  0);
158  sdb_set(bin->kv, "pe_dllcharacteristics.cparse", "enum pe_dllcharacteristics { IMAGE_LIBRARY_PROCESS_INIT=0x0001, IMAGE_LIBRARY_PROCESS_TERM=0x0002, "
159  " IMAGE_LIBRARY_THREAD_INIT=0x0004, IMAGE_LIBRARY_THREAD_TERM=0x0008, IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA=0x0020, "
160  " IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE=0x0040, IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY=0x0080, "
161  " IMAGE_DLLCHARACTERISTICS_NX_COMPAT=0x0100, IMAGE_DLLCHARACTERISTICS_NO_ISOLATION=0x0200,IMAGE_DLLCHARACTERISTICS_NO_SEH=0x0400, "
162  " IMAGE_DLLCHARACTERISTICS_NO_BIND=0x0800, IMAGE_DLLCHARACTERISTICS_APPCONTAINER=0x1000, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER=0x2000, "
163  " IMAGE_DLLCHARACTERISTICS_GUARD_CF=0x4000, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE=0x8000};",
164  0);
165 #if RZ_BIN_PE64
166  sdb_num_set(bin->kv, "pe_nt_image_headers64.offset", bin->dos_header->e_lfanew, 0);
167  sdb_set(bin->kv, "pe_nt_image_headers64.format", "[4]z?? signature (pe_image_file_header)fileHeader (pe_image_optional_header64)optionalHeader", 0);
168  sdb_set(bin->kv, "pe_image_optional_header64.format", "[2]Ebbxxxxxqxxwwwwwwxxxx[2]E[2]Bqqqqxx[16]?"
169  " (pe_magic)magic majorLinkerVersion minorLinkerVersion sizeOfCode sizeOfInitializedData"
170  " sizeOfUninitializedData addressOfEntryPoint baseOfCode imageBase"
171  " sectionAlignment fileAlignment majorOperatingSystemVersion minorOperatingSystemVersion"
172  " majorImageVersion minorImageVersion majorSubsystemVersion minorSubsystemVersion"
173  " win32VersionValue sizeOfImage sizeOfHeaders checkSum (pe_subsystem)subsystem (pe_dllcharacteristics)dllCharacteristics"
174  " sizeOfStackReserve sizeOfStackCommit sizeOfHeapReserve sizeOfHeapCommit loaderFlags"
175  " numberOfRvaAndSizes (pe_image_data_directory)dataDirectory",
176  0);
177 #else
178  sdb_num_set(bin->kv, "pe_nt_image_headers32.offset", bin->dos_header->e_lfanew, 0);
179  sdb_set(bin->kv, "pe_nt_image_headers32.format", "[4]z?? signature (pe_image_file_header)fileHeader (pe_image_optional_header32)optionalHeader", 0);
180  sdb_set(bin->kv, "pe_image_optional_header32.format", "[2]Ebbxxxxxxxxxwwwwwwxxxx[2]E[2]Bxxxxxx[16]?"
181  " (pe_magic)magic majorLinkerVersion minorLinkerVersion sizeOfCode sizeOfInitializedData"
182  " sizeOfUninitializedData addressOfEntryPoint baseOfCode baseOfData imageBase"
183  " sectionAlignment fileAlignment majorOperatingSystemVersion minorOperatingSystemVersion"
184  " majorImageVersion minorImageVersion majorSubsystemVersion minorSubsystemVersion"
185  " win32VersionValue sizeOfImage sizeOfHeaders checkSum (pe_subsystem)subsystem (pe_dllcharacteristics)dllCharacteristics"
186  " sizeOfStackReserve sizeOfStackCommit sizeOfHeapReserve sizeOfHeapCommit loaderFlags numberOfRvaAndSizes"
187  " (pe_image_data_directory)dataDirectory",
188  0);
189 #endif
190  sdb_set(bin->kv, "pe_machine.cparse", "enum pe_machine { IMAGE_FILE_MACHINE_I386=0x014c, IMAGE_FILE_MACHINE_IA64=0x0200, IMAGE_FILE_MACHINE_AMD64=0x8664 };", 0);
191  sdb_set(bin->kv, "pe_characteristics.cparse", "enum pe_characteristics { "
192  " IMAGE_FILE_RELOCS_STRIPPED=0x0001, IMAGE_FILE_EXECUTABLE_IMAGE=0x0002, IMAGE_FILE_LINE_NUMS_STRIPPED=0x0004, "
193  " IMAGE_FILE_LOCAL_SYMS_STRIPPED=0x0008, IMAGE_FILE_AGGRESIVE_WS_TRIM=0x0010, IMAGE_FILE_LARGE_ADDRESS_AWARE=0x0020, "
194  " IMAGE_FILE_BYTES_REVERSED_LO=0x0080, IMAGE_FILE_32BIT_MACHINE=0x0100, IMAGE_FILE_DEBUG_STRIPPED=0x0200, "
195  " IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP=0x0400, IMAGE_FILE_NET_RUN_FROM_SWAP=0x0800, IMAGE_FILE_SYSTEM=0x1000, "
196  " IMAGE_FILE_DLL=0x2000, IMAGE_FILE_UP_SYSTEM_ONLY=0x4000, IMAGE_FILE_BYTES_REVERSED_HI=0x8000 };",
197  0);
198  sdb_set(bin->kv, "pe_image_file_header.format", "[2]Ewtxxw[2]B"
199  " (pe_machine)machine numberOfSections timeDateStamp pointerToSymbolTable"
200  " numberOfSymbols sizeOfOptionalHeader (pe_characteristics)characteristics",
201  0);
202  sdb_set(bin->kv, "pe_image_data_directory.format", "xx virtualAddress size", 0);
203 
204  // adding compile time to the SDB
205  {
206  sdb_num_set(bin->kv, "image_file_header.TimeDateStamp", bin->nt_headers->file_header.TimeDateStamp, 0);
207  char *timestr = rz_time_stamp_to_str(bin->nt_headers->file_header.TimeDateStamp);
208  sdb_set_owned(bin->kv, "image_file_header.TimeDateStamp_string", timestr, 0);
209  }
210  bin->optional_header = &bin->nt_headers->optional_header;
211  bin->data_directory = (PE_(image_data_directory *)) & bin->optional_header->DataDirectory;
212 
213  if (bin->dos_header->e_magic != 0x5a4d || // "MZ"
214  (bin->nt_headers->Signature != 0x4550 && // "PE"
215  /* Check also for Phar Lap TNT DOS extender PL executable */
216  bin->nt_headers->Signature != 0x4c50)) { // "PL"
217  return false;
218  }
219  return true;
220 }
lzma_index ** i
Definition: index.h:629
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
void * malloc(size_t size)
Definition: malloc.c:123
#define header(is_bt, len_min, ret_op)
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
#define RzBinPEObj
Definition: pe.h:126
bool PE_() read_nt_headers(RzBuffer *buf, ut64 addr, PE_(image_nt_headers) *headers)
Definition: pe_hdr.c:109
int PE_() bin_pe_init_hdr(RzBinPEObj *bin)
Definition: pe_hdr.c:124
static bool read_dos_header_aux(RzBuffer *buf, ut64 *offset, PE_(image_dos_header) *header)
Definition: pe_hdr.c:8
static bool read_nt_headers_aux(RzBuffer *buf, ut64 *offset, PE_(image_nt_headers) *headers)
Definition: pe_hdr.c:57
bool PE_() read_dos_header(RzBuffer *buf, PE_(image_dos_header) *header)
Definition: pe_hdr.c:25
#define PE_(name)
Definition: pe_specs.h:23
#define PE_IMAGE_DIRECTORY_ENTRIES
Definition: pe_specs.h:142
#define rz_buf_read_le16_offset(b, offset, result)
Definition: rz_buf.h:276
#define rz_buf_read_le64_offset(b, offset, result)
Definition: rz_buf.h:278
#define rz_buf_read_le32_offset(b, offset, result)
Definition: rz_buf.h:277
#define rz_buf_read8_offset(b, offset, result)
Definition: rz_buf.h:274
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
RZ_API RZ_OWN char * rz_time_stamp_to_str(ut32 timestamp)
Converts an unix epoch timestamp to string.
Definition: time.c:143
#define rz_sys_perror(x)
Definition: rz_types.h:336
RZ_API int sdb_set_owned(Sdb *s, const char *key, char *val, ut32 cas)
Definition: sdb.c:607
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
Definition: malloc.c:26
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58