Refactor rz_bin_pe_get_libs() to use SetS and RzPVector
This commit is contained in:
parent
61c8074cbf
commit
ca2bbc076c
5 changed files with 87 additions and 176 deletions
|
|
@ -5,6 +5,7 @@
|
|||
#include <rz_util.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_bin.h>
|
||||
#include <rz_vector.h>
|
||||
|
||||
#include "pe_specs.h"
|
||||
#include "dotnet.h"
|
||||
|
|
@ -114,11 +115,6 @@ struct rz_bin_pe_string_t {
|
|||
int last;
|
||||
};
|
||||
|
||||
struct rz_bin_pe_lib_t {
|
||||
char name[PE_STRING_LENGTH];
|
||||
int last;
|
||||
};
|
||||
|
||||
typedef struct _PE_RESOURCE {
|
||||
char *timestr;
|
||||
char *type;
|
||||
|
|
@ -233,7 +229,7 @@ struct rz_bin_pe_addr_t *PE_(check_mingw)(RzBinPEObj *bin);
|
|||
struct rz_bin_pe_addr_t *PE_(rz_bin_pe_get_entrypoint)(RzBinPEObj *bin);
|
||||
struct rz_bin_pe_addr_t *PE_(rz_bin_pe_get_main_vaddr)(RzBinPEObj *bin);
|
||||
int PE_(rz_bin_pe_get_image_size)(RzBinPEObj *bin);
|
||||
struct rz_bin_pe_lib_t *PE_(rz_bin_pe_get_libs)(RzBinPEObj *bin);
|
||||
RzPVector /*<char *>*/ *PE_(rz_bin_pe_get_libs)(RzBinPEObj *bin);
|
||||
ut64 PE_(rz_bin_pe_get_image_base)(RzBinPEObj *bin);
|
||||
|
||||
// pe_overlay.c
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// SPDX-FileCopyrightText: 2008-2019 inisider <inisider@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_util/set.h>
|
||||
#include "pe.h"
|
||||
|
||||
static inline int is_thumb(RzBinPEObj *bin) {
|
||||
|
|
@ -385,125 +386,79 @@ int PE_(rz_bin_pe_is_stripped_debug)(RzBinPEObj *bin) {
|
|||
return HASCHR(PE_IMAGE_FILE_DEBUG_STRIPPED);
|
||||
}
|
||||
|
||||
struct rz_bin_pe_lib_t *PE_(rz_bin_pe_get_libs)(RzBinPEObj *bin) {
|
||||
static inline bool bin_buf_contains(const RzBinPEObj *bin, ut64 offset, ut64 nbytes) {
|
||||
if (UT64_ADD_OVFCHK(offset, nbytes)) {
|
||||
return false;
|
||||
}
|
||||
return offset + nbytes <= bin->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an directory entry is empty (filled with zeroes)
|
||||
*/
|
||||
static inline bool image_import_directory_is_empty(const PE_(image_import_directory) * dir) {
|
||||
return !(dir->FirstThunk || dir->Name || dir->TimeDateStamp || dir->Characteristics || dir->ForwarderChain);
|
||||
}
|
||||
|
||||
RzPVector /*<char *>*/ *PE_(rz_bin_pe_get_libs)(RzBinPEObj *bin) {
|
||||
if (!bin) {
|
||||
return NULL;
|
||||
}
|
||||
struct rz_bin_pe_lib_t *libs = NULL;
|
||||
struct rz_bin_pe_lib_t *new_libs = NULL;
|
||||
if (!bin_buf_contains(bin, bin->import_directory_offset, bin->import_directory_size)) {
|
||||
return NULL;
|
||||
}
|
||||
PE_(image_import_directory)
|
||||
curr_import_dir;
|
||||
PE_(image_delay_import_directory)
|
||||
curr_delay_import_dir;
|
||||
PE_DWord name_off = 0;
|
||||
HtSS *lib_map = NULL;
|
||||
ut64 off; // cache value
|
||||
int index = 0;
|
||||
int len = 0;
|
||||
int max_libs = 20;
|
||||
libs = calloc(max_libs + 1, sizeof(struct rz_bin_pe_lib_t));
|
||||
|
||||
SetS *libs = set_s_new(HT_STR_DUP);
|
||||
if (!libs) {
|
||||
rz_sys_perror("malloc (libs)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bin->import_directory_offset + bin->import_directory_size > bin->size) {
|
||||
RZ_LOG_INFO("import directory offset bigger than file\n");
|
||||
goto out_error;
|
||||
}
|
||||
lib_map = sdb_ht_new();
|
||||
off = bin->import_directory_offset;
|
||||
if (off < bin->size && off > 0) {
|
||||
ut64 last;
|
||||
int iidi = 0;
|
||||
// normal imports
|
||||
if (off + sizeof(PE_(image_import_directory)) > bin->size) {
|
||||
goto out_error;
|
||||
}
|
||||
int r = PE_(read_image_import_directory)(bin->b, off + iidi * sizeof(curr_import_dir),
|
||||
&curr_import_dir);
|
||||
last = off + bin->import_directory_size;
|
||||
while (r == sizeof(curr_import_dir) && off + (iidi + 1) * sizeof(curr_import_dir) <= last && (curr_import_dir.FirstThunk || curr_import_dir.Name || curr_import_dir.TimeDateStamp || curr_import_dir.Characteristics || curr_import_dir.ForwarderChain)) {
|
||||
name_off = PE_(bin_pe_rva_to_paddr)(bin, curr_import_dir.Name);
|
||||
len = rz_buf_read_at(bin->b, name_off, (ut8 *)libs[index].name, PE_STRING_LENGTH);
|
||||
if (!libs[index].name[0]) { // minimum string length
|
||||
goto next;
|
||||
}
|
||||
if (len < 2 || libs[index].name[0] == 0) { // minimum string length
|
||||
RZ_LOG_INFO("read (libs - import dirs) %d\n", len);
|
||||
char lib_name[PE_STRING_LENGTH];
|
||||
ut64 dir_off = bin->import_directory_offset;
|
||||
if (dir_off != 0 && dir_off < bin->size) {
|
||||
const ut64 end_off = dir_off + bin->import_directory_size;
|
||||
for (; dir_off < end_off; dir_off += sizeof(curr_import_dir)) {
|
||||
if (PE_(read_image_import_directory)(bin->b, dir_off, &curr_import_dir) < 0) {
|
||||
break;
|
||||
}
|
||||
libs[index].name[len - 1] = '\0';
|
||||
rz_str_case(libs[index].name, 0);
|
||||
if (!sdb_ht_find(lib_map, libs[index].name, NULL)) {
|
||||
sdb_ht_insert(lib_map, libs[index].name, "a");
|
||||
libs[index++].last = 0;
|
||||
if (index >= max_libs) {
|
||||
new_libs = realloc(libs, (max_libs * 2) * sizeof(struct rz_bin_pe_lib_t));
|
||||
if (!new_libs) {
|
||||
rz_sys_perror("realloc (libs)");
|
||||
goto out_error;
|
||||
}
|
||||
libs = new_libs;
|
||||
new_libs = NULL;
|
||||
max_libs *= 2;
|
||||
}
|
||||
}
|
||||
next:
|
||||
iidi++;
|
||||
r = PE_(read_image_import_directory)(bin->b, off + iidi * sizeof(curr_import_dir),
|
||||
&curr_import_dir);
|
||||
}
|
||||
}
|
||||
off = bin->delay_import_directory_offset;
|
||||
if (off < bin->size && off > 0) {
|
||||
ut64 did = 0;
|
||||
if (off + sizeof(PE_(image_delay_import_directory)) > bin->size) {
|
||||
goto out_error;
|
||||
}
|
||||
int r = PE_(read_image_delay_import_directory)(bin->b, off, &curr_delay_import_dir);
|
||||
if (r != sizeof(curr_delay_import_dir)) {
|
||||
goto out_error;
|
||||
}
|
||||
while (r == sizeof(curr_delay_import_dir) &&
|
||||
curr_delay_import_dir.Name != 0 && curr_delay_import_dir.DelayImportNameTable != 0) {
|
||||
name_off = PE_(bin_pe_rva_to_paddr)(bin, curr_delay_import_dir.Name);
|
||||
if (name_off > bin->size || name_off + PE_STRING_LENGTH > bin->size) {
|
||||
goto out_error;
|
||||
}
|
||||
len = rz_buf_read_at(bin->b, name_off, (ut8 *)libs[index].name, PE_STRING_LENGTH);
|
||||
if (len != PE_STRING_LENGTH) {
|
||||
RZ_LOG_INFO("read (libs - delay import dirs)\n");
|
||||
if (image_import_directory_is_empty(&curr_import_dir)) {
|
||||
break;
|
||||
}
|
||||
libs[index].name[len - 1] = '\0';
|
||||
rz_str_case(libs[index].name, 0);
|
||||
if (!sdb_ht_find(lib_map, libs[index].name, NULL)) {
|
||||
sdb_ht_insert(lib_map, libs[index].name, "a");
|
||||
libs[index++].last = 0;
|
||||
if (index >= max_libs) {
|
||||
new_libs = realloc(libs, (max_libs * 2) * sizeof(struct rz_bin_pe_lib_t));
|
||||
if (!new_libs) {
|
||||
rz_sys_perror("realloc (libs)");
|
||||
goto out_error;
|
||||
}
|
||||
libs = new_libs;
|
||||
new_libs = NULL;
|
||||
max_libs *= 2;
|
||||
}
|
||||
PE_DWord name_off = PE_(bin_pe_rva_to_paddr)(bin, curr_import_dir.Name);
|
||||
st64 len = rz_buf_read_at(bin->b, name_off, (ut8 *)lib_name, PE_STRING_LENGTH);
|
||||
if (len < 2 || !lib_name[0]) {
|
||||
break;
|
||||
}
|
||||
did++;
|
||||
r = PE_(read_image_delay_import_directory)(bin->b, off + did * sizeof(curr_delay_import_dir),
|
||||
&curr_delay_import_dir);
|
||||
lib_name[len - 1] = '\0';
|
||||
rz_str_case(lib_name, 0);
|
||||
set_s_add(libs, lib_name);
|
||||
}
|
||||
}
|
||||
sdb_ht_free(lib_map);
|
||||
libs[index].last = 1;
|
||||
return libs;
|
||||
out_error:
|
||||
sdb_ht_free(lib_map);
|
||||
free(libs);
|
||||
return NULL;
|
||||
dir_off = bin->delay_import_directory_offset;
|
||||
if (dir_off != 0 && dir_off < bin->size) {
|
||||
for (;; dir_off += sizeof(curr_delay_import_dir)) {
|
||||
if (PE_(read_image_delay_import_directory)(bin->b, dir_off, &curr_delay_import_dir) < 0) {
|
||||
break;
|
||||
}
|
||||
if (curr_delay_import_dir.Name == 0 || curr_delay_import_dir.DelayImportNameTable == 0) {
|
||||
break;
|
||||
}
|
||||
PE_DWord name_off = PE_(bin_pe_rva_to_paddr)(bin, curr_delay_import_dir.Name);
|
||||
st64 len = rz_buf_read_at(bin->b, name_off, (ut8 *)lib_name, PE_STRING_LENGTH);
|
||||
if (len < 2 || !lib_name[0]) {
|
||||
break;
|
||||
}
|
||||
lib_name[len - 1] = '\0';
|
||||
rz_str_case(lib_name, 0);
|
||||
set_s_add(libs, lib_name);
|
||||
}
|
||||
}
|
||||
RzPVector *vec = set_s_to_vector(libs);
|
||||
set_s_free(libs);
|
||||
return vec;
|
||||
}
|
||||
|
||||
int PE_(rz_bin_pe_get_image_size)(RzBinPEObj *bin) {
|
||||
|
|
|
|||
|
|
@ -124,11 +124,8 @@ static RzBinInfo *mdmp_info(RzBinFile *bf) {
|
|||
|
||||
static RzPVector /*<char *>*/ *mdmp_libs(RzBinFile *bf) {
|
||||
char *ptr = NULL;
|
||||
int i;
|
||||
MiniDmpObj *obj;
|
||||
struct rz_bin_pe_lib_t *libs = NULL;
|
||||
struct Pe32_rz_bin_mdmp_pe_bin *pe32_bin;
|
||||
struct Pe64_rz_bin_mdmp_pe_bin *pe64_bin;
|
||||
RzPVector *libs = NULL;
|
||||
RzPVector *ret = NULL;
|
||||
RzListIter *it;
|
||||
|
||||
|
|
@ -143,25 +140,29 @@ static RzPVector /*<char *>*/ *mdmp_libs(RzBinFile *bf) {
|
|||
|
||||
/* TODO: Resolve module name for lib, or filter to remove duplicates,
|
||||
** rather than the vaddr :) */
|
||||
struct Pe32_rz_bin_mdmp_pe_bin *pe32_bin;
|
||||
rz_list_foreach (obj->pe32_bins, it, pe32_bin) {
|
||||
if (!(libs = Pe32_rz_bin_pe_get_libs(pe32_bin->bin))) {
|
||||
return ret;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; !libs[i].last; i++) {
|
||||
ptr = rz_str_newf("[0x%.08" PFMT64x "] - %s", pe32_bin->vaddr, libs[i].name);
|
||||
void **libs_iter;
|
||||
rz_pvector_foreach (libs, libs_iter) {
|
||||
ptr = rz_str_newf("[0x%.08" PFMT64x "] - %s", pe32_bin->vaddr, (char *)*libs_iter);
|
||||
rz_pvector_push(ret, ptr);
|
||||
}
|
||||
free(libs);
|
||||
rz_pvector_free(libs);
|
||||
}
|
||||
struct Pe64_rz_bin_mdmp_pe_bin *pe64_bin;
|
||||
rz_list_foreach (obj->pe64_bins, it, pe64_bin) {
|
||||
if (!(libs = Pe64_rz_bin_pe_get_libs(pe64_bin->bin))) {
|
||||
return ret;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; !libs[i].last; i++) {
|
||||
ptr = rz_str_newf("[0x%.08" PFMT64x "] - %s", pe64_bin->vaddr, libs[i].name);
|
||||
void **libs_iter;
|
||||
rz_pvector_foreach (libs, libs_iter) {
|
||||
ptr = rz_str_newf("[0x%.08" PFMT64x "] - %s", pe64_bin->vaddr, (char *)*libs_iter);
|
||||
rz_pvector_push(ret, ptr);
|
||||
}
|
||||
free(libs);
|
||||
rz_pvector_free(libs);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -498,23 +498,7 @@ static RzPVector /*<RzBinReloc *>*/ *relocs(RzBinFile *bf) {
|
|||
}
|
||||
|
||||
static RzPVector /*<char *>*/ *libs(RzBinFile *bf) {
|
||||
struct rz_bin_pe_lib_t *libs = NULL;
|
||||
RzPVector *ret = NULL;
|
||||
char *ptr = NULL;
|
||||
int i;
|
||||
|
||||
if (!(ret = rz_pvector_new(free))) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(libs = PE_(rz_bin_pe_get_libs)(bf->o->bin_obj))) {
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; !libs[i].last; i++) {
|
||||
ptr = strdup(libs[i].name);
|
||||
rz_pvector_push(ret, ptr);
|
||||
}
|
||||
free(libs);
|
||||
return ret;
|
||||
return PE_(rz_bin_pe_get_libs)(bf->o->bin_obj);
|
||||
}
|
||||
|
||||
static RzPVector /*<RzBinResource *>*/ *resources(RzBinFile *bf) {
|
||||
|
|
@ -569,38 +553,6 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool is_dot_net(RzBinFile *bf) {
|
||||
struct rz_bin_pe_lib_t *libs = NULL;
|
||||
int i;
|
||||
if (!(libs = PE_(rz_bin_pe_get_libs)(bf->o->bin_obj))) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; !libs[i].last; i++) {
|
||||
if (!strcmp(libs[i].name, "mscoree.dll")) {
|
||||
free(libs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
free(libs);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_vb6(RzBinFile *bf) {
|
||||
struct rz_bin_pe_lib_t *libs = NULL;
|
||||
int i;
|
||||
if (!(libs = PE_(rz_bin_pe_get_libs)(bf->o->bin_obj))) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; !libs[i].last; i++) {
|
||||
if (!strcmp(libs[i].name, "msvbvm60.dll")) {
|
||||
free(libs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
free(libs);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int has_canary(RzBinFile *bf) {
|
||||
// XXX: We only need imports here but this causes leaks, we need to wait for the below. This is a horrible solution!
|
||||
// TODO: use O(1) when imports sdbized
|
||||
|
|
@ -636,6 +588,10 @@ static inline bool haschr(const struct PE_(rz_bin_pe_obj_t) * bin, ut16 dllChara
|
|||
return bin->nt_headers->optional_header.DllCharacteristics & dllCharacteristic;
|
||||
}
|
||||
|
||||
static int compare_strings(const void *a, const void *b, RZ_UNUSED void *user) {
|
||||
return strcmp((const char *)a, (const char *)b);
|
||||
}
|
||||
|
||||
static RzBinInfo *info(RzBinFile *bf) {
|
||||
struct PE_(rz_bin_pe_obj_t) * bin;
|
||||
SDebugInfo di = { { 0 } };
|
||||
|
|
@ -654,12 +610,15 @@ static RzBinInfo *info(RzBinFile *bf) {
|
|||
ret->machine = PE_(rz_bin_pe_get_machine)(bf->o->bin_obj);
|
||||
ret->subsystem = PE_(rz_bin_pe_get_subsystem)(bf->o->bin_obj);
|
||||
ret->default_cc = PE_(rz_bin_pe_get_cc)(bf->o->bin_obj);
|
||||
if (is_dot_net(bf)) {
|
||||
|
||||
RzPVector *libs = PE_(rz_bin_pe_get_libs)(bf->o->bin_obj);
|
||||
if (libs && rz_pvector_find(libs, "mscoree.dll", compare_strings, NULL)) {
|
||||
ret->lang = "cil";
|
||||
}
|
||||
if (is_vb6(bf)) {
|
||||
if (libs && rz_pvector_find(libs, "msvbvm60.dll", compare_strings, NULL)) {
|
||||
ret->lang = "vb";
|
||||
}
|
||||
rz_pvector_free(libs);
|
||||
|
||||
if (PE_(rz_bin_pe_is_dll)(bf->o->bin_obj)) {
|
||||
ret->type = strdup("DLL (Dynamic Link Library)");
|
||||
|
|
|
|||
|
|
@ -111,15 +111,15 @@ CMDS=il
|
|||
EXPECT=<<EOF
|
||||
library
|
||||
-------------
|
||||
kernel32.dll
|
||||
user32.dll
|
||||
advapi32.dll
|
||||
oleaut32.dll
|
||||
ole32.dll
|
||||
kernel32.dll
|
||||
pstorec.dll
|
||||
rasapi32.dll
|
||||
shell32.dll
|
||||
crypt32.dll
|
||||
oleaut32.dll
|
||||
advapi32.dll
|
||||
ole32.dll
|
||||
rasapi32.dll
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue