mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-13 18:32:56 +00:00
PE: Add support for parsing TLS and add TLS callback addresses to the list of entry points.
Only add the address if its valid.
This commit is contained in:
parent
36e42b33fe
commit
0e3d4bf773
@ -103,6 +103,11 @@ static PE_DWord bin_pe_rva_to_va(RBinPEObj* bin, PE_DWord rva) {
|
||||
return bin->nt_headers->optional_header.ImageBase + rva;
|
||||
}
|
||||
|
||||
static PE_DWord bin_pe_va_to_rva(RBinPEObj* bin, PE_DWord va) {
|
||||
if (va < bin->nt_headers->optional_header.ImageBase) return va;
|
||||
return va - bin->nt_headers->optional_header.ImageBase;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static PE_DWord PE_(r_bin_pe_paddr_to_vaddr)(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord paddr)
|
||||
{
|
||||
@ -824,6 +829,57 @@ static int bin_pe_init_resource(struct PE_(r_bin_pe_obj_t)* bin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bin_pe_store_tls_callbacks(struct PE_(r_bin_pe_obj_t) *bin, PE_DWord callbacks) {
|
||||
PE_DWord paddr;
|
||||
int count = 0;
|
||||
PE_DWord addressOfTLSCallback = 1;
|
||||
char *key;
|
||||
|
||||
while (addressOfTLSCallback != 0) {
|
||||
if (r_buf_read_at (bin->b, callbacks, (ut8*)&addressOfTLSCallback, sizeof (addressOfTLSCallback)) != sizeof (addressOfTLSCallback)) {
|
||||
eprintf("Warning: read (tls_callback)\n");
|
||||
return;
|
||||
}
|
||||
if (addressOfTLSCallback == 0) break;
|
||||
if (bin->nt_headers->optional_header.SizeOfImage) {
|
||||
int rva_callback = bin_pe_va_to_rva (bin, (PE_DWord) addressOfTLSCallback);
|
||||
if (rva_callback > bin->nt_headers->optional_header.SizeOfImage) break;
|
||||
}
|
||||
key = sdb_fmt (0, "pe.tls_callback%d_vaddr", count);
|
||||
sdb_num_set (bin->kv, key, addressOfTLSCallback, 0);
|
||||
|
||||
key = sdb_fmt (0, "pe.tls_callback%d_paddr", count);
|
||||
paddr = bin_pe_rva_to_paddr (bin, bin_pe_va_to_rva(bin, (PE_DWord) addressOfTLSCallback));
|
||||
sdb_num_set (bin->kv, key, paddr, 0);
|
||||
|
||||
count++;
|
||||
callbacks += sizeof (addressOfTLSCallback);
|
||||
}
|
||||
}
|
||||
|
||||
static int bin_pe_init_tls(struct PE_(r_bin_pe_obj_t) *bin) {
|
||||
PE_(image_tls_directory) *image_tls_directory;
|
||||
PE_(image_data_directory) *data_dir_tls = \
|
||||
&bin->nt_headers->optional_header.DataDirectory[ \
|
||||
PE_IMAGE_DIRECTORY_ENTRY_TLS];
|
||||
PE_DWord tls_paddr = bin_pe_rva_to_paddr (bin,
|
||||
data_dir_tls->VirtualAddress);
|
||||
|
||||
image_tls_directory = R_NEW (PE_(image_tls_directory));
|
||||
if (r_buf_read_at (bin->b, tls_paddr, (ut8*)image_tls_directory, sizeof (PE_(image_tls_directory))) != sizeof (PE_(image_tls_directory))) {
|
||||
eprintf ("Warning: read (image_tls_directory)\n");
|
||||
free(image_tls_directory);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bin->tls_directory = image_tls_directory;
|
||||
if (!image_tls_directory->AddressOfCallBacks) return 0;
|
||||
PE_DWord callbacks_paddr = bin_pe_rva_to_paddr (bin, bin_pe_va_to_rva(bin, (PE_DWord) image_tls_directory->AddressOfCallBacks));
|
||||
bin_pe_store_tls_callbacks (bin, callbacks_paddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_Var(Var *var) {
|
||||
if (var) {
|
||||
free(var->szKey);
|
||||
@ -1693,6 +1749,8 @@ static int bin_pe_init(struct PE_(r_bin_pe_obj_t)* bin) {
|
||||
bin_pe_init_imports(bin);
|
||||
bin_pe_init_exports(bin);
|
||||
bin_pe_init_resource(bin);
|
||||
bin_pe_init_tls(bin);
|
||||
|
||||
PE_(r_bin_store_all_resource_version_info)(bin);
|
||||
bin->relocs = NULL;
|
||||
return true;
|
||||
|
@ -70,6 +70,7 @@ struct PE_(r_bin_pe_obj_t) {
|
||||
PE_(image_section_header) *section_header;
|
||||
PE_(image_export_directory) *export_directory;
|
||||
PE_(image_import_directory) *import_directory;
|
||||
PE_(image_tls_directory) *tls_directory;
|
||||
Pe_image_resource_directory *resource_directory;
|
||||
PE_(image_delay_import_directory) *delay_import_directory;
|
||||
// these values define the real offset into the untouched binary
|
||||
|
@ -289,6 +289,15 @@ typedef struct {
|
||||
ut32 TimeStamp;
|
||||
} Pe32_image_delay_import_directory, Pe64_image_delay_import_directory;
|
||||
|
||||
typedef struct {
|
||||
ut32 StartAddressOfRawData;
|
||||
ut32 EndAddressOfRawData;
|
||||
ut32 AddressOfIndex;
|
||||
ut32 AddressOfCallBacks;
|
||||
ut32 SizeOfZeroFill;
|
||||
ut32 Characteristics;
|
||||
} Pe32_image_tls_directory, Pe64_image_tls_directory;
|
||||
|
||||
typedef struct {
|
||||
ut32 Signature;
|
||||
Pe32_image_file_header file_header;
|
||||
|
@ -70,6 +70,33 @@ static RBinAddr* binsym(RBinFile *arch, int type) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void add_tls_callbacks(RBinFile *arch, RList* list) {
|
||||
PE_DWord paddr, vaddr;
|
||||
int count = 0;
|
||||
RBinAddr *ptr = NULL;
|
||||
struct PE_(r_bin_pe_obj_t) *bin = (struct PE_(r_bin_pe_obj_t) *) (arch->o->bin_obj);
|
||||
char *key;
|
||||
|
||||
do {
|
||||
key = sdb_fmt (0, "pe.tls_callback%d_paddr", count);
|
||||
paddr = sdb_num_get (bin->kv, key, 0);
|
||||
if (!paddr) break;
|
||||
|
||||
key = sdb_fmt (0, "pe.tls_callback%d_vaddr", count);
|
||||
vaddr = sdb_num_get (bin->kv, key, 0);
|
||||
if (!vaddr) break;
|
||||
|
||||
if ((ptr = R_NEW0 (RBinAddr))) {
|
||||
ptr->paddr = paddr;
|
||||
ptr->vaddr = vaddr;
|
||||
ptr->type = R_BIN_ENTRY_TYPE_TLS;
|
||||
r_list_append (list, ptr);
|
||||
}
|
||||
count++;
|
||||
} while (vaddr != 0);
|
||||
|
||||
}
|
||||
|
||||
static RList* entries(RBinFile *arch) {
|
||||
RList* ret;
|
||||
RBinAddr *ptr = NULL;
|
||||
@ -80,12 +107,17 @@ static RList* entries(RBinFile *arch) {
|
||||
ret->free = free;
|
||||
if (!(entry = PE_(r_bin_pe_get_entrypoint) (arch->o->bin_obj)))
|
||||
return ret;
|
||||
if ((ptr = R_NEW (RBinAddr))) {
|
||||
if ((ptr = R_NEW0 (RBinAddr))) {
|
||||
ptr->paddr = entry->paddr;
|
||||
ptr->vaddr = entry->vaddr;
|
||||
ptr->type = R_BIN_ENTRY_TYPE_PROGRAM;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
free (entry);
|
||||
|
||||
// get TLS callback addresses
|
||||
add_tls_callbacks (arch, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,11 @@ R_LIB_VERSION_HEADER (r_bin);
|
||||
#define R_BIN_DBG_SYMS 0x08
|
||||
#define R_BIN_DBG_RELOCS 0x10
|
||||
|
||||
#define R_BIN_ENTRY_TYPE_PROGRAM 0
|
||||
#define R_BIN_ENTRY_TYPE_INIT 1
|
||||
#define R_BIN_ENTRY_TYPE_FINI 2
|
||||
#define R_BIN_ENTRY_TYPE_TLS 3
|
||||
|
||||
#define R_BIN_SIZEOF_STRINGS 512
|
||||
#define R_BIN_MAX_ARCH 1024
|
||||
|
||||
@ -71,6 +76,7 @@ enum {
|
||||
typedef struct r_bin_addr_t {
|
||||
ut64 vaddr;
|
||||
ut64 paddr;
|
||||
int type;
|
||||
} RBinAddr;
|
||||
|
||||
typedef struct r_bin_hash_t {
|
||||
|
Loading…
x
Reference in New Issue
Block a user