1 /* radare - LGPL - Copyright 2008-2013 nibble, pancake, xvilka */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <r_types.h>
7 #include <r_util.h>
8 #include "te_specs.h"
9 #include "te.h"
10 
r_bin_te_get_stripped_delta(struct r_bin_te_obj_t * bin)11 ut64 r_bin_te_get_stripped_delta(struct r_bin_te_obj_t *bin) {
12 	if (bin && bin->header) {
13 		return bin->header->StrippedSize - sizeof (TE_image_file_header);
14 	}
15 	return 0LL;
16 }
17 
r_bin_te_init_hdr(struct r_bin_te_obj_t * bin)18 static int r_bin_te_init_hdr(struct r_bin_te_obj_t *bin) {
19 	if (!bin) {
20 		return false;
21 	}
22 	if (!(bin->header = malloc (sizeof(TE_image_file_header)))) {
23 		r_sys_perror ("malloc (header)");
24 		return false;
25 	}
26 	if (r_buf_read_at (bin->b, 0, (ut8*)bin->header, sizeof (TE_image_file_header)) == -1) {
27 		eprintf("Error: read (header)\n");
28 		return false;
29 	}
30 	if (!bin->kv) {
31 		eprintf("Error: sdb instance is empty\n");
32 		return false;
33 	}
34 
35 	sdb_set (bin->kv, "te_machine.cparse", "enum te_machine { TE_IMAGE_FILE_MACHINE_UNKNOWN=0x0, TE_IMAGE_FILE_MACHINE_ALPHA=0x184, "
36 	"TE_IMAGE_FILE_MACHINE_ALPHA64=0x284, TE_IMAGE_FILE_MACHINE_AM33=0x1d3, TE_IMAGE_FILE_MACHINE_AMD64=0x8664, "
37 	"TE_IMAGE_FILE_MACHINE_ARM=0x1c0, TE_IMAGE_FILE_MACHINE_AXP64=0x184, TE_IMAGE_FILE_MACHINE_CEE=0xc0ee, "
38 	"TE_IMAGE_FILE_MACHINE_CEF=0x0cef, TE_IMAGE_FILE_MACHINE_EBC=0x0ebc, TE_IMAGE_FILE_MACHINE_I386=0x014c, "
39 	"TE_IMAGE_FILE_MACHINE_IA64=0x0200, TE_IMAGE_FILE_MACHINE_M32R=0x9041, TE_IMAGE_FILE_MACHINE_M68K=0x0268, "
40 	"TE_IMAGE_FILE_MACHINE_MIPS16=0x0266, TE_IMAGE_FILE_MACHINE_MIPSFPU=0x0366, TE_IMAGE_FILE_MACHINE_MIPSFPU16=0x0466, "
41 	"TE_IMAGE_FILE_MACHINE_POWERPC=0x01f0, TE_IMAGE_FILE_MACHINE_POWERPCFP=0x01f1, TE_IMAGE_FILE_MACHINE_R10000=0x0168, "
42 	"TE_IMAGE_FILE_MACHINE_R3000=0x0162, TE_IMAGE_FILE_MACHINE_R4000=0x0166, TE_IMAGE_FILE_MACHINE_SH3=0x01a2, "
43 	"TE_IMAGE_FILE_MACHINE_SH3DSP=0x01a3, TE_IMAGE_FILE_MACHINE_SH3E=0x01a4, TE_IMAGE_FILE_MACHINE_SH4=0x01a6, "
44 	"TE_IMAGE_FILE_MACHINE_SH5=0x01a8, TE_IMAGE_FILE_MACHINE_THUMB=0x01c2, TE_IMAGE_FILE_MACHINE_TRICORE=0x0520, "
45 	"TE_IMAGE_FILE_MACHINE_WCEMIPSV2=0x0169};", 0);
46 	sdb_set (bin->kv, "te_subsystem.cparse", "enum te_subsystem { TE_IMAGE_SUBSYSTEM_UNKNOWN=0, TE_IMAGE_SUBSYSTEM_NATIVE=1, "
47 	"TE_IMAGE_SUBSYSTEM_WINDOWS_GUI=2, TE_IMAGE_SUBSYSTEM_WINDOWS_CUI=3, "
48 	"TE_IMAGE_SUBSYSTEM_POSIX_CUI=7, TE_IMAGE_SUBSYSTEM_WINDOWS_CE_GU=9, "
49 	"TE_IMAGE_SUBSYSTEM_EFI_APPLICATION=10, TE_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER=11, TE_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER=12, "
50 	"TE_IMAGE_SUBSYSTEM_EFI_ROM=13, TE_IMAGE_SUBSYSTEM_XBOX=14};", 0);
51 	sdb_num_set (bin->kv, "te_header.offset", 0, 0);
52 	sdb_set (bin->kv, "te_header.format", "[2]z[2]Eb[1]Ewxxq"
53 		" Signature (te_machine)Machine NumberOfSections (te_subsystem)Subsystem StrippedSize AddressOfEntryPoint BaseOfCode ImageBase", 0);
54 	sdb_num_set (bin->kv, "te_directory1_header.offset", 24, 0);
55 	sdb_set (bin->kv, "te_directory1_header.format", "xx"
56 		" VirtualAddress Size", 0);
57 	sdb_num_set (bin->kv, "te_directory2_header.offset", 32, 0);
58 	sdb_set (bin->kv, "te_directory2_header.format", "xx"
59 		" VirtualAddress Size", 0);
60 
61 	if (strncmp ((char *)&bin->header->Signature, "VZ", 2)) {
62 		return false;
63 	}
64 	return true;
65 }
66 
r_bin_te_get_main_paddr(struct r_bin_te_obj_t * bin)67 ut64 r_bin_te_get_main_paddr(struct r_bin_te_obj_t *bin) {
68 	RBinAddr *entry = r_bin_te_get_entrypoint (bin);
69 	ut64 addr = 0LL;
70 	ut8 buf[512];
71 	if (!bin) {
72 		return 0LL;
73 	}
74 	if (r_buf_read_at (bin->b, entry->paddr, buf, sizeof (buf)) == -1) {
75 		eprintf ("Error: read (entry)\n");
76 	} else {
77 		if (buf[367] == 0xe8) {
78 			int delta = (buf[368] | buf[369]<<8 | buf[370]<<16 | buf[371]<<24);
79 			delta += 367 + 5;
80 			addr = entry->vaddr;
81 			if (delta >= (UT64_MAX - addr)) {
82 				free (entry);
83 				return UT64_MAX;
84 			}
85 			addr += delta;
86 		}
87 	}
88 	free (entry);
89 	return addr;
90 }
91 
r_bin_te_vaddr_to_paddr(struct r_bin_te_obj_t * bin,TE_DWord vaddr)92 static TE_DWord r_bin_te_vaddr_to_paddr(struct r_bin_te_obj_t* bin, TE_DWord vaddr) {
93 	TE_DWord section_base;
94 	int i, section_size;
95 
96 	for (i = 0; i < bin->header->NumberOfSections; i++) {
97 		section_base = bin->section_header[i].VirtualAddress;
98 		section_size = bin->section_header[i].VirtualSize;
99 		if (vaddr >= section_base && vaddr < section_base + section_size) {
100 			return bin->section_header[i].PointerToRawData + (vaddr - section_base);
101 		}
102 	}
103 	return 0;
104 }
105 
r_bin_te_init_sections(struct r_bin_te_obj_t * bin)106 static int r_bin_te_init_sections(struct r_bin_te_obj_t* bin) {
107 	int sections_size = sizeof(TE_image_section_header) * bin->header->NumberOfSections;
108 	if (sections_size > bin->size) {
109 		eprintf ("Invalid NumberOfSections value\n");
110 		return false;
111 	}
112 	if (!(bin->section_header = malloc (sections_size))) {
113 		perror ("malloc (sections headers)");
114 		return false;
115 	}
116 	if (r_buf_read_at (bin->b, sizeof(TE_image_file_header),
117 				(ut8*)bin->section_header, sections_size) == -1) {
118 		eprintf ("Error: read (sections headers)\n");
119 		return false;
120 	}
121 	return true;
122 }
123 
r_bin_te_init(struct r_bin_te_obj_t * bin)124 static int r_bin_te_init(struct r_bin_te_obj_t* bin) {
125 	bin->header = NULL;
126 	bin->section_header = NULL;
127 	bin->endian = 0;
128 	if (!r_bin_te_init_hdr (bin)) {
129 		eprintf("Warning: File is not TE\n");
130 		return false;
131 	}
132 	if (!r_bin_te_init_sections (bin)) {
133 		eprintf("Warning: Cannot initialize sections\n");
134 		return false;
135 	}
136 	return true;
137 }
138 
r_bin_te_get_arch(struct r_bin_te_obj_t * bin)139 char* r_bin_te_get_arch(struct r_bin_te_obj_t* bin) {
140 	char *arch;
141 	if (!bin) {
142 		return NULL;
143 	}
144 	switch (bin->header->Machine) {
145 	case TE_IMAGE_FILE_MACHINE_ALPHA:
146 	case TE_IMAGE_FILE_MACHINE_ALPHA64:
147 		arch = strdup ("alpha");
148 		break;
149 	case TE_IMAGE_FILE_MACHINE_ARM:
150 	case TE_IMAGE_FILE_MACHINE_THUMB:
151 		arch = strdup ("arm");
152 		break;
153 	case TE_IMAGE_FILE_MACHINE_M68K:
154 		arch = strdup ("m68k");
155 		break;
156 	case TE_IMAGE_FILE_MACHINE_MIPS16:
157 	case TE_IMAGE_FILE_MACHINE_MIPSFPU:
158 	case TE_IMAGE_FILE_MACHINE_MIPSFPU16:
159 	case TE_IMAGE_FILE_MACHINE_WCEMIPSV2:
160 		arch = strdup ("mips");
161 		break;
162 	case TE_IMAGE_FILE_MACHINE_POWERPC:
163 	case TE_IMAGE_FILE_MACHINE_POWERPCFP:
164 		arch = strdup ("ppc");
165 		break;
166 	default:
167 		arch = strdup ("x86");
168 	}
169 	return arch;
170 }
171 
r_bin_te_get_bits(struct r_bin_te_obj_t * bin)172 int r_bin_te_get_bits(struct r_bin_te_obj_t* bin) {
173 	return 32; // It is always 32 bit by now
174 }
175 
176 
r_bin_te_get_entrypoint(struct r_bin_te_obj_t * bin)177 RBinAddr* r_bin_te_get_entrypoint(struct r_bin_te_obj_t* bin) {
178 	RBinAddr *entry = NULL;
179 
180 	if (!bin || !bin->header) {
181 		return NULL;
182 	}
183 	if (!(entry = malloc (sizeof (RBinAddr)))) {
184 		perror("malloc (entrypoint)");
185 		return NULL;
186 	}
187 	entry->vaddr = bin->header->AddressOfEntryPoint - r_bin_te_get_stripped_delta (bin);
188 	if (entry->vaddr == 0) { // in TE if EP = 0 then EP = baddr
189 		entry->vaddr = bin->header->ImageBase;
190 	}
191 	entry->paddr = r_bin_te_vaddr_to_paddr (bin, entry->vaddr);
192 	return entry;
193 }
194 
r_bin_te_get_image_base(struct r_bin_te_obj_t * bin)195 ut64 r_bin_te_get_image_base(struct r_bin_te_obj_t* bin)
196 {
197 	if (bin && bin->header) {
198 		return (ut64)bin->header->ImageBase;
199 	}
200 	return 0LL;
201 }
202 
r_bin_te_get_machine(struct r_bin_te_obj_t * bin)203 char* r_bin_te_get_machine(struct r_bin_te_obj_t* bin) {
204 	char *machine;
205 	if (!bin) {
206 		return NULL;
207 	}
208 	switch (bin->header->Machine) {
209 	case TE_IMAGE_FILE_MACHINE_ALPHA:
210 		machine = strdup ("Alpha");
211 		break;
212 	case TE_IMAGE_FILE_MACHINE_ALPHA64:
213 		machine = strdup ("Alpha 64");
214 		break;
215 	case TE_IMAGE_FILE_MACHINE_AM33:
216 		machine = strdup ("AM33");
217 		break;
218 	case TE_IMAGE_FILE_MACHINE_AMD64:
219 		machine = strdup ("AMD 64");
220 		break;
221 	case TE_IMAGE_FILE_MACHINE_ARM:
222 		machine = strdup ("ARM");
223 		break;
224 	case TE_IMAGE_FILE_MACHINE_CEE:
225 		machine = strdup ("CEE");
226 		break;
227 	case TE_IMAGE_FILE_MACHINE_CEF:
228 		machine = strdup ("CEF");
229 		break;
230 	case TE_IMAGE_FILE_MACHINE_EBC:
231 		machine = strdup ("EBC");
232 		break;
233 	case TE_IMAGE_FILE_MACHINE_I386:
234 		machine = strdup ("i386");
235 		break;
236 	case TE_IMAGE_FILE_MACHINE_IA64:
237 		machine = strdup ("ia64");
238 		break;
239 	case TE_IMAGE_FILE_MACHINE_M32R:
240 		machine = strdup ("M32R");
241 		break;
242 	case TE_IMAGE_FILE_MACHINE_M68K:
243 		machine = strdup ("M68K");
244 		break;
245 	case TE_IMAGE_FILE_MACHINE_MIPS16:
246 		machine = strdup ("Mips 16");
247 		break;
248 	case TE_IMAGE_FILE_MACHINE_MIPSFPU:
249 		machine = strdup ("Mips FPU");
250 		break;
251 	case TE_IMAGE_FILE_MACHINE_MIPSFPU16:
252 		machine = strdup ("Mips FPU 16");
253 		break;
254 	case TE_IMAGE_FILE_MACHINE_POWERPC:
255 		machine = strdup ("PowerPC");
256 		break;
257 	case TE_IMAGE_FILE_MACHINE_POWERPCFP:
258 		machine = strdup ("PowerPC FP");
259 		break;
260 	case TE_IMAGE_FILE_MACHINE_R10000:
261 		machine = strdup ("R10000");
262 		break;
263 	case TE_IMAGE_FILE_MACHINE_R3000:
264 		machine = strdup ("R3000");
265 		break;
266 	case TE_IMAGE_FILE_MACHINE_R4000:
267 		machine = strdup ("R4000");
268 		break;
269 	case TE_IMAGE_FILE_MACHINE_SH3:
270 		machine = strdup ("SH3");
271 		break;
272 	case TE_IMAGE_FILE_MACHINE_SH3DSP:
273 		machine = strdup ("SH3DSP");
274 		break;
275 	case TE_IMAGE_FILE_MACHINE_SH3E:
276 		machine = strdup ("SH3E");
277 		break;
278 	case TE_IMAGE_FILE_MACHINE_SH4:
279 		machine = strdup ("SH4");
280 		break;
281 	case TE_IMAGE_FILE_MACHINE_SH5:
282 		machine = strdup ("SH5");
283 		break;
284 	case TE_IMAGE_FILE_MACHINE_THUMB:
285 		machine = strdup ("Thumb");
286 		break;
287 	case TE_IMAGE_FILE_MACHINE_TRICORE:
288 		machine = strdup ("Tricore");
289 		break;
290 	case TE_IMAGE_FILE_MACHINE_WCEMIPSV2:
291 		machine = strdup ("WCE Mips V2");
292 		break;
293 	default:
294 		machine = strdup ("unknown");
295 	}
296 	return machine;
297 }
298 
r_bin_te_get_os(struct r_bin_te_obj_t * bin)299 char* r_bin_te_get_os(struct r_bin_te_obj_t* bin) {
300 	char *os;
301 	if (!bin) {
302 		return NULL;
303 	}
304 
305 	switch (bin->header->Subsystem) {
306 	case TE_IMAGE_SUBSYSTEM_NATIVE:
307 		os = strdup ("native");
308 		break;
309 	case TE_IMAGE_SUBSYSTEM_WINDOWS_GUI:
310 	case TE_IMAGE_SUBSYSTEM_WINDOWS_CUI:
311 	case TE_IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
312 		os = strdup ("windows");
313 		break;
314 	case TE_IMAGE_SUBSYSTEM_POSIX_CUI:
315 		os = strdup ("posix");
316 		break;
317 	case TE_IMAGE_SUBSYSTEM_EFI_APPLICATION:
318 	case TE_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
319 	case TE_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
320 	case TE_IMAGE_SUBSYSTEM_EFI_ROM:
321 		os = strdup ("efi");
322 		break;
323 	case TE_IMAGE_SUBSYSTEM_XBOX:
324 		os = strdup ("xbox");
325 		break;
326 	default:
327 		// XXX: this is unknown
328 		os = strdup ("windows");
329 	}
330 	return os;
331 }
332 
r_bin_te_get_sections(struct r_bin_te_obj_t * bin)333 struct r_bin_te_section_t* r_bin_te_get_sections(struct r_bin_te_obj_t* bin) {
334 	struct r_bin_te_section_t *sections = NULL;
335 	TE_image_section_header *shdr;
336 	int i, sections_count;
337 	if (!bin) {
338 		return NULL;
339 	}
340 	shdr = bin->section_header;
341 	sections_count = bin->header->NumberOfSections;
342 
343 	if (!(sections = calloc ((sections_count + 1), sizeof (struct r_bin_te_section_t)))) {
344 		perror ("malloc (sections)");
345 		return NULL;
346 	}
347 	for (i = 0; i < sections_count; i++) {
348 		memcpy (sections[i].name, shdr[i].Name, TE_IMAGE_SIZEOF_NAME);
349 		// not a null terminated string if len==buflen
350 		//sections[i].name[TE_IMAGE_SIZEOF_NAME] = '\0';
351 		sections[i].vaddr = shdr[i].VirtualAddress - r_bin_te_get_stripped_delta (bin);
352 		sections[i].size = shdr[i].SizeOfRawData;
353 		sections[i].vsize = shdr[i].VirtualSize;
354 		sections[i].paddr = shdr[i].PointerToRawData - r_bin_te_get_stripped_delta (bin);
355 		sections[i].flags = shdr[i].Characteristics;
356 		sections[i].last = 0;
357 	}
358 	sections[i].last = 1;
359 	return sections;
360 }
361 
r_bin_te_get_subsystem(struct r_bin_te_obj_t * bin)362 char* r_bin_te_get_subsystem(struct r_bin_te_obj_t* bin) {
363 	char *subsystem;
364 
365 	if (!bin) {
366 		return NULL;
367 	}
368 	switch (bin->header->Subsystem) {
369 	case TE_IMAGE_SUBSYSTEM_NATIVE:
370 		subsystem = strdup ("Native");
371 		break;
372 	case TE_IMAGE_SUBSYSTEM_WINDOWS_GUI:
373 		subsystem = strdup ("Windows GUI");
374 		break;
375 	case TE_IMAGE_SUBSYSTEM_WINDOWS_CUI:
376 		subsystem = strdup ("Windows CUI");
377 		break;
378 	case TE_IMAGE_SUBSYSTEM_POSIX_CUI:
379 		subsystem = strdup ("POSIX CUI");
380 		break;
381 	case TE_IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
382 		subsystem = strdup ("Windows CE GUI");
383 		break;
384 	case TE_IMAGE_SUBSYSTEM_EFI_APPLICATION:
385 		subsystem = strdup ("EFI Application");
386 		break;
387 	case TE_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
388 		subsystem = strdup ("EFI Boot Service Driver");
389 		break;
390 	case TE_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
391 		subsystem = strdup ("EFI Runtime Driver");
392 		break;
393 	case TE_IMAGE_SUBSYSTEM_EFI_ROM:
394 		subsystem = strdup ("EFI ROM");
395 		break;
396 	case TE_IMAGE_SUBSYSTEM_XBOX:
397 		subsystem = strdup ("XBOX");
398 		break;
399 	default:
400 		subsystem = strdup ("Unknown");
401 	}
402 	return subsystem;
403 }
404 
r_bin_te_free(struct r_bin_te_obj_t * bin)405 void* r_bin_te_free(struct r_bin_te_obj_t* bin) {
406 	if (!bin) {
407 		return NULL;
408 	}
409 	free (bin->header);
410 	free (bin->section_header);
411 	r_buf_free (bin->b);
412 	free (bin);
413 	return NULL;
414 }
415 
r_bin_te_new(const char * file)416 struct r_bin_te_obj_t* r_bin_te_new(const char* file) {
417 	struct r_bin_te_obj_t *bin = R_NEW0 (struct r_bin_te_obj_t);
418 	if (!bin) {
419 		return NULL;
420 	}
421 	bin->file = file;
422 	size_t binsz;
423 	ut8 *buf = (ut8*)r_file_slurp (file, &binsz);
424 	bin->size = binsz;
425 	if (!buf) {
426 		return r_bin_te_free (bin);
427 	}
428 	bin->b = r_buf_new ();
429 	if (!r_buf_set_bytes (bin->b, buf, bin->size)) {
430 		free (buf);
431 		return r_bin_te_free (bin);
432 	}
433 	free (buf);
434 	if (!r_bin_te_init (bin)) {
435 		return r_bin_te_free (bin);
436 	}
437 	return bin;
438 }
439 
r_bin_te_new_buf(RBuffer * buf)440 struct r_bin_te_obj_t* r_bin_te_new_buf(RBuffer *buf) {
441 	struct r_bin_te_obj_t *bin = R_NEW0 (struct r_bin_te_obj_t);
442 	if (!bin) {
443 		return NULL;
444 	}
445 	bin->kv = sdb_new0 ();
446 	bin->size = r_buf_size (buf);
447 	bin->b = r_buf_new_with_buf (buf);
448 	if (!bin->b) {
449 		return r_bin_te_free (bin);
450 	}
451 	if (!r_bin_te_init (bin)) {
452 		return r_bin_te_free (bin);
453 	}
454 	return bin;
455 }
456