Rizin
unix-like reverse engineering framework and cli tools
bin_pe64.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 #define RZ_BIN_PE64 1
5 #include "bin_pe.inc"
6 
7 static bool check_buffer(RzBuffer *b) {
9  if (length <= 0x3d) {
10  return false;
11  }
12 
13  ut16 idx;
14  if (!rz_buf_read_le16_at(b, 0x3c, &idx)) {
15  return false;
16  }
17 
18  if (idx + 26 < length) {
19  /* Here PE signature for usual PE files
20  * and PL signature for Phar Lap TNT DOS extender 32bit executables
21  */
22  ut8 buf[2];
23  rz_buf_read_at(b, 0, buf, sizeof(buf));
24  if (!memcmp(buf, "MZ", 2)) {
25  rz_buf_read_at(b, idx, buf, sizeof(buf));
26  // TODO: Add one more indicator, to prevent false positives
27  // if (!memcmp (buf, "PL", 2)) { return true; }
28  if (!memcmp(buf, "PE", 2)) {
29  rz_buf_read_at(b, idx + 0x18, buf, sizeof(buf));
30  return !memcmp(buf, "\x0b\x02", 2);
31  }
32  }
33  }
34  return false;
35 }
36 
37 static RzList *fields(RzBinFile *bf) {
39  if (!ret) {
40  return NULL;
41  }
42 
43 #define ROWL(nam, siz, val, fmt) \
44  rz_list_append(ret, rz_bin_field_new(addr, addr, siz, nam, sdb_fmt("0x%08" PFMT64x, (ut64)val), fmt, false));
45 
46  struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
47  ut64 addr = bin->rich_header_offset ? bin->rich_header_offset : 128;
48 
49  RzListIter *it;
50  Pe_image_rich_entry *rich;
51  rz_list_foreach (bin->rich_entries, it, rich) {
52  rz_list_append(ret, rz_bin_field_new(addr, addr, 0, "RICH_ENTRY_NAME", strdup(rich->productName), "s", false));
53  ROWL("RICH_ENTRY_ID", 2, rich->productId, "x");
54  addr += 2;
55  ROWL("RICH_ENTRY_VERSION", 2, rich->minVersion, "x");
56  addr += 2;
57  ROWL("RICH_ENTRY_TIMES", 4, rich->timesUsed, "x");
58  addr += 4;
59  }
60 
61  ROWL("Signature", 4, bin->nt_headers->Signature, "x");
62  addr += 4;
63  ROWL("Machine", 2, bin->nt_headers->file_header.Machine, "x");
64  addr += 2;
65  ROWL("NumberOfSections", 2, bin->nt_headers->file_header.NumberOfSections, "x");
66  addr += 2;
67  ROWL("TimeDateStamp", 4, bin->nt_headers->file_header.TimeDateStamp, "x");
68  addr += 4;
69  ROWL("PointerToSymbolTable", 4, bin->nt_headers->file_header.PointerToSymbolTable, "x");
70  addr += 4;
71  ROWL("NumberOfSymbols ", 4, bin->nt_headers->file_header.NumberOfSymbols, "x");
72  addr += 4;
73  ROWL("SizeOfOptionalHeader", 2, bin->nt_headers->file_header.SizeOfOptionalHeader, "x");
74  addr += 2;
75  ROWL("Characteristics", 2, bin->nt_headers->file_header.Characteristics, "x");
76  addr += 2;
77  ROWL("Magic", 2, bin->nt_headers->optional_header.Magic, "x");
78  addr += 2;
79  ROWL("MajorLinkerVersion", 1, bin->nt_headers->optional_header.MajorLinkerVersion, "x");
80  addr += 1;
81  ROWL("MinorLinkerVersion", 1, bin->nt_headers->optional_header.MinorLinkerVersion, "x");
82  addr += 1;
83  ROWL("SizeOfCode", 4, bin->nt_headers->optional_header.SizeOfCode, "x");
84  addr += 4;
85  ROWL("SizeOfInitializedData", 4, bin->nt_headers->optional_header.SizeOfInitializedData, "x");
86  addr += 4;
87  ROWL("SizeOfUninitializedData", 4, bin->nt_headers->optional_header.SizeOfUninitializedData, "x");
88  addr += 4;
89  ROWL("AddressOfEntryPoint", 4, bin->nt_headers->optional_header.AddressOfEntryPoint, "x");
90  addr += 4;
91  ROWL("BaseOfCode", 4, bin->nt_headers->optional_header.BaseOfCode, "x");
92  addr += 4;
93  ROWL("ImageBase", 4, bin->nt_headers->optional_header.ImageBase, "x");
94  addr += 4;
95  ROWL("SectionAlignment", 4, bin->nt_headers->optional_header.SectionAlignment, "x");
96  addr += 4;
97  ROWL("FileAlignment", 4, bin->nt_headers->optional_header.FileAlignment, "x");
98  addr += 4;
99  ROWL("MajorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MajorOperatingSystemVersion, "x");
100  addr += 2;
101  ROWL("MinorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MinorOperatingSystemVersion, "x");
102  addr += 2;
103  ROWL("MajorImageVersion", 2, bin->nt_headers->optional_header.MajorImageVersion, "x");
104  addr += 2;
105  ROWL("MinorImageVersion", 2, bin->nt_headers->optional_header.MinorImageVersion, "x");
106  addr += 2;
107  ROWL("MajorSubsystemVersion", 2, bin->nt_headers->optional_header.MajorSubsystemVersion, "x");
108  addr += 2;
109  ROWL("MinorSubsystemVersion", 2, bin->nt_headers->optional_header.MinorSubsystemVersion, "x");
110  addr += 2;
111  ROWL("Win32VersionValue", 4, bin->nt_headers->optional_header.Win32VersionValue, "x");
112  addr += 4;
113  ROWL("SizeOfImage", 4, bin->nt_headers->optional_header.SizeOfImage, "x");
114  addr += 4;
115  ROWL("SizeOfHeaders", 4, bin->nt_headers->optional_header.SizeOfHeaders, "x");
116  addr += 4;
117  ROWL("CheckSum", 4, bin->nt_headers->optional_header.CheckSum, "x");
118  addr += 4;
119  ROWL("Subsystem", 24, bin->nt_headers->optional_header.Subsystem, "x");
120  addr += 2;
121  ROWL("DllCharacteristics", 2, bin->nt_headers->optional_header.DllCharacteristics, "x");
122  addr += 2;
123  ROWL("SizeOfStackReserve", 4, bin->nt_headers->optional_header.SizeOfStackReserve, "x");
124  addr += 4;
125  ROWL("SizeOfStackCommit", 4, bin->nt_headers->optional_header.SizeOfStackCommit, "x");
126  addr += 4;
127  ROWL("SizeOfHeapReserve", 4, bin->nt_headers->optional_header.SizeOfHeapReserve, "x");
128  addr += 4;
129  ROWL("SizeOfHeapCommit", 4, bin->nt_headers->optional_header.SizeOfHeapCommit, "x");
130  addr += 4;
131  ROWL("LoaderFlags", 4, bin->nt_headers->optional_header.LoaderFlags, "x");
132  addr += 4;
133  ROWL("NumberOfRvaAndSizes", 4, bin->nt_headers->optional_header.NumberOfRvaAndSizes, "x");
134  addr += 4;
135 
136  int i;
137  ut64 tmp = addr;
138  for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
139  if (bin->nt_headers->optional_header.DataDirectory[i].Size > 0) {
140  addr = tmp + i * 8;
141  switch (i) {
143  ROWL("IMAGE_DIRECTORY_ENTRY_EXPORT", 4,
144  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
145  addr += 4;
146  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_EXPORT", 4,
147  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
148  break;
150  ROWL("IMAGE_DIRECTORY_ENTRY_IMPORT", 4,
151  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
152  addr += 4;
153  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_IMPORT", 4,
154  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
155  break;
157  ROWL("IMAGE_DIRECTORY_ENTRY_RESOURCE", 4,
158  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
159  addr += 4;
160  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_RESOURCE", 4,
161  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
162  break;
164  ROWL("IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4,
165  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
166  addr += 4;
167  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4,
168  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
169  break;
171  ROWL("IMAGE_DIRECTORY_ENTRY_SECURITY", 4,
172  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
173  addr += 4;
174  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_SECURITY", 4,
175  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
176  break;
178  ROWL("IMAGE_DIRECTORY_ENTRY_BASERELOC", 4,
179  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
180  addr += 4;
181  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_BASERELOC", 4,
182  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
183  break;
185  ROWL("IMAGE_DIRECTORY_ENTRY_DEBUG", 4,
186  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
187  addr += 4;
188  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_DEBUG", 4,
189  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
190  break;
192  ROWL("IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4,
193  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
194  addr += 4;
195  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4,
196  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
197  break;
199  ROWL("IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4,
200  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
201  addr += 4;
202  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4,
203  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
204  break;
206  ROWL("IMAGE_DIRECTORY_ENTRY_TLS", 4,
207  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
208  addr += 4;
209  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_TLS", 4,
210  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
211  break;
213  ROWL("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4,
214  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
215  addr += 4;
216  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4,
217  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
218  break;
220  ROWL("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4,
221  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
222  addr += 4;
223  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4,
224  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
225  break;
227  ROWL("IMAGE_DIRECTORY_ENTRY_IAT", 4,
228  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
229  addr += 4;
230  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_IAT", 4,
231  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
232  break;
234  ROWL("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4,
235  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
236  addr += 4;
237  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4,
238  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
239  break;
241  ROWL("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4,
242  bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
243  addr += 4;
244  ROWL("SIZE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4,
245  bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
246  break;
247  }
248  }
249  }
250 
251  return ret;
252 }
253 
254 static void header(RzBinFile *bf) {
255  struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
256  struct rz_bin_t *rbin = bf->rbin;
257  rbin->cb_printf("PE file header:\n");
258  rbin->cb_printf("IMAGE_NT_HEADERS\n");
259  rbin->cb_printf(" Signature : 0x%x\n", bin->nt_headers->Signature);
260  rbin->cb_printf("IMAGE_FILE_HEADERS\n");
261  rbin->cb_printf(" Machine : 0x%x\n", bin->nt_headers->file_header.Machine);
262  rbin->cb_printf(" NumberOfSections : 0x%x\n", bin->nt_headers->file_header.NumberOfSections);
263  rbin->cb_printf(" TimeDateStamp : 0x%x\n", bin->nt_headers->file_header.TimeDateStamp);
264  rbin->cb_printf(" PointerToSymbolTable : 0x%x\n", bin->nt_headers->file_header.PointerToSymbolTable);
265  rbin->cb_printf(" NumberOfSymbols : 0x%x\n", bin->nt_headers->file_header.NumberOfSymbols);
266  rbin->cb_printf(" SizeOfOptionalHeader : 0x%x\n", bin->nt_headers->file_header.SizeOfOptionalHeader);
267  rbin->cb_printf(" Characteristics : 0x%x\n", bin->nt_headers->file_header.Characteristics);
268  rbin->cb_printf("IMAGE_OPTIONAL_HEADERS\n");
269  rbin->cb_printf(" Magic : 0x%x\n", bin->nt_headers->optional_header.Magic);
270  rbin->cb_printf(" MajorLinkerVersion : 0x%x\n", bin->nt_headers->optional_header.MajorLinkerVersion);
271  rbin->cb_printf(" MinorLinkerVersion : 0x%x\n", bin->nt_headers->optional_header.MinorLinkerVersion);
272  rbin->cb_printf(" SizeOfCode : 0x%x\n", bin->nt_headers->optional_header.SizeOfCode);
273  rbin->cb_printf(" SizeOfInitializedData : 0x%x\n", bin->nt_headers->optional_header.SizeOfInitializedData);
274  rbin->cb_printf(" SizeOfUninitializedData : 0x%x\n", bin->nt_headers->optional_header.SizeOfUninitializedData);
275  rbin->cb_printf(" AddressOfEntryPoint : 0x%x\n", bin->nt_headers->optional_header.AddressOfEntryPoint);
276  rbin->cb_printf(" BaseOfCode : 0x%x\n", bin->nt_headers->optional_header.BaseOfCode);
277  rbin->cb_printf(" ImageBase : 0x%" PFMT64x "\n", bin->nt_headers->optional_header.ImageBase);
278  rbin->cb_printf(" SectionAlignment : 0x%x\n", bin->nt_headers->optional_header.SectionAlignment);
279  rbin->cb_printf(" FileAlignment : 0x%x\n", bin->nt_headers->optional_header.FileAlignment);
280  rbin->cb_printf(" MajorOperatingSystemVersion : 0x%x\n", bin->nt_headers->optional_header.MajorOperatingSystemVersion);
281  rbin->cb_printf(" MinorOperatingSystemVersion : 0x%x\n", bin->nt_headers->optional_header.MinorOperatingSystemVersion);
282  rbin->cb_printf(" MajorImageVersion : 0x%x\n", bin->nt_headers->optional_header.MajorImageVersion);
283  rbin->cb_printf(" MinorImageVersion : 0x%x\n", bin->nt_headers->optional_header.MinorImageVersion);
284  rbin->cb_printf(" MajorSubsystemVersion : 0x%x\n", bin->nt_headers->optional_header.MajorSubsystemVersion);
285  rbin->cb_printf(" MinorSubsystemVersion : 0x%x\n", bin->nt_headers->optional_header.MinorSubsystemVersion);
286  rbin->cb_printf(" Win32VersionValue : 0x%x\n", bin->nt_headers->optional_header.Win32VersionValue);
287  rbin->cb_printf(" SizeOfImage : 0x%x\n", bin->nt_headers->optional_header.SizeOfImage);
288  rbin->cb_printf(" SizeOfHeaders : 0x%x\n", bin->nt_headers->optional_header.SizeOfHeaders);
289  rbin->cb_printf(" CheckSum : 0x%x\n", bin->nt_headers->optional_header.CheckSum);
290  rbin->cb_printf(" Subsystem : 0x%x\n", bin->nt_headers->optional_header.Subsystem);
291  rbin->cb_printf(" DllCharacteristics : 0x%x\n", bin->nt_headers->optional_header.DllCharacteristics);
292  rbin->cb_printf(" SizeOfStackReserve : 0x%" PFMT64x "\n", bin->nt_headers->optional_header.SizeOfStackReserve);
293  rbin->cb_printf(" SizeOfStackCommit : 0x%" PFMT64x "\n", bin->nt_headers->optional_header.SizeOfStackCommit);
294  rbin->cb_printf(" SizeOfHeapReserve : 0x%" PFMT64x "\n", bin->nt_headers->optional_header.SizeOfHeapReserve);
295  rbin->cb_printf(" SizeOfHeapCommit : 0x%" PFMT64x "\n", bin->nt_headers->optional_header.SizeOfHeapCommit);
296  rbin->cb_printf(" LoaderFlags : 0x%x\n", bin->nt_headers->optional_header.LoaderFlags);
297  rbin->cb_printf(" NumberOfRvaAndSizes : 0x%x\n", bin->nt_headers->optional_header.NumberOfRvaAndSizes);
298  RzListIter *it;
300  rbin->cb_printf("RICH_FIELDS\n");
301  rz_list_foreach (bin->rich_entries, it, entry) {
302  rbin->cb_printf(" Product: %d Name: %s Version: %d Times: %d\n", entry->productId, entry->productName, entry->minVersion, entry->timesUsed);
303  }
304  int i;
305  for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
306  if (bin->nt_headers->optional_header.DataDirectory[i].Size > 0) {
307  switch (i) {
309  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_EXPORT\n");
310  break;
312  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_IMPORT\n");
313  break;
315  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_RESOURCE\n");
316  break;
318  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_EXCEPTION\n");
319  break;
321  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_SECURITY\n");
322  break;
324  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_BASERELOC\n");
325  break;
327  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_DEBUG\n");
328  break;
330  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_COPYRIGHT\n");
331  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE\n");
332  break;
334  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_GLOBALPTR\n");
335  break;
337  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_TLS\n");
338  break;
340  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG\n");
341  break;
343  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT\n");
344  break;
346  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_IAT\n");
347  break;
349  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT\n");
350  break;
352  rbin->cb_printf("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR\n");
353  break;
354  }
355  rbin->cb_printf(" VirtualAddress : 0x%x\n", bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress);
356  rbin->cb_printf(" Size : 0x%x\n", bin->nt_headers->optional_header.DataDirectory[i].Size);
357  }
358  }
359 }
360 
361 #define RzBinPEObj struct PE_(rz_bin_pe_obj_t)
362 static inline int find_section(RzBinPEObj *bin, PE_DWord rva) {
363  PE_DWord section_base;
364  int i, section_size;
365  for (i = 0; i < bin->num_sections; i++) {
366  section_base = bin->sections[i].vaddr;
367  section_size = bin->sections[i].vsize;
368  if (rva >= section_base && rva < section_base + section_size) {
369  return i;
370  }
371  }
372  return -1;
373 }
374 
375 static inline ut64 rva_to_paddr(const struct rz_bin_pe_section_t *section, ut64 rva) {
376  return section->paddr + (rva - section->vaddr);
377 }
378 
379 static inline const struct rz_bin_pe_section_t *get_section(RzBinPEObj *bin, const struct rz_bin_pe_section_t *unwind_data_section, PE_DWord rva) {
380  if (!unwind_data_section || (rva < unwind_data_section->vaddr || rva > unwind_data_section->vaddr + unwind_data_section->vsize)) {
381  const int section_idx = find_section(bin, rva);
382  if (section_idx == -1) {
383  return NULL;
384  }
385  if (bin->sections[section_idx].paddr > rz_buf_size(bin->b)) {
386  return NULL;
387  }
388  return &bin->sections[section_idx];
389  }
390  return unwind_data_section;
391 }
392 
393 static RzList *trycatch(RzBinFile *bf) {
394  ut64 baseAddr = bf->o->opts.baseaddr;
395  ut64 offset;
396 
397  struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
398  if (bin->optional_header->NumberOfRvaAndSizes < PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION) {
399  return NULL;
400  }
401  if (bin->optional_header->DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress == 0) {
402  return NULL;
403  }
404  PE_(image_data_directory) *expdir = &bin->optional_header->DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION];
405  if (!expdir->Size) {
406  return NULL;
407  }
408  const struct rz_bin_pe_section_t *pdata = get_section(bin, NULL, expdir->VirtualAddress);
409  if (!pdata) {
410  return NULL;
411  }
412  const ut64 paddr = rva_to_paddr(pdata, expdir->VirtualAddress);
413  if (paddr > rz_buf_size(bin->b)) {
414  return NULL;
415  }
416 
418  if (!tclist) {
419  return NULL;
420  }
421  const struct rz_bin_pe_section_t *unwind_data_section = NULL;
422 
423  const ut64 end = RZ_MIN(rz_buf_size(bin->b), pdata->paddr + pdata->size);
424 
425  for (offset = paddr; offset < end; offset += sizeof(PE64_RUNTIME_FUNCTION)) {
427  bool suc = rz_buf_read_at(bin->b, offset, (ut8 *)&rfcn, sizeof(rfcn));
428  if (!rfcn.BeginAddress) {
429  break;
430  }
431  rfcn.BeginAddress = rz_read_ble32((ut8 *)&rfcn.BeginAddress, bin->big_endian);
432  rfcn.EndAddress = rz_read_ble32((ut8 *)&rfcn.EndAddress, bin->big_endian);
433  rfcn.UnwindData = rz_read_ble32((ut8 *)&rfcn.UnwindData, bin->big_endian);
434  ut32 savedBeginOff = rfcn.BeginAddress;
435  ut32 savedEndOff = rfcn.EndAddress;
436  while (suc && rfcn.UnwindData & 1) {
437  suc = rz_buf_read_at(bin->b, rva_to_paddr(pdata, rfcn.UnwindData & ~1), (ut8 *)&rfcn, sizeof(rfcn));
438  rfcn.UnwindData = rz_read_ble32((ut8 *)&rfcn.UnwindData, bin->big_endian);
439  }
440  rfcn.BeginAddress = savedBeginOff;
441  rfcn.EndAddress = savedEndOff;
442  if (!suc) {
443  continue;
444  }
445  unwind_data_section = get_section(bin, unwind_data_section, rfcn.UnwindData);
446  if (!unwind_data_section) {
447  continue;
448  }
449  ut64 unwind_data_paddr = rva_to_paddr(unwind_data_section, rfcn.UnwindData);
450  if (unwind_data_paddr > unwind_data_section->paddr + unwind_data_section->size) {
451  continue;
452  }
454  suc = rz_buf_read_at(bin->b, unwind_data_paddr, (ut8 *)&info, sizeof(info));
455  if (!suc || info.Version != 1 || (!(info.Flags & PE64_UNW_FLAG_EHANDLER) && !(info.Flags & PE64_UNW_FLAG_CHAININFO))) {
456  continue;
457  }
458 
459  ut32 sizeOfCodeEntries = info.CountOfCodes % 2 ? info.CountOfCodes + 1 : info.CountOfCodes;
460  sizeOfCodeEntries *= sizeof(PE64_UNWIND_CODE);
461  ut64 exceptionDataOff = unwind_data_paddr + offsetof(PE64_UNWIND_INFO, UnwindCode) + sizeOfCodeEntries;
462 
463  if (info.Flags & PE64_UNW_FLAG_CHAININFO) {
464  savedBeginOff = rfcn.BeginAddress;
465  savedEndOff = rfcn.EndAddress;
466  do {
467  if (!rz_buf_read_at(bin->b, exceptionDataOff, (ut8 *)&rfcn, sizeof(rfcn))) {
468  break;
469  }
470  rfcn.BeginAddress = rz_read_ble32((ut8 *)&rfcn.BeginAddress, bin->big_endian);
471  rfcn.EndAddress = rz_read_ble32((ut8 *)&rfcn.EndAddress, bin->big_endian);
472  rfcn.UnwindData = rz_read_ble32((ut8 *)&rfcn.UnwindData, bin->big_endian);
473  unwind_data_section = get_section(bin, unwind_data_section, rfcn.UnwindData);
474  if (!unwind_data_section) {
475  break;
476  }
477  unwind_data_paddr = rva_to_paddr(unwind_data_section, rfcn.UnwindData);
478  suc = rz_buf_read_at(bin->b, unwind_data_paddr, (ut8 *)&info, sizeof(info));
479  if (!suc || info.Version != 1) {
480  break;
481  }
482  while (suc && (unwind_data_paddr & 1)) {
483  suc = rz_buf_read_at(bin->b, unwind_data_paddr & ~1, (ut8 *)&rfcn, sizeof(rfcn));
484  rfcn.UnwindData = rz_read_ble32((ut8 *)&rfcn.UnwindData, bin->big_endian);
485  unwind_data_paddr = rva_to_paddr(unwind_data_section, rfcn.UnwindData);
486  }
487  if (!suc || info.Version != 1) {
488  break;
489  }
490  sizeOfCodeEntries = info.CountOfCodes % 2 ? info.CountOfCodes + 1 : info.CountOfCodes;
491  sizeOfCodeEntries *= sizeof(PE64_UNWIND_CODE);
492  exceptionDataOff = unwind_data_paddr + offsetof(PE64_UNWIND_INFO, UnwindCode) + sizeOfCodeEntries;
493  } while (info.Flags & PE64_UNW_FLAG_CHAININFO);
494  if (!(info.Flags & PE64_UNW_FLAG_EHANDLER)) {
495  continue;
496  }
497  rfcn.BeginAddress = savedBeginOff;
498  rfcn.EndAddress = savedEndOff;
499  }
500 
501  ut32 handler;
502  if (!rz_buf_read_at(bin->b, exceptionDataOff, (ut8 *)&handler, sizeof(handler))) {
503  continue;
504  }
505  exceptionDataOff += sizeof(ut32);
506 
507  PE64_SCOPE_TABLE tbl;
508  if (!rz_buf_read_at(bin->b, exceptionDataOff, (ut8 *)&tbl, sizeof(tbl))) {
509  continue;
510  }
511  tbl.Count = rz_read_ble32((ut8 *)&tbl.Count, bin->big_endian);
512  const ut64 last_scope_addr = RZ_MIN(rz_buf_size(bin->b), unwind_data_section->paddr + unwind_data_section->size) - sizeof(PE64_SCOPE_RECORD);
513  PE64_SCOPE_RECORD scope;
514  ut64 scopeRecOff = exceptionDataOff + sizeof(tbl);
515  int i;
516  for (i = 0; i < tbl.Count && scopeRecOff <= last_scope_addr; i++, scopeRecOff += sizeof(PE64_SCOPE_RECORD)) {
517  if (!rz_buf_read_at(bin->b, scopeRecOff, (ut8 *)&scope, sizeof(PE64_SCOPE_RECORD))) {
518  break;
519  }
520  scope.BeginAddress = rz_read_ble32((ut8 *)&scope.BeginAddress, bin->big_endian);
521  scope.EndAddress = rz_read_ble32((ut8 *)&scope.EndAddress, bin->big_endian);
522  scope.HandlerAddress = rz_read_ble32((ut8 *)&scope.HandlerAddress, bin->big_endian);
523  scope.JumpTarget = rz_read_ble32((ut8 *)&scope.JumpTarget, bin->big_endian);
524  if (scope.BeginAddress > scope.EndAddress || scope.BeginAddress == UT32_MAX || scope.EndAddress == UT32_MAX || !scope.BeginAddress || !scope.EndAddress) {
525  break;
526  }
527  if (!(scope.BeginAddress >= rfcn.BeginAddress - 1 && scope.BeginAddress < rfcn.EndAddress && scope.EndAddress <= rfcn.EndAddress + 1 && scope.EndAddress > rfcn.BeginAddress)) {
528  continue;
529  }
530  if (!scope.JumpTarget) {
531  // scope.HandlerAddress == __finally block
532  scope.JumpTarget = scope.HandlerAddress;
533  scope.HandlerAddress = 1;
534  }
535  ut64 handlerAddr = scope.HandlerAddress == 1 ? 0 : scope.HandlerAddress + baseAddr;
537  rfcn.BeginAddress + baseAddr,
538  scope.BeginAddress + baseAddr,
539  scope.EndAddress + baseAddr,
540  scope.JumpTarget + baseAddr,
541  handlerAddr);
542  rz_list_append(tclist, tc);
543  }
544  }
545  return tclist;
546 }
547 
549  .name = "pe64",
550  .desc = "PE64 (PE32+) bin plugin",
551  .license = "LGPL3",
552  .get_sdb = &get_sdb,
553  .load_buffer = &load_buffer,
554  .destroy = &destroy,
555  .check_buffer = &check_buffer,
556  .baddr = &baddr,
557  .binsym = &binsym,
558  .entries = &entries,
559  .maps = &maps,
560  .sections = &sections,
561  .symbols = &symbols,
562  .imports = &imports,
563  .strings = &strings,
564  .info = &info,
565  .header = &header,
566  .fields = &fields,
567  .libs = &libs,
568  .relocs = &relocs,
569  .get_offset = &get_offset,
570  .get_vaddr = &get_vaddr,
571  .trycatch = &trycatch,
572  .hashes = &compute_hashes,
573  .resources = &resources,
574  .section_flag_to_rzlist = &PE_(section_flag_to_rzlist),
575 };
576 
577 #ifndef RZ_PLUGIN_INCORE
580  .data = &rz_bin_plugin_pe64,
582 };
583 #endif
lzma_index ** i
Definition: index.h:629
RZ_API void rz_bin_field_free(RzBinField *field)
Definition: bin.c:950
RZ_API RzBinTrycatch * rz_bin_trycatch_new(ut64 source, ut64 from, ut64 to, ut64 handler, ut64 filter)
Definition: bin.c:1178
RZ_API RzBinField * rz_bin_field_new(ut64 paddr, ut64 vaddr, int size, const char *name, const char *comment, const char *format, bool format_named)
Definition: bin.c:935
RZ_API void rz_bin_trycatch_free(RzBinTrycatch *tc)
Definition: bin.c:1190
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_any.c:50
static void destroy(RzBinFile *bf)
Definition: bin_any.c:54
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
static Sdb * get_sdb(RzBinFile *bf)
Definition: bin_art.c:60
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
static RzBinAddr * binsym(RzBinFile *bf, RzBinSpecialSymbol sym)
Definition: bin_coff.c:47
static RzList * libs(RzBinFile *bf)
Definition: bin_coff.c:379
static ut64 get_offset(RzBinFile *bf, int type, int index)
Definition: bin_dex.c:206
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RzList * symbols(RzBinFile *bf)
Definition: bin_ne.c:102
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
static ut64 get_vaddr(RzBinFile *bf, ut64 baddr, ut64 paddr, ut64 vaddr)
Definition: bin_omf.c:161
static void header(RzBinFile *bf)
Definition: bin_pe64.c:254
static ut64 rva_to_paddr(const struct rz_bin_pe_section_t *section, ut64 rva)
Definition: bin_pe64.c:375
static RzList * fields(RzBinFile *bf)
Definition: bin_pe64.c:37
RZ_API RzLibStruct rizin_plugin
Definition: bin_pe64.c:578
#define RzBinPEObj
Definition: bin_pe64.c:361
static bool check_buffer(RzBuffer *b)
Definition: bin_pe64.c:7
static const struct rz_bin_pe_section_t * get_section(RzBinPEObj *bin, const struct rz_bin_pe_section_t *unwind_data_section, PE_DWord rva)
Definition: bin_pe64.c:379
static int find_section(RzBinPEObj *bin, PE_DWord rva)
Definition: bin_pe64.c:362
RzBinPlugin rz_bin_plugin_pe64
Definition: bin_pe64.c:548
#define ROWL(nam, siz, val, fmt)
static RzList * trycatch(RzBinFile *bf)
Definition: bin_pe64.c:393
static ut64 rva(RzBinObject *o, ut64 paddr, ut64 vaddr, int va)
Definition: cbin.c:77
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
uint16_t ut16
uint32_t ut32
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type strings(--mime-type and\n" " --mime-encoding)\n") OPT('s'
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
#define offsetof(type, member)
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RzList *MACH0_() section_flag_to_rzlist(ut64 flag)
Definition: mach0.c:2378
int idx
Definition: setup.py:197
#define PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pe_specs.h:146
#define PE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT
Definition: pe_specs.h:150
#define PE_(name)
Definition: pe_specs.h:23
#define PE_IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pe_specs.h:144
#define PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
Definition: pe_specs.h:158
#define PE_IMAGE_DIRECTORY_ENTRY_RESOURCE
Definition: pe_specs.h:145
#define PE_IMAGE_DIRECTORY_ENTRY_BASERELOC
Definition: pe_specs.h:148
#define PE64_UNW_FLAG_EHANDLER
Definition: pe_specs.h:701
#define PE_IMAGE_DIRECTORY_ENTRY_DEBUG
Definition: pe_specs.h:149
#define PE_IMAGE_DIRECTORY_ENTRY_SECURITY
Definition: pe_specs.h:147
#define PE_IMAGE_DIRECTORY_ENTRY_IAT
Definition: pe_specs.h:156
#define PE64_UNW_FLAG_CHAININFO
Definition: pe_specs.h:703
#define PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
Definition: pe_specs.h:157
#define PE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
Definition: pe_specs.h:155
#define PE_DWord
Definition: pe_specs.h:27
#define PE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR
Definition: pe_specs.h:152
#define PE_IMAGE_DIRECTORY_ENTRIES
Definition: pe_specs.h:142
#define PE_IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: pe_specs.h:143
#define PE_IMAGE_DIRECTORY_ENTRY_TLS
Definition: pe_specs.h:153
#define PE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
Definition: pe_specs.h:154
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
#define UT32_MAX
Definition: rz_types_base.h:99
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
Definition: pe_specs.h:345
ut16 productId
Definition: pe_specs.h:346
ut32 timesUsed
Definition: pe_specs.h:348
char * productName
Definition: pe_specs.h:349
ut16 minVersion
Definition: pe_specs.h:347
Definition: malloc.c:26
Definition: zipcmp.c:77
ut64 baseaddr
where the linker maps the binary in memory
Definition: rz_bin.h:248
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
struct rz_bin_t * rbin
Definition: rz_bin.h:316
RzBinObjectLoadOptions opts
Definition: rz_bin.h:260
void * bin_obj
Definition: rz_bin.h:293
ut64 vaddr
Definition: pe.h:67
ut64 vsize
Definition: pe.h:66
ut64 paddr
Definition: pe.h:68
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
PrintfCallback cb_printf
Definition: rz_bin.h:345
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58