1 /* radare - LGPL - Copyright 2009-2019 - nibble, pancake */
2 #define R_BIN_PE64 1
3 #include "bin_pe.inc"
4
check_buffer(RBuffer * b)5 static bool check_buffer(RBuffer *b) {
6 ut64 length = r_buf_size (b);
7 if (length <= 0x3d) {
8 return false;
9 }
10 ut16 idx = r_buf_read_le16_at (b, 0x3c);
11 if (idx + 26 < length) {
12 /* Here PE signature for usual PE files
13 * and PL signature for Phar Lap TNT DOS extender 32bit executables
14 */
15 ut8 buf[2];
16 r_buf_read_at (b, 0, buf, sizeof (buf));
17 if (!memcmp (buf, "MZ", 2)) {
18 r_buf_read_at (b, idx, buf, sizeof (buf));
19 // TODO: Add one more indicator, to prevent false positives
20 // if (!memcmp (buf, "PL", 2)) { return true; }
21 if (!memcmp (buf, "PE", 2)) {
22 r_buf_read_at (b, idx + 0x18, buf, sizeof (buf));
23 return !memcmp (buf, "\x0b\x02", 2);
24 }
25 }
26 }
27 return false;
28 }
29
fields(RBinFile * bf)30 static RList *fields(RBinFile *bf) {
31 RList *ret = r_list_new ();
32 if (!ret) {
33 return NULL;
34 }
35
36 #define ROWL(nam,siz,val,fmt) \
37 r_list_append (ret, r_bin_field_new (addr, addr, siz, nam, \
38 sdb_fmt ("0x%08"PFMT64x, (ut64)val), fmt, false));
39
40 struct PE_(r_bin_pe_obj_t) * bin = bf->o->bin_obj;
41 ut64 addr = bin->rich_header_offset ? bin->rich_header_offset : 128;
42
43 RListIter *it;
44 Pe_image_rich_entry *rich;
45 r_list_foreach (bin->rich_entries, it, rich) {
46 r_list_append (ret, r_bin_field_new (addr, addr, 0, "RICH_ENTRY_NAME", strdup (rich->productName), "s", false));
47 ROWL ("RICH_ENTRY_ID", 2, rich->productId, "x"); addr += 2;
48 ROWL ("RICH_ENTRY_VERSION", 2, rich->minVersion, "x"); addr += 2;
49 ROWL ("RICH_ENTRY_TIMES", 4, rich->timesUsed, "x"); addr += 4;
50 }
51
52 ROWL ("Signature", 4, bin->nt_headers->Signature, "x"); addr += 4;
53 ROWL ("Machine", 2, bin->nt_headers->file_header.Machine, "x"); addr += 2;
54 ROWL ("NumberOfSections", 2, bin->nt_headers->file_header.NumberOfSections, "x"); addr += 2;
55 ROWL ("TimeDateStamp", 4, bin->nt_headers->file_header.TimeDateStamp, "x"); addr += 4;
56 ROWL ("PointerToSymbolTable", 4, bin->nt_headers->file_header.PointerToSymbolTable, "x"); addr += 4;
57 ROWL ("NumberOfSymbols ", 4, bin->nt_headers->file_header.NumberOfSymbols, "x"); addr += 4;
58 ROWL ("SizeOfOptionalHeader", 2, bin->nt_headers->file_header.SizeOfOptionalHeader, "x"); addr += 2;
59 ROWL ("Characteristics", 2, bin->nt_headers->file_header.Characteristics, "x"); addr += 2;
60 ROWL ("Magic", 2, bin->nt_headers->optional_header.Magic, "x"); addr += 2;
61 ROWL ("MajorLinkerVersion", 1, bin->nt_headers->optional_header.MajorLinkerVersion, "x"); addr += 1;
62 ROWL ("MinorLinkerVersion", 1, bin->nt_headers->optional_header.MinorLinkerVersion, "x"); addr += 1;
63 ROWL ("SizeOfCode", 4, bin->nt_headers->optional_header.SizeOfCode, "x"); addr += 4;
64 ROWL ("SizeOfInitializedData", 4, bin->nt_headers->optional_header.SizeOfInitializedData, "x"); addr += 4;
65 ROWL ("SizeOfUninitializedData", 4, bin->nt_headers->optional_header.SizeOfUninitializedData, "x"); addr += 4;
66 ROWL ("AddressOfEntryPoint", 4, bin->nt_headers->optional_header.AddressOfEntryPoint, "x"); addr += 4;
67 ROWL ("BaseOfCode", 4, bin->nt_headers->optional_header.BaseOfCode, "x"); addr += 4;
68 ROWL ("ImageBase", 4, bin->nt_headers->optional_header.ImageBase, "x"); addr += 4;
69 ROWL ("SectionAlignment", 4, bin->nt_headers->optional_header.SectionAlignment, "x"); addr += 4;
70 ROWL ("FileAlignment", 4, bin->nt_headers->optional_header.FileAlignment, "x"); addr += 4;
71 ROWL ("MajorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MajorOperatingSystemVersion, "x"); addr += 2;
72 ROWL ("MinorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MinorOperatingSystemVersion, "x"); addr += 2;
73 ROWL ("MajorImageVersion", 2, bin->nt_headers->optional_header.MajorImageVersion, "x"); addr += 2;
74 ROWL ("MinorImageVersion", 2, bin->nt_headers->optional_header.MinorImageVersion, "x"); addr += 2;
75 ROWL ("MajorSubsystemVersion", 2, bin->nt_headers->optional_header.MajorSubsystemVersion, "x"); addr += 2;
76 ROWL ("MinorSubsystemVersion", 2, bin->nt_headers->optional_header.MinorSubsystemVersion, "x"); addr += 2;
77 ROWL ("Win32VersionValue", 4, bin->nt_headers->optional_header.Win32VersionValue, "x"); addr += 4;
78 ROWL ("SizeOfImage", 4, bin->nt_headers->optional_header.SizeOfImage, "x"); addr += 4;
79 ROWL ("SizeOfHeaders", 4, bin->nt_headers->optional_header.SizeOfHeaders, "x"); addr += 4;
80 ROWL ("CheckSum", 4, bin->nt_headers->optional_header.CheckSum, "x"); addr += 4;
81 ROWL ("Subsystem",24, bin->nt_headers->optional_header.Subsystem, "x"); addr += 2;
82 ROWL ("DllCharacteristics", 2, bin->nt_headers->optional_header.DllCharacteristics, "x"); addr += 2;
83 ROWL ("SizeOfStackReserve", 4, bin->nt_headers->optional_header.SizeOfStackReserve, "x"); addr += 4;
84 ROWL ("SizeOfStackCommit", 4, bin->nt_headers->optional_header.SizeOfStackCommit, "x"); addr += 4;
85 ROWL ("SizeOfHeapReserve", 4, bin->nt_headers->optional_header.SizeOfHeapReserve, "x"); addr += 4;
86 ROWL ("SizeOfHeapCommit", 4, bin->nt_headers->optional_header.SizeOfHeapCommit, "x"); addr += 4;
87 ROWL ("LoaderFlags", 4, bin->nt_headers->optional_header.LoaderFlags, "x"); addr += 4;
88 ROWL ("NumberOfRvaAndSizes", 4, bin->nt_headers->optional_header.NumberOfRvaAndSizes, "x"); addr += 4;
89
90 int i;
91 ut64 tmp = addr;
92 for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
93 if (bin->nt_headers->optional_header.DataDirectory[i].Size > 0) {
94 addr = tmp + i*8;
95 switch (i) {
96 case PE_IMAGE_DIRECTORY_ENTRY_EXPORT:
97 ROWL ("IMAGE_DIRECTORY_ENTRY_EXPORT", 4, \
98 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
99 addr += 4;
100 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_EXPORT", 4, \
101 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
102 break;
103 case PE_IMAGE_DIRECTORY_ENTRY_IMPORT:
104 ROWL ("IMAGE_DIRECTORY_ENTRY_IMPORT", 4, \
105 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
106 addr += 4;
107 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_IMPORT", 4, \
108 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
109 break;
110 case PE_IMAGE_DIRECTORY_ENTRY_RESOURCE:
111 ROWL ("IMAGE_DIRECTORY_ENTRY_RESOURCE", 4, \
112 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
113 addr += 4;
114 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_RESOURCE", 4, \
115 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
116 break;
117 case PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION:
118 ROWL ("IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4, \
119 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
120 addr += 4;
121 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4, \
122 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
123 break;
124 case PE_IMAGE_DIRECTORY_ENTRY_SECURITY:
125 ROWL ("IMAGE_DIRECTORY_ENTRY_SECURITY", 4, \
126 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
127 addr += 4;
128 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_SECURITY", 4, \
129 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
130 break;
131 case PE_IMAGE_DIRECTORY_ENTRY_BASERELOC:
132 ROWL ("IMAGE_DIRECTORY_ENTRY_BASERELOC", 4, \
133 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
134 addr += 4;
135 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_BASERELOC", 4, \
136 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
137 break;
138 case PE_IMAGE_DIRECTORY_ENTRY_DEBUG:
139 ROWL ("IMAGE_DIRECTORY_ENTRY_DEBUG", 4, \
140 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
141 addr += 4;
142 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_DEBUG", 4, \
143 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
144 break;
145 case PE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
146 ROWL ("IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4, \
147 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
148 addr += 4;
149 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4, \
150 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
151 break;
152 case PE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
153 ROWL ("IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4, \
154 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
155 addr += 4;
156 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4, \
157 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
158 break;
159 case PE_IMAGE_DIRECTORY_ENTRY_TLS:
160 ROWL ("IMAGE_DIRECTORY_ENTRY_TLS", 4, \
161 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
162 addr += 4;
163 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_TLS", 4, \
164 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
165 break;
166 case PE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
167 ROWL ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4, \
168 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
169 addr += 4;
170 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4, \
171 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
172 break;
173 case PE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
174 ROWL ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4, \
175 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
176 addr += 4;
177 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4, \
178 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
179 break;
180 case PE_IMAGE_DIRECTORY_ENTRY_IAT:
181 ROWL ("IMAGE_DIRECTORY_ENTRY_IAT", 4, \
182 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
183 addr += 4;
184 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_IAT", 4, \
185 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
186 break;
187 case PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
188 ROWL ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4, \
189 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
190 addr += 4;
191 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4, \
192 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
193 break;
194 case PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
195 ROWL ("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4, \
196 bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
197 addr += 4;
198 ROWL ("SIZE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4, \
199 bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
200 break;
201 }
202 }
203 }
204
205 return ret;
206 }
207
header(RBinFile * bf)208 static void header(RBinFile *bf) {
209 struct PE_(r_bin_pe_obj_t) * bin = bf->o->bin_obj;
210 struct r_bin_t *rbin = bf->rbin;
211 rbin->cb_printf ("PE file header:\n");
212 rbin->cb_printf ("IMAGE_NT_HEADERS\n");
213 rbin->cb_printf (" Signature : 0x%x\n", bin->nt_headers->Signature);
214 rbin->cb_printf ("IMAGE_FILE_HEADERS\n");
215 rbin->cb_printf (" Machine : 0x%x\n", bin->nt_headers->file_header.Machine);
216 rbin->cb_printf (" NumberOfSections : 0x%x\n", bin->nt_headers->file_header.NumberOfSections);
217 rbin->cb_printf (" TimeDateStamp : 0x%x\n", bin->nt_headers->file_header.TimeDateStamp);
218 rbin->cb_printf (" PointerToSymbolTable : 0x%x\n", bin->nt_headers->file_header.PointerToSymbolTable);
219 rbin->cb_printf (" NumberOfSymbols : 0x%x\n", bin->nt_headers->file_header.NumberOfSymbols);
220 rbin->cb_printf (" SizeOfOptionalHeader : 0x%x\n", bin->nt_headers->file_header.SizeOfOptionalHeader);
221 rbin->cb_printf (" Characteristics : 0x%x\n", bin->nt_headers->file_header.Characteristics);
222 rbin->cb_printf ("IMAGE_OPTIONAL_HEADERS\n");
223 rbin->cb_printf (" Magic : 0x%x\n", bin->nt_headers->optional_header.Magic);
224 rbin->cb_printf (" MajorLinkerVersion : 0x%x\n", bin->nt_headers->optional_header.MajorLinkerVersion);
225 rbin->cb_printf (" MinorLinkerVersion : 0x%x\n", bin->nt_headers->optional_header.MinorLinkerVersion);
226 rbin->cb_printf (" SizeOfCode : 0x%x\n", bin->nt_headers->optional_header.SizeOfCode);
227 rbin->cb_printf (" SizeOfInitializedData : 0x%x\n", bin->nt_headers->optional_header.SizeOfInitializedData);
228 rbin->cb_printf (" SizeOfUninitializedData : 0x%x\n", bin->nt_headers->optional_header.SizeOfUninitializedData);
229 rbin->cb_printf (" AddressOfEntryPoint : 0x%x\n", bin->nt_headers->optional_header.AddressOfEntryPoint);
230 rbin->cb_printf (" BaseOfCode : 0x%x\n", bin->nt_headers->optional_header.BaseOfCode);
231 rbin->cb_printf (" ImageBase : 0x%"PFMT64x"\n", bin->nt_headers->optional_header.ImageBase);
232 rbin->cb_printf (" SectionAlignment : 0x%x\n", bin->nt_headers->optional_header.SectionAlignment);
233 rbin->cb_printf (" FileAlignment : 0x%x\n", bin->nt_headers->optional_header.FileAlignment);
234 rbin->cb_printf (" MajorOperatingSystemVersion : 0x%x\n", bin->nt_headers->optional_header.MajorOperatingSystemVersion);
235 rbin->cb_printf (" MinorOperatingSystemVersion : 0x%x\n", bin->nt_headers->optional_header.MinorOperatingSystemVersion);
236 rbin->cb_printf (" MajorImageVersion : 0x%x\n", bin->nt_headers->optional_header.MajorImageVersion);
237 rbin->cb_printf (" MinorImageVersion : 0x%x\n", bin->nt_headers->optional_header.MinorImageVersion);
238 rbin->cb_printf (" MajorSubsystemVersion : 0x%x\n", bin->nt_headers->optional_header.MajorSubsystemVersion);
239 rbin->cb_printf (" MinorSubsystemVersion : 0x%x\n", bin->nt_headers->optional_header.MinorSubsystemVersion);
240 rbin->cb_printf (" Win32VersionValue : 0x%x\n", bin->nt_headers->optional_header.Win32VersionValue);
241 rbin->cb_printf (" SizeOfImage : 0x%x\n", bin->nt_headers->optional_header.SizeOfImage);
242 rbin->cb_printf (" SizeOfHeaders : 0x%x\n", bin->nt_headers->optional_header.SizeOfHeaders);
243 rbin->cb_printf (" CheckSum : 0x%x\n", bin->nt_headers->optional_header.CheckSum);
244 rbin->cb_printf (" Subsystem : 0x%x\n", bin->nt_headers->optional_header.Subsystem);
245 rbin->cb_printf (" DllCharacteristics : 0x%x\n", bin->nt_headers->optional_header.DllCharacteristics);
246 rbin->cb_printf (" SizeOfStackReserve : 0x%"PFMT64x"\n", bin->nt_headers->optional_header.SizeOfStackReserve);
247 rbin->cb_printf (" SizeOfStackCommit : 0x%"PFMT64x"\n", bin->nt_headers->optional_header.SizeOfStackCommit);
248 rbin->cb_printf (" SizeOfHeapReserve : 0x%"PFMT64x"\n", bin->nt_headers->optional_header.SizeOfHeapReserve);
249 rbin->cb_printf (" SizeOfHeapCommit : 0x%"PFMT64x"\n", bin->nt_headers->optional_header.SizeOfHeapCommit);
250 rbin->cb_printf (" LoaderFlags : 0x%x\n", bin->nt_headers->optional_header.LoaderFlags);
251 rbin->cb_printf (" NumberOfRvaAndSizes : 0x%x\n", bin->nt_headers->optional_header.NumberOfRvaAndSizes);
252 RListIter *it;
253 Pe_image_rich_entry *entry;
254 rbin->cb_printf ("RICH_FIELDS\n");
255 r_list_foreach (bin->rich_entries, it, entry) {
256 rbin->cb_printf (" Product: %d Name: %s Version: %d Times: %d\n", entry->productId, entry->productName, entry->minVersion, entry->timesUsed);
257 }
258 int i;
259 for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
260 if (bin->nt_headers->optional_header.DataDirectory[i].Size > 0) {
261 switch (i) {
262 case PE_IMAGE_DIRECTORY_ENTRY_EXPORT:
263 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_EXPORT\n");
264 break;
265 case PE_IMAGE_DIRECTORY_ENTRY_IMPORT:
266 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_IMPORT\n");
267 break;
268 case PE_IMAGE_DIRECTORY_ENTRY_RESOURCE:
269 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_RESOURCE\n");
270 break;
271 case PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION:
272 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_EXCEPTION\n");
273 break;
274 case PE_IMAGE_DIRECTORY_ENTRY_SECURITY:
275 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_SECURITY\n");
276 break;
277 case PE_IMAGE_DIRECTORY_ENTRY_BASERELOC:
278 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_BASERELOC\n");
279 break;
280 case PE_IMAGE_DIRECTORY_ENTRY_DEBUG:
281 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_DEBUG\n");
282 break;
283 case PE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
284 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_COPYRIGHT\n");
285 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE\n");
286 break;
287 case PE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
288 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_GLOBALPTR\n");
289 break;
290 case PE_IMAGE_DIRECTORY_ENTRY_TLS:
291 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_TLS\n");
292 break;
293 case PE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
294 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG\n");
295 break;
296 case PE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
297 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT\n");
298 break;
299 case PE_IMAGE_DIRECTORY_ENTRY_IAT:
300 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_IAT\n");
301 break;
302 case PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
303 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT\n");
304 break;
305 case PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
306 rbin->cb_printf ("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR\n");
307 break;
308 }
309 rbin->cb_printf (" VirtualAddress : 0x%x\n", bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress);
310 rbin->cb_printf (" Size : 0x%x\n", bin->nt_headers->optional_header.DataDirectory[i].Size);
311 }
312 }
313 }
314
315 extern struct r_bin_write_t r_bin_write_pe64;
316
trycatch(RBinFile * bf)317 static RList *trycatch(RBinFile *bf) {
318 RIO *io = bf->rbin->iob.io;
319 ut64 baseAddr = bf->o->baddr;
320 int i;
321 ut64 offset;
322 ut32 c_handler = 0;
323
324 struct PE_(r_bin_pe_obj_t) * bin = bf->o->bin_obj;
325 PE_(image_data_directory) *expdir = &bin->optional_header->DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION];
326 if (!expdir->Size) {
327 return NULL;
328 }
329
330 RList *tclist = r_list_newf ((RListFree)r_bin_trycatch_free);
331 if (!tclist) {
332 return NULL;
333 }
334
335 for (offset = expdir->VirtualAddress; offset < (ut64)expdir->VirtualAddress + expdir->Size; offset += sizeof (PE64_RUNTIME_FUNCTION)) {
336 PE64_RUNTIME_FUNCTION rfcn;
337 bool suc = r_io_read_at_mapped (io, offset + baseAddr, (ut8 *)&rfcn, sizeof (rfcn));
338 if (!rfcn.BeginAddress) {
339 break;
340 }
341 ut32 savedBeginOff = rfcn.BeginAddress;
342 ut32 savedEndOff = rfcn.EndAddress;
343 while (suc && rfcn.UnwindData & 1) {
344 suc = r_io_read_at_mapped (io, baseAddr + (rfcn.UnwindData & ~1), (ut8 *)&rfcn, sizeof (rfcn));
345 }
346 rfcn.BeginAddress = savedBeginOff;
347 rfcn.EndAddress = savedEndOff;
348 if (!suc) {
349 continue;
350 }
351 PE64_UNWIND_INFO info;
352 suc = r_io_read_at_mapped (io, rfcn.UnwindData + baseAddr, (ut8 *)&info, sizeof (info));
353 if (!suc || info.Version != 1 || (!(info.Flags & PE64_UNW_FLAG_EHANDLER) && !(info.Flags & PE64_UNW_FLAG_CHAININFO))) {
354 continue;
355 }
356
357 ut32 sizeOfCodeEntries = info.CountOfCodes % 2 ? info.CountOfCodes + 1 : info.CountOfCodes;
358 sizeOfCodeEntries *= sizeof (PE64_UNWIND_CODE);
359 ut64 exceptionDataOff = baseAddr + rfcn.UnwindData + offsetof (PE64_UNWIND_INFO, UnwindCode) + sizeOfCodeEntries;
360
361 if (info.Flags & PE64_UNW_FLAG_CHAININFO) {
362 savedBeginOff = rfcn.BeginAddress;
363 savedEndOff = rfcn.EndAddress;
364 do {
365 if (!r_io_read_at_mapped (io, exceptionDataOff, (ut8 *)&rfcn, sizeof (rfcn))) {
366 break;
367 }
368 suc = r_io_read_at_mapped (io, rfcn.UnwindData + baseAddr, (ut8 *)&info, sizeof (info));
369 if (!suc || info.Version != 1) {
370 break;
371 }
372 while (suc && (rfcn.UnwindData & 1)) {
373 suc = r_io_read_at_mapped (io, baseAddr + (rfcn.UnwindData & ~1), (ut8 *)&rfcn, sizeof (rfcn));
374 }
375 if (!suc || info.Version != 1) {
376 break;
377 }
378 sizeOfCodeEntries = info.CountOfCodes % 2 ? info.CountOfCodes + 1 : info.CountOfCodes;
379 sizeOfCodeEntries *= sizeof (PE64_UNWIND_CODE);
380 exceptionDataOff = baseAddr + rfcn.UnwindData + offsetof (PE64_UNWIND_INFO, UnwindCode) + sizeOfCodeEntries;
381 } while (info.Flags & PE64_UNW_FLAG_CHAININFO);
382 if (!(info.Flags & PE64_UNW_FLAG_EHANDLER)) {
383 continue;
384 }
385 rfcn.BeginAddress = savedBeginOff;
386 rfcn.EndAddress = savedEndOff;
387 }
388
389 ut32 handler;
390 if (!r_io_read_at_mapped (io, exceptionDataOff, (ut8 *)&handler, sizeof (handler))) {
391 continue;
392 }
393 if (c_handler && c_handler != handler) {
394 continue;
395 }
396 exceptionDataOff += sizeof (ut32);
397
398 if (!c_handler) {
399 ut32 magic, rva_to_fcninfo;
400 if (r_io_read_at_mapped (io, exceptionDataOff, (ut8 *)&rva_to_fcninfo, sizeof (rva_to_fcninfo)) &&
401 r_io_read_at_mapped (io, baseAddr + rva_to_fcninfo, (ut8 *)&magic, sizeof (magic))) {
402 if (magic >= 0x19930520 && magic <= 0x19930522) {
403 // __CxxFrameHandler3 or __GSHandlerCheck_EH
404 continue;
405 }
406 }
407 }
408
409 PE64_SCOPE_TABLE tbl;
410 if (!r_io_read_at_mapped (io, exceptionDataOff, (ut8 *)&tbl, sizeof (tbl))) {
411 continue;
412 }
413
414 PE64_SCOPE_RECORD scope;
415 ut64 scopeRecOff = exceptionDataOff + sizeof (tbl);
416 for (i = 0; i < tbl.Count; i++) {
417 if (!r_io_read_at_mapped (io, scopeRecOff, (ut8 *)&scope, sizeof (PE64_SCOPE_RECORD))) {
418 break;
419 }
420 if (scope.BeginAddress > scope.EndAddress
421 || scope.BeginAddress == UT32_MAX || scope.EndAddress == UT32_MAX
422 || !scope.BeginAddress || !scope.EndAddress) {
423 break;
424 }
425 if (!(scope.BeginAddress >= rfcn.BeginAddress - 1 && scope.BeginAddress < rfcn.EndAddress
426 && scope.EndAddress <= rfcn.EndAddress + 1 && scope.EndAddress > rfcn.BeginAddress)) {
427 continue;
428 }
429 if (!scope.JumpTarget) {
430 // scope.HandlerAddress == __finally block
431 continue;
432 }
433 ut64 handlerAddr = scope.HandlerAddress == 1 ? 0 : scope.HandlerAddress + baseAddr;
434 RBinTrycatch *tc = r_bin_trycatch_new (
435 rfcn.BeginAddress + baseAddr,
436 scope.BeginAddress + baseAddr,
437 scope.EndAddress + baseAddr,
438 scope.JumpTarget + baseAddr,
439 handlerAddr
440 );
441 c_handler = handler;
442 r_list_append (tclist, tc);
443 scopeRecOff += sizeof (PE64_SCOPE_RECORD);
444 }
445 }
446 return tclist;
447 }
448
449 RBinPlugin r_bin_plugin_pe64 = {
450 .name = "pe64",
451 .desc = "PE64 (PE32+) bin plugin",
452 .license = "LGPL3",
453 .get_sdb = &get_sdb,
454 .load_buffer = &load_buffer,
455 .destroy = &destroy,
456 .check_buffer = &check_buffer,
457 .baddr = &baddr,
458 .binsym = &binsym,
459 .entries = &entries,
460 .sections = §ions,
461 .symbols = &symbols,
462 .imports = &imports,
463 .info = &info,
464 .header = &header,
465 .fields = &fields,
466 .libs = &libs,
467 .relocs = &relocs,
468 .get_vaddr = &get_vaddr,
469 .trycatch = &trycatch,
470 .write = &r_bin_write_pe64,
471 .hashes = &compute_hashes
472 };
473
474 #ifndef R2_PLUGIN_INCORE
475 R_API RLibStruct radare_plugin = {
476 .type = R_LIB_TYPE_BIN,
477 .data = &r_bin_plugin_pe64,
478 .version = R2_VERSION
479 };
480 #endif
481