|
|
e2e2c2 |
/***************************************************************/
|
|
|
e2e2c2 |
/* perk: PE Resource Kit */
|
|
|
ced38a |
/* Copyright (C) 2015--2017 Z. Gilboa */
|
|
|
e2e2c2 |
/* Released under GPLv2 and GPLv3; see COPYING.PERK. */
|
|
|
e2e2c2 |
/***************************************************************/
|
|
|
e2e2c2 |
|
|
|
c0fbae |
#include <stdint.h>
|
|
|
c0fbae |
#include <stdlib.h>
|
|
|
c0fbae |
#include <stdio.h>
|
|
|
c0fbae |
#include <string.h>
|
|
|
c0fbae |
|
|
|
20e8a3 |
#include <mdso/mdso_specs.h>
|
|
|
20e8a3 |
#include <mdso/mdso_structs.h>
|
|
|
20e8a3 |
|
|
|
c0fbae |
#include <perk/perk.h>
|
|
|
413f56 |
#include "perk_reader_impl.h"
|
|
|
0e3fd6 |
#include "perk_errinfo_impl.h"
|
|
|
c0fbae |
|
|
|
0e3fd6 |
static int pe_free_image_meta_impl(struct pe_image_meta * meta, int ret)
|
|
|
c0fbae |
{
|
|
|
c3f597 |
int i;
|
|
|
4e9e98 |
|
|
|
fa22b4 |
if (meta) {
|
|
|
2111da |
for (i=0; i<meta->m_stats.t_nimplibs; i++)
|
|
|
58ced9 |
free(meta->m_idata[i].ih_items);
|
|
|
c0fbae |
|
|
|
58ced9 |
free(meta->m_idata);
|
|
|
58ced9 |
free(meta->m_sectbl);
|
|
|
fa22b4 |
free(meta);
|
|
|
fa22b4 |
}
|
|
|
da8e21 |
|
|
|
0e3fd6 |
return ret;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
2b7f36 |
void pe_free_image_meta(struct pe_image_meta * meta)
|
|
|
c0fbae |
{
|
|
|
fa22b4 |
pe_free_image_meta_impl(meta,0);
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
2b7f36 |
int pe_get_named_section_index(const struct pe_image_meta * m, const char * name)
|
|
|
c0fbae |
{
|
|
|
58ced9 |
int i; for (i=0; i<m->m_coff.cfh_num_of_sections; i++)
|
|
|
58ced9 |
if (!(strcmp(name,m->m_sectbl[i].sh_name)))
|
|
|
c0fbae |
return i;
|
|
|
c0fbae |
|
|
|
c0fbae |
return -1;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
2b7f36 |
int pe_get_block_section_index(const struct pe_image_meta * m, const struct pe_block * block)
|
|
|
c0fbae |
{
|
|
|
c0fbae |
int i;
|
|
|
c0fbae |
uint32_t low,high;
|
|
|
c0fbae |
|
|
|
f3d26e |
if (m->r_obj)
|
|
|
862cb6 |
return -1;
|
|
|
862cb6 |
|
|
|
58ced9 |
for (i=0; i<m->m_coff.cfh_num_of_sections; i++) {
|
|
|
58ced9 |
low = m->m_sectbl[i].sh_virtual_addr;
|
|
|
58ced9 |
high = low + m->m_sectbl[i].sh_virtual_size;
|
|
|
c0fbae |
|
|
|
a402c4 |
if ((block->dh_rva >= low) && (block->dh_rva + block->dh_size <= high))
|
|
|
c0fbae |
return i;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
c0fbae |
return -1;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
62b9db |
int pe_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, uint32_t * roffset)
|
|
|
62b9db |
{
|
|
|
62b9db |
int i;
|
|
|
62b9db |
uint32_t low,high;
|
|
|
62b9db |
|
|
|
58ced9 |
for (i=0; i<m->m_coff.cfh_num_of_sections; i++) {
|
|
|
58ced9 |
low = m->m_sectbl[i].sh_virtual_addr;
|
|
|
58ced9 |
high = low + m->m_sectbl[i].sh_virtual_size;
|
|
|
62b9db |
|
|
|
62b9db |
if ((rva >= low) && (rva < high)) {
|
|
|
58ced9 |
*roffset = (rva - low) + m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
62b9db |
return 0;
|
|
|
62b9db |
}
|
|
|
62b9db |
}
|
|
|
62b9db |
|
|
|
62b9db |
return -1;
|
|
|
62b9db |
}
|
|
|
62b9db |
|
|
|
62b9db |
int pe_get_rva_from_roffset(const struct pe_image_meta * m, uint32_t roffset, uint32_t * rva)
|
|
|
62b9db |
{
|
|
|
62b9db |
int i;
|
|
|
62b9db |
uint32_t low,high,ref;
|
|
|
62b9db |
|
|
|
58ced9 |
for (i=0, ref=~0; i<m->m_coff.cfh_num_of_sections; i++) {
|
|
|
58ced9 |
low = m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
58ced9 |
high = low + m->m_sectbl[i].sh_virtual_size;
|
|
|
62b9db |
|
|
|
62b9db |
if ((roffset >= low) && (roffset < high)) {
|
|
|
58ced9 |
*rva = (roffset - low) + m->m_sectbl[i].sh_virtual_addr;
|
|
|
62b9db |
return 0;
|
|
|
62b9db |
} else if (ref > low) {
|
|
|
62b9db |
ref = low;
|
|
|
62b9db |
}
|
|
|
62b9db |
}
|
|
|
62b9db |
|
|
|
62b9db |
if (roffset < ref) {
|
|
|
62b9db |
*rva = roffset;
|
|
|
62b9db |
return 0;
|
|
|
62b9db |
}
|
|
|
62b9db |
|
|
|
62b9db |
return -1;
|
|
|
62b9db |
}
|
|
|
62b9db |
|
|
|
cf4adc |
int pe_get_expsym_by_name(
|
|
|
c7ca52 |
const struct pe_image_meta * m,
|
|
|
cf4adc |
const char * name,
|
|
|
cf4adc |
struct pe_expsym * expsym)
|
|
|
c7ca52 |
{
|
|
|
c7ca52 |
uint32_t offset;
|
|
|
c7ca52 |
uint32_t * symrva;
|
|
|
c7ca52 |
const char * sym;
|
|
|
c7ca52 |
unsigned i;
|
|
|
c7ca52 |
|
|
|
f3d26e |
if (m->r_obj || !m->h_edata)
|
|
|
862cb6 |
return -1;
|
|
|
862cb6 |
|
|
|
25e3c0 |
offset = m->h_edata->sh_virtual_addr - m->h_edata->sh_ptr_to_raw_data;
|
|
|
ed06fb |
symrva = (uint32_t *)((uintptr_t)m->r_image.map_addr + (m->m_edata.eh_name_ptr_rva - offset));
|
|
|
c7ca52 |
|
|
|
58ced9 |
for (i=0; i<m->m_edata.eh_num_of_name_ptrs; i++) {
|
|
|
ed06fb |
sym = (const char *)m->r_image.map_addr + symrva[i] - offset;
|
|
|
c7ca52 |
|
|
|
cf4adc |
if (!(strcmp(sym,name))) {
|
|
|
cf4adc |
if (expsym) {
|
|
|
f0d194 |
expsym->s_name = sym;
|
|
|
f0d194 |
expsym->s_eaddr = 0;
|
|
|
f0d194 |
expsym->s_maddr = 0;
|
|
|
f0d194 |
expsym->s_roffset = 0;
|
|
|
cf4adc |
}
|
|
|
cf4adc |
|
|
|
cf4adc |
return 0;
|
|
|
cf4adc |
}
|
|
|
c7ca52 |
}
|
|
|
c7ca52 |
|
|
|
cf4adc |
return -1;
|
|
|
c7ca52 |
}
|
|
|
c7ca52 |
|
|
|
cf4adc |
int pe_get_expsym_by_index(
|
|
|
c7ca52 |
const struct pe_image_meta * m,
|
|
|
cf4adc |
unsigned index,
|
|
|
cf4adc |
struct pe_expsym * expsym)
|
|
|
c7ca52 |
{
|
|
|
c7ca52 |
uint32_t offset;
|
|
|
c7ca52 |
uint32_t * symrva;
|
|
|
cf4adc |
uintptr_t symaddr;
|
|
|
c7ca52 |
|
|
|
f3d26e |
if (m->r_obj)
|
|
|
862cb6 |
return -1;
|
|
|
862cb6 |
|
|
|
58ced9 |
if (index >= m->m_edata.eh_num_of_name_ptrs)
|
|
|
cf4adc |
return -1;
|
|
|
c7ca52 |
|
|
|
cf4adc |
if (expsym) {
|
|
|
25e3c0 |
offset = m->h_edata->sh_virtual_addr - m->h_edata->sh_ptr_to_raw_data;
|
|
|
ed06fb |
symrva = (uint32_t *)((uintptr_t)m->r_image.map_addr + (m->m_edata.eh_name_ptr_rva - offset));
|
|
|
ed06fb |
symaddr = (uintptr_t)m->r_image.map_addr + symrva[index] - offset;
|
|
|
c7ca52 |
|
|
|
f0d194 |
expsym->s_name = (const char *)symaddr;
|
|
|
f0d194 |
expsym->s_eaddr = 0;
|
|
|
f0d194 |
expsym->s_maddr = 0;
|
|
|
f0d194 |
expsym->s_roffset = 0;
|
|
|
cf4adc |
}
|
|
|
cf4adc |
|
|
|
cf4adc |
return 0;
|
|
|
c7ca52 |
}
|
|
|
c7ca52 |
|
|
|
180890 |
static void pe_detect_image_abi(struct pe_image_meta * m)
|
|
|
180890 |
{
|
|
|
180890 |
int abi;
|
|
|
180890 |
|
|
|
180890 |
if (m->r_obj) {
|
|
|
180890 |
switch (m->m_coff.cfh_machine) {
|
|
|
180890 |
case PE_IMAGE_FILE_MACHINE_I386:
|
|
|
180890 |
abi = PE_ABI_PE32;
|
|
|
180890 |
break;
|
|
|
180890 |
|
|
|
180890 |
case PE_IMAGE_FILE_MACHINE_IA64:
|
|
|
180890 |
case PE_IMAGE_FILE_MACHINE_AMD64:
|
|
|
180890 |
abi = PE_ABI_PE64;
|
|
|
180890 |
break;
|
|
|
180890 |
|
|
|
180890 |
default:
|
|
|
180890 |
abi = PE_ABI_UNSUPPORTED;
|
|
|
180890 |
break;
|
|
|
180890 |
}
|
|
|
180890 |
} else {
|
|
|
180890 |
switch (m->m_opt.oh_std.coh_magic) {
|
|
|
180890 |
case PE_MAGIC_PE32:
|
|
|
180890 |
abi = PE_ABI_PE32;
|
|
|
180890 |
break;
|
|
|
180890 |
|
|
|
180890 |
case PE_MAGIC_PE32_PLUS:
|
|
|
180890 |
abi = PE_ABI_PE64;
|
|
|
180890 |
break;
|
|
|
180890 |
|
|
|
180890 |
default:
|
|
|
180890 |
abi = PE_ABI_UNSUPPORTED;
|
|
|
180890 |
break;
|
|
|
180890 |
}
|
|
|
180890 |
}
|
|
|
180890 |
|
|
|
180890 |
m->m_abi = abi;
|
|
|
180890 |
}
|
|
|
180890 |
|
|
|
aec459 |
static void pe_detect_image_subtype(struct pe_image_meta * m)
|
|
|
aec459 |
{
|
|
|
aec459 |
int subtype;
|
|
|
aec459 |
|
|
|
aec459 |
if (m->r_obj)
|
|
|
aec459 |
subtype = PE_SUBTYPE_OBJ;
|
|
|
aec459 |
|
|
|
aec459 |
else if (m->m_coff.cfh_characteristics & PE_IMAGE_FILE_DLL)
|
|
|
aec459 |
subtype = PE_SUBTYPE_DLL;
|
|
|
aec459 |
|
|
|
aec459 |
else
|
|
|
aec459 |
subtype = PE_SUBTYPE_EXE;
|
|
|
aec459 |
|
|
|
aec459 |
m->m_subtype = subtype;
|
|
|
aec459 |
}
|
|
|
aec459 |
|
|
|
c13a6b |
static bool pe_image_is_psxscl(const struct pe_image_meta * m)
|
|
|
c13a6b |
{
|
|
|
c13a6b |
return (!m->m_stats.t_nimplibs
|
|
|
c13a6b |
&& !pe_get_expsym_by_name(m,"__psx_init",0));
|
|
|
c13a6b |
}
|
|
|
c13a6b |
|
|
|
c13a6b |
static bool pe_image_is_cygwin(const struct pe_image_meta * m)
|
|
|
c13a6b |
{
|
|
|
c13a6b |
int i;
|
|
|
c13a6b |
|
|
|
c13a6b |
for (i=0; i<m->m_stats.t_nimplibs; i++)
|
|
|
c13a6b |
if (!(strcmp(m->m_idata[i].ih_name,"cygwin1.dll")))
|
|
|
c13a6b |
return true;
|
|
|
c13a6b |
|
|
|
c13a6b |
return false;
|
|
|
c13a6b |
}
|
|
|
c13a6b |
|
|
|
c13a6b |
static bool pe_image_is_msys(const struct pe_image_meta * m)
|
|
|
c13a6b |
{
|
|
|
c13a6b |
int i;
|
|
|
c13a6b |
|
|
|
c13a6b |
for (i=0; i<m->m_stats.t_nimplibs; i++)
|
|
|
c13a6b |
if (!(strcmp(m->m_idata[i].ih_name,"msys-2.0.dll")))
|
|
|
c13a6b |
return true;
|
|
|
c13a6b |
|
|
|
c13a6b |
return false;
|
|
|
c13a6b |
}
|
|
|
c13a6b |
|
|
|
c13a6b |
static bool pe_image_is_mingw(const struct pe_image_meta * m)
|
|
|
c13a6b |
{
|
|
|
c13a6b |
return ((pe_get_named_section_index(m,".CRT") >= 0)
|
|
|
c13a6b |
&& (pe_get_named_section_index(m,".bss") >= 0)
|
|
|
c13a6b |
&& (pe_get_named_section_index(m,".tls") >= 0));
|
|
|
c13a6b |
}
|
|
|
c13a6b |
|
|
|
c13a6b |
static void pe_detect_image_framework(struct pe_image_meta * m)
|
|
|
c13a6b |
{
|
|
|
c13a6b |
int framework;
|
|
|
c13a6b |
|
|
|
c13a6b |
if (pe_get_named_section_index(m,".midipix") >= 0)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_MIDIPIX;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_get_named_section_index(m,".freestd") >= 0)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_FREESTD;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_get_named_section_index(m,".cygheap") >= 0)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_CYGONE;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_image_is_psxscl(m))
|
|
|
c13a6b |
framework = PE_FRAMEWORK_PSXSCL;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_image_is_cygwin(m))
|
|
|
c13a6b |
framework = PE_FRAMEWORK_CYGWIN;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_image_is_msys(m))
|
|
|
c13a6b |
framework = PE_FRAMEWORK_MSYS;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (pe_image_is_mingw(m))
|
|
|
c13a6b |
framework = PE_FRAMEWORK_MINGW;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_POSIX_CUI)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_SUACON;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_WINCON;
|
|
|
c13a6b |
|
|
|
c13a6b |
else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
|
|
c13a6b |
framework = PE_FRAMEWORK_WIN32;
|
|
|
c13a6b |
|
|
|
c13a6b |
else
|
|
|
c13a6b |
framework = PE_FRAMEWORK_UNKNOWN;
|
|
|
c13a6b |
|
|
|
c13a6b |
m->m_framework = framework;
|
|
|
c13a6b |
}
|
|
|
c13a6b |
|
|
|
0e3fd6 |
int pe_get_image_meta(
|
|
|
0e3fd6 |
const struct pe_driver_ctx * dctx,
|
|
|
0e3fd6 |
const struct pe_raw_image * image,
|
|
|
0e3fd6 |
struct pe_image_meta ** meta)
|
|
|
c0fbae |
{
|
|
|
85fd0d |
int ret;
|
|
|
85fd0d |
int i,s;
|
|
|
85fd0d |
long l;
|
|
|
85fd0d |
unsigned j;
|
|
|
4a8ae6 |
const unsigned char * mark;
|
|
|
85fd0d |
struct pe_image_meta * m;
|
|
|
85fd0d |
char * base;
|
|
|
a7f9b1 |
uint64_t vaddr;
|
|
|
85fd0d |
|
|
|
ed06fb |
base = image->map_addr;
|
|
|
c0fbae |
|
|
|
c0fbae |
if (!(m = calloc(1,sizeof(*m))))
|
|
|
0e3fd6 |
return PERK_SYSTEM_ERROR(dctx);
|
|
|
c0fbae |
|
|
|
f3d26e |
m->r_obj = (struct pe_raw_coff_object_hdr *)base;
|
|
|
c0fbae |
|
|
|
f3d26e |
if (pe_read_object_header(m->r_obj,&m->m_coff)) {
|
|
|
f3d26e |
m->r_obj = 0;
|
|
|
f3d26e |
m->r_dos = (struct pe_raw_image_dos_hdr *)base;
|
|
|
c0fbae |
|
|
|
f3d26e |
if ((ret = (pe_read_dos_header(m->r_dos,&m->m_dos))))
|
|
|
862cb6 |
return pe_free_image_meta_impl(
|
|
|
862cb6 |
m,PERK_CUSTOM_ERROR(dctx,ret));
|
|
|
c0fbae |
|
|
|
f3d26e |
m->r_coff = (struct pe_raw_coff_image_hdr *)(base + m->m_dos.dos_lfanew);
|
|
|
862cb6 |
|
|
|
f3d26e |
if ((ret = (pe_read_coff_header(m->r_coff,&m->m_coff))))
|
|
|
862cb6 |
return pe_free_image_meta_impl(
|
|
|
862cb6 |
m,PERK_CUSTOM_ERROR(dctx,ret));
|
|
|
862cb6 |
}
|
|
|
c0fbae |
|
|
|
58ced9 |
mark = (const unsigned char *)base + m->m_coff.cfh_ptr_to_sym_tbl;
|
|
|
58ced9 |
mark += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol);
|
|
|
67b1e9 |
|
|
|
58ced9 |
if (m->m_coff.cfh_ptr_to_sym_tbl) {
|
|
|
58ced9 |
m->m_coff.cfh_ptr_to_str_tbl = m->m_coff.cfh_ptr_to_sym_tbl;
|
|
|
58ced9 |
m->m_coff.cfh_ptr_to_str_tbl += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol);
|
|
|
58ced9 |
m->m_coff.cfh_size_of_str_tbl = pe_read_long(mark);
|
|
|
b60586 |
}
|
|
|
67b1e9 |
|
|
|
f3d26e |
if (m->r_dos) {
|
|
|
f3d26e |
mark = &m->r_coff->cfh_signature[0];
|
|
|
f3d26e |
m->r_opt = (union pe_raw_opt_hdr *)(mark + sizeof(*m->r_coff));
|
|
|
c0fbae |
|
|
|
f3d26e |
if ((ret = (pe_read_optional_header(m->r_opt,&m->m_opt))))
|
|
|
862cb6 |
return pe_free_image_meta_impl(
|
|
|
862cb6 |
m,PERK_CUSTOM_ERROR(dctx,ret));
|
|
|
c0fbae |
|
|
|
f3d26e |
mark = &m->r_opt->opt_hdr_32.coh_magic[0];
|
|
|
f3d26e |
m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + m->m_coff.cfh_size_of_opt_hdr);
|
|
|
862cb6 |
} else {
|
|
|
f3d26e |
mark = &m->r_obj->cfh_machine[0];
|
|
|
f3d26e |
m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + sizeof(*m->r_obj));
|
|
|
862cb6 |
}
|
|
|
c0fbae |
|
|
|
58ced9 |
if (!(m->m_sectbl = calloc(m->m_coff.cfh_num_of_sections,sizeof(*(m->m_sectbl)))))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_SYSTEM_ERROR(dctx));
|
|
|
c0fbae |
|
|
|
58ced9 |
for (i=0; i<m->m_coff.cfh_num_of_sections; i++) {
|
|
|
f3d26e |
pe_read_section_header(&m->r_sectbl[i],&m->m_sectbl[i]);
|
|
|
c0fbae |
|
|
|
58ced9 |
if (m->m_sectbl[i].sh_name[0] == '/')
|
|
|
58ced9 |
if ((l = strtol(&m->m_sectbl[i].sh_name[1],0,10)) > 0)
|
|
|
58ced9 |
if (l < m->m_coff.cfh_size_of_str_tbl)
|
|
|
58ced9 |
m->m_sectbl[i].sh_long_name = base + m->m_coff.cfh_ptr_to_str_tbl + l;
|
|
|
67b1e9 |
}
|
|
|
67b1e9 |
|
|
|
c0fbae |
/* .edata */
|
|
|
c0fbae |
i = pe_get_named_section_index(m,".edata");
|
|
|
58ced9 |
s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_export_tbl);
|
|
|
c0fbae |
|
|
|
c0fbae |
if ((i >= 0) && (i != s))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED));
|
|
|
c0fbae |
|
|
|
ed9e7f |
if (s >= 0) {
|
|
|
25e3c0 |
m->h_edata = &m->m_sectbl[s];
|
|
|
f3d26e |
m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data
|
|
|
58ced9 |
+ m->m_opt.oh_dirs.coh_export_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr);
|
|
|
ffd8a3 |
m->m_edata.eh_virtual_addr = m->m_opt.oh_dirs.coh_export_tbl.dh_rva;
|
|
|
ed9e7f |
} else if (i >= 0) {
|
|
|
25e3c0 |
m->h_edata = &m->m_sectbl[i];
|
|
|
f3d26e |
m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data);
|
|
|
ffd8a3 |
m->m_edata.eh_virtual_addr = m->m_sectbl[i].sh_virtual_addr;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
f3d26e |
if (m->r_edata) {
|
|
|
f3d26e |
pe_read_export_header(m->r_edata,&m->m_edata);
|
|
|
2111da |
m->m_stats.t_nexpsyms = m->m_edata.eh_num_of_name_ptrs;
|
|
|
ad7d42 |
}
|
|
|
c0fbae |
|
|
|
c0fbae |
/* .idata */
|
|
|
34ee9e |
struct pe_raw_import_hdr * pidata;
|
|
|
34ee9e |
union pe_raw_import_lookup * pitem;
|
|
|
c0fbae |
|
|
|
c0fbae |
i = pe_get_named_section_index(m,".idata");
|
|
|
58ced9 |
s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_import_tbl);
|
|
|
c0fbae |
|
|
|
c0fbae |
if ((i >= 0) && (i != s))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED));
|
|
|
c0fbae |
|
|
|
ed9e7f |
if (s >= 0) {
|
|
|
25e3c0 |
m->h_idata = &m->m_sectbl[s];
|
|
|
f3d26e |
m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data
|
|
|
58ced9 |
+ m->m_opt.oh_dirs.coh_import_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr);
|
|
|
a7f9b1 |
vaddr = m->m_opt.oh_dirs.coh_import_tbl.dh_rva;
|
|
|
ed9e7f |
} else if (i >= 0) {
|
|
|
25e3c0 |
m->h_idata = &m->m_sectbl[i];
|
|
|
f3d26e |
m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data);
|
|
|
a7f9b1 |
vaddr = m->m_sectbl[i].sh_virtual_addr;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
f3d26e |
if (m->r_idata) {
|
|
|
c0fbae |
/* num of implibs */
|
|
|
f3d26e |
for (pidata=m->r_idata; pe_read_long(pidata->ih_name_rva); pidata++)
|
|
|
2111da |
m->m_stats.t_nimplibs++;
|
|
|
c0fbae |
|
|
|
c0fbae |
/* import headers */
|
|
|
2111da |
if (!(m->m_idata = calloc(m->m_stats.t_nimplibs,sizeof(*m->m_idata))))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_SYSTEM_ERROR(dctx));
|
|
|
c0fbae |
|
|
|
2111da |
for (i=0; i<m->m_stats.t_nimplibs; i++) {
|
|
|
a7f9b1 |
m->m_idata[i].ih_virtual_addr = vaddr + (i * sizeof(*m->r_idata));
|
|
|
f3d26e |
pe_read_import_header(&m->r_idata[i],&m->m_idata[i]);
|
|
|
c0fbae |
|
|
|
25e3c0 |
m->m_idata[i].ih_name = base + m->h_idata->sh_ptr_to_raw_data
|
|
|
58ced9 |
+ m->m_idata[i].ih_name_rva
|
|
|
25e3c0 |
- m->h_idata->sh_virtual_addr;
|
|
|
c0fbae |
|
|
|
58ced9 |
if (m->m_idata[i].ih_import_lookup_tbl_rva)
|
|
|
25e3c0 |
m->m_idata[i].ih_aitems = (union pe_raw_import_lookup *)(base + m->h_idata->sh_ptr_to_raw_data
|
|
|
58ced9 |
+ m->m_idata[i].ih_import_lookup_tbl_rva
|
|
|
25e3c0 |
- m->h_idata->sh_virtual_addr);
|
|
|
c0fbae |
|
|
|
c0fbae |
/* items */
|
|
|
7d801c |
uint32_t * hint;
|
|
|
58ced9 |
m->m_idata[i].ih_count = 0;
|
|
|
7d801c |
|
|
|
58ced9 |
if (m->m_idata[i].ih_import_lookup_tbl_rva) {
|
|
|
58ced9 |
pitem = m->m_idata[i].ih_aitems;
|
|
|
f845bd |
hint = (uint32_t *)pitem->ii_hint_name_tbl_rva;
|
|
|
7d801c |
|
|
|
f845bd |
for (; *hint; hint=(uint32_t *)((++pitem)->ii_hint_name_tbl_rva))
|
|
|
58ced9 |
m->m_idata[i].ih_count++;
|
|
|
c0fbae |
|
|
|
58ced9 |
if (!(m->m_idata[i].ih_items = calloc(m->m_idata[i].ih_count,sizeof(*(m->m_idata[i].ih_items)))))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_SYSTEM_ERROR(dctx));
|
|
|
82a0a1 |
}
|
|
|
c0fbae |
|
|
|
58ced9 |
for (j=0; j<m->m_idata[i].ih_count; j++) {
|
|
|
9770d4 |
if ((ret = pe_read_import_lookup(
|
|
|
58ced9 |
&(m->m_idata[i].ih_aitems[j]),
|
|
|
58ced9 |
&(m->m_idata[i].ih_items[j]),
|
|
|
58ced9 |
m->m_opt.oh_std.coh_magic)))
|
|
|
85fd0d |
return pe_free_image_meta_impl(
|
|
|
85fd0d |
m,PERK_CUSTOM_ERROR(dctx,ret));
|
|
|
c0fbae |
|
|
|
58ced9 |
switch (m->m_opt.oh_std.coh_magic) {
|
|
|
c0fbae |
case PE_MAGIC_PE32:
|
|
|
58ced9 |
m->m_idata[i].ih_items[j].ii_flags = m->m_idata[i].ih_items[j].u.ii_import_lookup_entry_32;
|
|
|
c0fbae |
break;
|
|
|
c0fbae |
|
|
|
c0fbae |
case PE_MAGIC_PE32_PLUS:
|
|
|
58ced9 |
m->m_idata[i].ih_items[j].ii_flags = (m->m_idata[i].ih_items[j].u.ii_import_lookup_entry_64 >> 32);
|
|
|
c0fbae |
break;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
58ced9 |
if (!m->m_idata[i].ih_items[j].ii_flags) {
|
|
|
34ee9e |
struct pe_raw_hint_name_entry * pentry =
|
|
|
25e3c0 |
(struct pe_raw_hint_name_entry *)(base + m->h_idata->sh_ptr_to_raw_data
|
|
|
25e3c0 |
+ m->m_idata[i].ih_items[j].u.ii_hint_name_tbl_rva - m->h_idata->sh_virtual_addr);
|
|
|
c0fbae |
|
|
|
58ced9 |
m->m_idata[i].ih_items[j].ii_name = (char *)pentry->ii_name;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
}
|
|
|
c0fbae |
}
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
20e8a3 |
/* .dsometa */
|
|
|
20e8a3 |
if ((i = pe_get_named_section_index(m,MDSO_META_SECTION)) >= 0) {
|
|
|
20e8a3 |
m->h_dsometa = &m->m_sectbl[i];
|
|
|
20e8a3 |
m->r_dsometa = base + m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
20e8a3 |
|
|
|
20e8a3 |
m->m_stats.t_ndsolibs = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS)
|
|
|
20e8a3 |
? m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m64)
|
|
|
20e8a3 |
: m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m32);
|
|
|
20e8a3 |
}
|
|
|
20e8a3 |
|
|
|
20e8a3 |
/* .dsosyms */
|
|
|
20e8a3 |
if ((i = pe_get_named_section_index(m,MDSO_SYMS_SECTION)) >= 0) {
|
|
|
20e8a3 |
m->h_dsosyms = &m->m_sectbl[i];
|
|
|
20e8a3 |
m->r_dsosyms = base + m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
20e8a3 |
|
|
|
20e8a3 |
m->m_stats.t_ndsosyms = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS)
|
|
|
20e8a3 |
? m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m64)
|
|
|
20e8a3 |
: m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m32);
|
|
|
20e8a3 |
}
|
|
|
20e8a3 |
|
|
|
20e8a3 |
/* .dsostrs */
|
|
|
20e8a3 |
if ((i = pe_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0) {
|
|
|
20e8a3 |
m->h_dsostrs = &m->m_sectbl[i];
|
|
|
20e8a3 |
m->r_dsostrs = base + m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
20e8a3 |
}
|
|
|
20e8a3 |
|
|
|
20e8a3 |
/* .dsodata */
|
|
|
20e8a3 |
if ((i = pe_get_named_section_index(m,MDSO_DATA_SECTION)) >= 0) {
|
|
|
20e8a3 |
m->h_dsodata = &m->m_sectbl[i];
|
|
|
20e8a3 |
m->r_dsodata = base + m->m_sectbl[i].sh_ptr_to_raw_data;
|
|
|
20e8a3 |
}
|
|
|
20e8a3 |
|
|
|
180890 |
/* image */
|
|
|
180890 |
m->r_image.map_addr = image->map_addr;
|
|
|
180890 |
m->r_image.map_size = image->map_size;
|
|
|
180890 |
|
|
|
180890 |
/* info */
|
|
|
180890 |
pe_detect_image_abi(m);
|
|
|
aec459 |
pe_detect_image_subtype(m);
|
|
|
c13a6b |
pe_detect_image_framework(m);
|
|
|
180890 |
|
|
|
20e8a3 |
/* mdso abi */
|
|
|
20e8a3 |
if (m->h_dsometa || m->h_dsosyms)
|
|
|
180890 |
if (m->m_abi == PE_ABI_UNSUPPORTED)
|
|
|
20e8a3 |
return pe_free_image_meta_impl(
|
|
|
20e8a3 |
m,PERK_CUSTOM_ERROR(
|
|
|
20e8a3 |
dctx,PERK_ERR_UNSUPPORTED_ABI));
|
|
|
20e8a3 |
|
|
|
c0fbae |
|
|
|
c0fbae |
/* all done */
|
|
|
c0fbae |
*meta = m;
|
|
|
c0fbae |
return 0;
|
|
|
c0fbae |
}
|