Rizin
unix-like reverse engineering framework and cli tools
pe_imports.c File Reference
#include "pe.h"

Go to the source code of this file.

Functions

int PE_() read_image_import_directory (RzBuffer *b, ut64 addr, PE_(image_import_directory) *import_dir)
 
int PE_() read_image_delay_import_directory (RzBuffer *b, ut64 addr, PE_(image_delay_import_directory) *directory)
 
static char * resolveModuleOrdinal (Sdb *sdb, const char *module, int ordinal)
 
static int bin_pe_parse_imports (RzBinPEObj *bin, struct rz_bin_pe_import_t **importp, int *nimp, const char *dll_name, PE_DWord OriginalFirstThunk, PE_DWord FirstThunk)
 
struct rz_bin_pe_import_t *PE_() rz_bin_pe_get_imports (RzBinPEObj *bin)
 
int PE_() bin_pe_init_imports (RzBinPEObj *bin)
 

Function Documentation

◆ bin_pe_init_imports()

int PE_() bin_pe_init_imports ( RzBinPEObj bin)

HACK to modify import size because of begin 0.. this may report wrong info con corkami tests

Definition at line 325 of file pe_imports.c.

325  {
326  PE_(image_data_directory) *data_dir_import = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_IMPORT];
327  PE_(image_data_directory) *data_dir_delay_import = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
328 
329  PE_DWord import_dir_paddr = PE_(bin_pe_rva_to_paddr)(bin, data_dir_import->VirtualAddress);
330  PE_DWord import_dir_offset = PE_(bin_pe_rva_to_paddr)(bin, data_dir_import->VirtualAddress);
331  PE_DWord delay_import_dir_offset = PE_(bin_pe_rva_to_paddr)(bin, data_dir_delay_import->VirtualAddress);
332 
333  PE_(image_import_directory) *import_dir = NULL;
334  PE_(image_import_directory) *new_import_dir = NULL;
335  PE_(image_import_directory) *curr_import_dir = NULL;
336 
337  PE_(image_delay_import_directory) *delay_import_dir = NULL;
338  PE_(image_delay_import_directory) *new_delay_import_dir = NULL;
339  PE_(image_delay_import_directory) *curr_delay_import_dir = NULL;
340 
341  int dir_size = sizeof(PE_(image_import_directory));
342  int delay_import_size = sizeof(PE_(image_delay_import_directory));
343  int indx = 0;
344  int rr, count = 0;
345  int import_dir_size = data_dir_import->Size;
346  int delay_import_dir_size = data_dir_delay_import->Size;
348  if (!import_dir_size) {
349  // asume 1 entry for each
350  import_dir_size = data_dir_import->Size = 0xffff;
351  }
352  if (!delay_import_dir_size) {
353  data_dir_delay_import->Size = 0xffff;
354  }
355  int maxidsz = RZ_MIN((PE_DWord)bin->size, import_dir_offset + import_dir_size);
356  maxidsz -= import_dir_offset;
357  if (maxidsz < 0) {
358  maxidsz = 0;
359  }
360  // int maxcount = maxidsz/ sizeof (struct rz_bin_pe_import_t);
361 
362  RZ_FREE(bin->import_directory);
363  if (import_dir_paddr != 0) {
364  if (import_dir_size < 1 || import_dir_size > maxidsz) {
365  RZ_LOG_INFO("Invalid import directory size: 0x%x is now 0x%x\n", import_dir_size, maxidsz);
366  import_dir_size = maxidsz;
367  }
368  bin->import_directory_offset = import_dir_offset;
369  count = 0;
370  do {
371  new_import_dir = (PE_(image_import_directory) *)realloc(import_dir, ((1 + indx) * dir_size));
372  if (!new_import_dir) {
373  rz_sys_perror("malloc (import directory)");
374  RZ_FREE(import_dir);
375  break; //
376  // goto fail;
377  }
378  import_dir = new_import_dir;
379  new_import_dir = NULL;
380  curr_import_dir = import_dir + indx;
381  if (PE_(read_image_import_directory)(bin->b, import_dir_offset + indx * dir_size, curr_import_dir) <= 0) {
382  RZ_LOG_INFO("read (import directory)\n");
383  RZ_FREE(import_dir);
384  break; // return false;
385  }
386  if (((2 + indx) * dir_size) > import_dir_size) {
387  break; // goto fail;
388  }
389  indx++;
390  count++;
391  } while (curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
392  curr_import_dir->TimeDateStamp != 0 || curr_import_dir->Characteristics != 0 ||
393  curr_import_dir->ForwarderChain != 0);
394 
395  bin->import_directory = import_dir;
396  bin->import_directory_size = import_dir_size;
397  }
398 
399  indx = 0;
400  if (rz_buf_size(bin->b) > 0) {
401  if ((delay_import_dir_offset != 0) && (delay_import_dir_offset < (ut32)rz_buf_size(bin->b))) {
402  ut64 off;
403  bin->delay_import_directory_offset = delay_import_dir_offset;
404  do {
405  indx++;
406  off = indx * delay_import_size;
407  if (off >= rz_buf_size(bin->b)) {
408  RZ_LOG_INFO("Cannot find end of import symbols\n");
409  break;
410  }
411  new_delay_import_dir = (PE_(image_delay_import_directory) *)realloc(
412  delay_import_dir, (indx * delay_import_size) + 1);
413  if (!new_delay_import_dir) {
414  rz_sys_perror("malloc (delay import directory)");
415  free(delay_import_dir);
416  return false;
417  }
418  delay_import_dir = new_delay_import_dir;
419  curr_delay_import_dir = delay_import_dir + (indx - 1);
420  rr = PE_(read_image_delay_import_directory)(bin->b, delay_import_dir_offset + (indx - 1) * delay_import_size,
421  curr_delay_import_dir);
422  if (rr != dir_size) {
423  RZ_LOG_INFO("read (delay import directory)\n");
424  goto fail;
425  }
426  } while (curr_delay_import_dir->Name != 0);
427  bin->delay_import_directory = delay_import_dir;
428  }
429  }
430 
431  return true;
432 fail:
433  RZ_FREE(import_dir);
434  bin->import_directory = import_dir;
435  free(delay_import_dir);
436  return false;
437 }
#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 count
Definition: sflib.h:98
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
int off
Definition: pal.c:13
PE_DWord PE_() bin_pe_rva_to_paddr(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:15
int PE_() read_image_delay_import_directory(RzBuffer *b, ut64 addr, PE_(image_delay_import_directory) *directory)
Definition: pe_imports.c:24
int PE_() read_image_import_directory(RzBuffer *b, ut64 addr, PE_(image_import_directory) *import_dir)
Definition: pe_imports.c:8
#define PE_(name)
Definition: pe_specs.h:23
#define PE_IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pe_specs.h:144
#define PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
Definition: pe_specs.h:157
#define PE_DWord
Definition: pe_specs.h:27
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define rz_sys_perror(x)
Definition: rz_types.h:336
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
Definition: malloc.c:26
#define fail(test)
Definition: tests.h:29
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int indx(const char **ptr, const char **list, int error, const char **expr)
Definition: z80asm.c:154

References bin_pe_rva_to_paddr(), count, fail, free(), indx(), NULL, off, PE_, PE_DWord, PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, PE_IMAGE_DIRECTORY_ENTRY_IMPORT, read_image_delay_import_directory(), read_image_import_directory(), realloc(), rz_buf_size(), RZ_FREE, RZ_LOG_INFO, RZ_MIN, rz_sys_perror, and ut64().

Referenced by bin_pe_init().

◆ bin_pe_parse_imports()

static int bin_pe_parse_imports ( RzBinPEObj bin,
struct rz_bin_pe_import_t **  importp,
int nimp,
const char *  dll_name,
PE_DWord  OriginalFirstThunk,
PE_DWord  FirstThunk 
)
static

Definition at line 54 of file pe_imports.c.

58  {
59  char import_name[PE_NAME_LENGTH + 1];
60  char name[PE_NAME_LENGTH + 1];
61  PE_Word import_hint, import_ordinal = 0;
62  PE_DWord import_table = 0, off = 0;
63  int i = 0, len;
64  Sdb *db = NULL;
65  char *sdb_module = NULL;
66  char *symname = NULL;
67  char *filename = NULL;
68  char *symdllname = NULL;
69 
70  if (!dll_name || !*dll_name || *dll_name == '0') {
71  return 0;
72  }
73 
74  if (!(off = PE_(bin_pe_rva_to_paddr)(bin, OriginalFirstThunk)) &&
75  !(off = PE_(bin_pe_rva_to_paddr)(bin, FirstThunk))) {
76  return 0;
77  }
78  do {
79  if (import_ordinal >= UT16_MAX) {
80  break;
81  }
82  if (off + i * sizeof(PE_DWord) > bin->size) {
83  break;
84  }
85  if (!RZ_BUF_READ_PE_DWORD_AT(bin->b, off + i * sizeof(PE_DWord), &import_table)) {
86  RZ_LOG_INFO("read (import table)\n");
87  goto error;
88  } else if (import_table) {
89  if (import_table & ILT_MASK1) {
90  import_ordinal = import_table & ILT_MASK2;
91  import_hint = 0;
92  snprintf(import_name, PE_NAME_LENGTH, "Ordinal_%i", import_ordinal);
93  free(symdllname);
94  strncpy(name, dll_name, sizeof(name) - 1);
95  name[sizeof(name) - 1] = 0;
96  symdllname = strdup(name);
97 
98  // remove the trailling ".dll"
99  size_t len = strlen(symdllname);
100  rz_str_case(symdllname, 0);
101  len = len < 4 ? 0 : len - 4;
102  symdllname[len] = 0;
103 
104  if (!sdb_module || strcmp(symdllname, sdb_module)) {
105  sdb_free(db);
106  if (db) {
107  sdb_free(db);
108  }
109  db = NULL;
110  free(sdb_module);
111  sdb_module = strdup(symdllname);
112  filename = rz_str_newf("%s.sdb", symdllname);
113  if (filename && rz_file_exists(filename)) {
114  db = sdb_new(NULL, filename, 0);
115  } else {
116  char *formats_dir = rz_path_system(RZ_SDB_FORMAT);
117  free(filename);
118  filename = rz_str_newf(RZ_JOIN_3_PATHS("%s", "dll", "%s.sdb"), formats_dir, symdllname);
119  free(formats_dir);
120  if (rz_file_exists(filename)) {
121  db = sdb_new(NULL, filename, 0);
122  }
123  }
124  }
125  if (db) {
126  symname = resolveModuleOrdinal(db, symdllname, import_ordinal);
127  if (symname) {
128  snprintf(import_name, PE_NAME_LENGTH, "%s", symname);
129  RZ_FREE(symname);
130  }
131  } else {
132  RZ_LOG_INFO("Cannot find %s\n", filename);
133  }
134  RZ_FREE(filename);
135  } else {
136  import_ordinal++;
137  const ut64 off = PE_(bin_pe_rva_to_paddr)(bin, import_table);
138  if (off > bin->size || (off + sizeof(PE_Word)) > bin->size) {
139  RZ_LOG_INFO("off > bin->size\n");
140  goto error;
141  }
142  if (!rz_buf_read_le16_at(bin->b, off, &import_hint)) {
143  RZ_LOG_INFO("read import hint at 0x%08" PFMT64x "\n", off);
144  goto error;
145  }
146  name[0] = '\0';
147  len = rz_buf_read_at(bin->b, off + sizeof(PE_Word), (ut8 *)name, PE_NAME_LENGTH);
148  if (len < 1) {
149  RZ_LOG_INFO("read (import name)\n");
150  goto error;
151  } else if (!*name) {
152  break;
153  }
154  name[PE_NAME_LENGTH] = '\0';
155  int len = snprintf(import_name, sizeof(import_name), "%s", name);
156  if (len >= sizeof(import_name)) {
157  RZ_LOG_WARN("Import name '%s' has been truncated.\n", import_name);
158  }
159  }
160  struct rz_bin_pe_import_t *new_importp = realloc(*importp, (*nimp + 1) * sizeof(struct rz_bin_pe_import_t));
161  if (!new_importp) {
162  rz_sys_perror("realloc (import)");
163  goto error;
164  }
165  *importp = new_importp;
166  memcpy((*importp)[*nimp].name, import_name, PE_NAME_LENGTH);
167  (*importp)[*nimp].name[PE_NAME_LENGTH] = '\0';
168  memcpy((*importp)[*nimp].libname, dll_name, PE_NAME_LENGTH);
169  (*importp)[*nimp].libname[PE_NAME_LENGTH] = '\0';
170  (*importp)[*nimp].vaddr = PE_(bin_pe_rva_to_va)(bin, FirstThunk + i * sizeof(PE_DWord));
171  (*importp)[*nimp].paddr = PE_(bin_pe_rva_to_paddr)(bin, FirstThunk) + i * sizeof(PE_DWord);
172  (*importp)[*nimp].hint = import_hint;
173  (*importp)[*nimp].ordinal = import_ordinal;
174  (*importp)[*nimp].last = 0;
175  (*nimp)++;
176  i++;
177  }
178  } while (import_table);
179 
180  if (db) {
181  sdb_free(db);
182  db = NULL;
183  }
184  free(symdllname);
185  free(sdb_module);
186  return i;
187 
188 error:
189  if (db) {
190  sdb_free(db);
191  db = NULL;
192  }
193  free(symdllname);
194  free(sdb_module);
195  return false;
196 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
const char * filename
Definition: ioapi.h:137
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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")
const char * name
Definition: op.c:541
PE_DWord PE_() bin_pe_rva_to_va(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:28
static char * resolveModuleOrdinal(Sdb *sdb, const char *module, int ordinal)
Definition: pe_imports.c:43
#define PE_NAME_LENGTH
Definition: pe_specs.h:36
#define ILT_MASK2
Definition: pe_specs.h:25
#define PE_Word
Definition: pe_specs.h:26
#define ILT_MASK1
Definition: pe_specs.h:24
#define RZ_BUF_READ_PE_DWORD_AT
Definition: pe_specs.h:29
#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 bool rz_file_exists(const char *str)
Definition: file.c:192
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void rz_str_case(char *str, bool up)
Definition: str.c:341
#define RZ_JOIN_3_PATHS(p1, p2, p3)
Definition: rz_types.h:225
#define PFMT64x
Definition: rz_types.h:393
#define UT16_MAX
#define RZ_SDB_FORMAT
Definition: rz_userconf.h:87
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
Definition: z80asm.h:102
ut8 libname[PE_NAME_LENGTH+1]
Definition: pe.h:76
Definition: sdb.h:63
void error(const char *msg)
Definition: untgz.c:593

References bin_pe_rva_to_paddr(), bin_pe_rva_to_va(), error(), free(), i, ILT_MASK1, ILT_MASK2, len, rz_bin_pe_import_t::libname, memcpy(), name, NULL, off, PE_, PE_DWord, PE_NAME_LENGTH, PE_Word, PFMT64x, realloc(), resolveModuleOrdinal(), rz_buf_read_at(), rz_buf_read_le16_at, RZ_BUF_READ_PE_DWORD_AT, rz_file_exists(), RZ_FREE, RZ_JOIN_3_PATHS, RZ_LOG_INFO, RZ_LOG_WARN, rz_path_system(), RZ_SDB_FORMAT, rz_str_case(), rz_str_newf(), rz_sys_perror, sdb_free(), sdb_new(), snprintf, strdup(), UT16_MAX, and ut64().

Referenced by rz_bin_pe_get_imports().

◆ read_image_delay_import_directory()

int PE_() read_image_delay_import_directory ( RzBuffer b,
ut64  addr,
PE_(image_delay_import_directory) *  directory 
)

Definition at line 24 of file pe_imports.c.

24  {
25  st64 o_addr = rz_buf_seek(b, 0, RZ_BUF_CUR);
26  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
27  return -1;
28  }
29  ut8 buf[sizeof(PE_(image_delay_import_directory))];
30  rz_buf_read(b, buf, sizeof(buf));
31  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), Attributes, 32);
32  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), Name, 32);
33  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), ModulePlugin, 32);
34  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), DelayImportAddressTable, 32);
35  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), DelayImportNameTable, 32);
36  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), BoundDelayImportTable, 32);
37  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), UnloadDelayImportTable, 32);
38  PE_READ_STRUCT_FIELD(directory, PE_(image_delay_import_directory), TimeStamp, 32);
39  rz_buf_seek(b, o_addr, RZ_BUF_SET);
40  return sizeof(PE_(image_delay_import_directory));
41 }
voidpf void * buf
Definition: ioapi.h:138
directory
Definition: regress.py:17
#define PE_READ_STRUCT_FIELD(var, struct_type, field, size)
Definition: pe.h:177
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_CUR
Definition: rz_buf.h:15
#define RZ_BUF_SET
Definition: rz_buf.h:14
RZ_API st64 rz_buf_read(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
#define st64
Definition: rz_types_base.h:10
#define b(i)
Definition: sha256.c:42
static int addr
Definition: z80asm.c:58

References addr, b, regress::directory, PE_, PE_READ_STRUCT_FIELD, RZ_BUF_CUR, rz_buf_read(), rz_buf_seek(), RZ_BUF_SET, and st64.

Referenced by bin_pe_init_imports(), rz_bin_pe_get_imports(), and rz_bin_pe_get_libs().

◆ read_image_import_directory()

int PE_() read_image_import_directory ( RzBuffer b,
ut64  addr,
PE_(image_import_directory) *  import_dir 
)

Definition at line 8 of file pe_imports.c.

8  {
9  st64 o_addr = rz_buf_seek(b, 0, RZ_BUF_CUR);
10  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
11  return -1;
12  }
13  ut8 buf[sizeof(PE_(image_import_directory))];
14  rz_buf_read(b, buf, sizeof(buf));
15  PE_READ_STRUCT_FIELD(import_dir, PE_(image_import_directory), Characteristics, 32);
16  PE_READ_STRUCT_FIELD(import_dir, PE_(image_import_directory), TimeDateStamp, 32);
17  PE_READ_STRUCT_FIELD(import_dir, PE_(image_import_directory), ForwarderChain, 32);
18  PE_READ_STRUCT_FIELD(import_dir, PE_(image_import_directory), Name, 32);
19  PE_READ_STRUCT_FIELD(import_dir, PE_(image_import_directory), FirstThunk, 32);
20  rz_buf_seek(b, o_addr, RZ_BUF_SET);
21  return sizeof(PE_(image_import_directory));
22 }

References addr, b, PE_, PE_READ_STRUCT_FIELD, RZ_BUF_CUR, rz_buf_read(), rz_buf_seek(), RZ_BUF_SET, and st64.

Referenced by bin_pe_init_imports(), rz_bin_pe_get_imports(), and rz_bin_pe_get_libs().

◆ resolveModuleOrdinal()

static char* resolveModuleOrdinal ( Sdb sdb,
const char *  module,
int  ordinal 
)
static

Definition at line 43 of file pe_imports.c.

43  {
44  Sdb *db = sdb;
45  char *foo = sdb_get(db, sdb_fmt("%d", ordinal), 0);
46  if (foo && *foo) {
47  return foo;
48  } else {
49  free(foo); // should never happen
50  }
51  return NULL;
52 }
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
static RzMain foo[]
Definition: main.c:11
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290

References foo, free(), NULL, sdb_fmt(), and sdb_get().

Referenced by bin_pe_parse_imports().

◆ rz_bin_pe_get_imports()

struct rz_bin_pe_import_t* PE_() rz_bin_pe_get_imports ( RzBinPEObj bin)

Definition at line 198 of file pe_imports.c.

198  {
199  struct rz_bin_pe_import_t *imps, *imports = NULL;
200  char dll_name[PE_NAME_LENGTH + 1];
201  int nimp = 0;
202  ut64 off; // used to cache value
203  PE_DWord dll_name_offset = 0;
204  PE_DWord paddr = 0;
205  PE_DWord import_func_name_offset;
206  PE_(image_import_directory)
207  curr_import_dir;
208  PE_(image_delay_import_directory)
209  curr_delay_import_dir;
210 
211  if (!bin) {
212  return NULL;
213  }
214  if (bin->import_directory_offset >= bin->size) {
215  return NULL;
216  }
217  if (bin->import_directory_offset + 20 > bin->size) {
218  return NULL;
219  }
220 
221  off = bin->import_directory_offset;
222  if (off < bin->size && off > 0) {
223  ut64 last;
224  int idi = 0;
225  if (off + sizeof(PE_(image_import_directory)) > bin->size) {
226  return NULL;
227  }
228  int r = PE_(read_image_import_directory)(bin->b, bin->import_directory_offset + idi * sizeof(curr_import_dir), &curr_import_dir);
229  if (r < 0) {
230  return NULL;
231  }
232 
233  if (bin->import_directory_size < 1) {
234  return NULL;
235  }
236  if (off + bin->import_directory_size > bin->size) {
237  // why chopping instead of returning and cleaning?
238  RZ_LOG_INFO("read (import directory too big)\n");
239  bin->import_directory_size = bin->size - bin->import_directory_offset;
240  }
241  last = bin->import_directory_offset + bin->import_directory_size;
242  while (r == sizeof(curr_import_dir) && bin->import_directory_offset + (idi + 1) * sizeof(curr_import_dir) <= last && (curr_import_dir.FirstThunk != 0 || curr_import_dir.Name != 0 || curr_import_dir.TimeDateStamp != 0 || curr_import_dir.Characteristics != 0 || curr_import_dir.ForwarderChain != 0)) {
243  int rr;
244  dll_name_offset = curr_import_dir.Name;
245  paddr = PE_(bin_pe_rva_to_paddr)(bin, dll_name_offset);
246  if (paddr > bin->size) {
247  goto beach;
248  }
249  if (paddr + PE_NAME_LENGTH > bin->size) {
250  rr = rz_buf_read_at(bin->b, paddr, (ut8 *)dll_name, bin->size - paddr);
251  if (rr != bin->size - paddr) {
252  goto beach;
253  }
254  dll_name[bin->size - paddr] = '\0';
255  } else {
256  rr = rz_buf_read_at(bin->b, paddr, (ut8 *)dll_name, PE_NAME_LENGTH);
257  if (rr != PE_NAME_LENGTH) {
258  goto beach;
259  }
260  dll_name[PE_NAME_LENGTH] = '\0';
261  }
262  if (!bin_pe_parse_imports(bin, &imports, &nimp, dll_name,
263  curr_import_dir.Characteristics,
264  curr_import_dir.FirstThunk)) {
265  break;
266  }
267  idi++;
268  r = PE_(read_image_import_directory)(bin->b, bin->import_directory_offset + idi * sizeof(curr_import_dir), &curr_import_dir);
269  if (r < 0) {
270  free(imports);
271  return NULL;
272  }
273  }
274  }
275  off = bin->delay_import_directory_offset;
276  if (off < bin->size && off > 0) {
277  if (off + sizeof(PE_(image_delay_import_directory)) > bin->size) {
278  goto beach;
279  }
280  int didi;
281  for (didi = 0;; didi++) {
282  int r = PE_(read_image_delay_import_directory)(bin->b, off + didi * sizeof(curr_delay_import_dir),
283  &curr_delay_import_dir);
284  if (r != sizeof(curr_delay_import_dir)) {
285  goto beach;
286  }
287  if ((curr_delay_import_dir.Name == 0) || (curr_delay_import_dir.DelayImportAddressTable == 0)) {
288  break;
289  }
290  if (!curr_delay_import_dir.Attributes) {
291  dll_name_offset = PE_(bin_pe_rva_to_paddr)(bin, curr_delay_import_dir.Name - PE_(rz_bin_pe_get_image_base)(bin));
292  import_func_name_offset = curr_delay_import_dir.DelayImportNameTable - PE_(rz_bin_pe_get_image_base)(bin);
293  } else {
294  dll_name_offset = PE_(bin_pe_rva_to_paddr)(bin, curr_delay_import_dir.Name);
295  import_func_name_offset = curr_delay_import_dir.DelayImportNameTable;
296  }
297  if (dll_name_offset > bin->size || dll_name_offset + PE_NAME_LENGTH > bin->size) {
298  goto beach;
299  }
300  int rr = rz_buf_read_at(bin->b, dll_name_offset, (ut8 *)dll_name, PE_NAME_LENGTH);
301  if (rr < 5) {
302  goto beach;
303  }
304  dll_name[PE_NAME_LENGTH] = '\0';
305  if (!bin_pe_parse_imports(bin, &imports, &nimp, dll_name, import_func_name_offset,
306  curr_delay_import_dir.DelayImportAddressTable)) {
307  break;
308  }
309  }
310  }
311 beach:
312  if (nimp) {
313  imps = realloc(imports, (nimp + 1) * sizeof(struct rz_bin_pe_import_t));
314  if (!imps) {
315  rz_sys_perror("realloc (import)");
316  free(imports);
317  return NULL;
318  }
319  imports = imps;
320  imports[nimp].last = 1;
321  }
322  return imports;
323 }
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
#define r
Definition: crypto_rc6.c:12
voidpf void uLong size
Definition: ioapi.h:138
ut64 PE_() rz_bin_pe_get_image_base(RzBinPEObj *bin)
Definition: pe_info.c:588
static int bin_pe_parse_imports(RzBinPEObj *bin, struct rz_bin_pe_import_t **importp, int *nimp, const char *dll_name, PE_DWord OriginalFirstThunk, PE_DWord FirstThunk)
Definition: pe_imports.c:54
ut64 paddr
Definition: pe.h:78

References bin_pe_parse_imports(), bin_pe_rva_to_paddr(), free(), imports(), rz_bin_pe_import_t::last, NULL, off, rz_bin_pe_import_t::paddr, PE_, PE_DWord, PE_NAME_LENGTH, r, read_image_delay_import_directory(), read_image_import_directory(), realloc(), rz_bin_pe_get_image_base(), rz_buf_read_at(), RZ_LOG_INFO, rz_sys_perror, and ut64().

Referenced by rz_bin_mdmp_pe_get_imports(), and rz_bin_mdmp_pe_get_symbols().