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