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 = &sections,
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