diff options
author | midipix <writeonce@midipix.org> | 2015-05-02 10:05:51 -0400 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2016-11-10 23:35:18 -0500 |
commit | c0fbae7a40c662ae77f59f5f919cd6b88e38a85d (patch) | |
tree | ad6aaca1b75a1f4b5e9ac533220e382f49489c94 /src | |
parent | 99ace9f6a21b254216f60613e91191d902daeeb8 (diff) | |
download | perk-c0fbae7a40c662ae77f59f5f919cd6b88e38a85d.tar.bz2 perk-c0fbae7a40c662ae77f59f5f919cd6b88e38a85d.tar.xz |
initial commit.
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/perk_impl.h | 64 | ||||
-rw-r--r-- | src/main/pe_get_image_meta.c | 184 | ||||
-rw-r--r-- | src/main/pe_map_raw_image.c | 40 | ||||
-rw-r--r-- | src/main/perk.c | 116 | ||||
-rw-r--r-- | src/output/pe_output_export_symbols.c | 24 | ||||
-rw-r--r-- | src/reader/pe_read_coff_header.c | 37 | ||||
-rw-r--r-- | src/reader/pe_read_dos_header.c | 52 | ||||
-rw-r--r-- | src/reader/pe_read_export_header.c | 32 | ||||
-rw-r--r-- | src/reader/pe_read_import_header.c | 46 | ||||
-rw-r--r-- | src/reader/pe_read_optional_header.c | 139 | ||||
-rw-r--r-- | src/reader/pe_read_section_header.c | 37 |
11 files changed, 771 insertions, 0 deletions
diff --git a/src/internal/perk_impl.h b/src/internal/perk_impl.h new file mode 100644 index 0000000..497ddbe --- /dev/null +++ b/src/internal/perk_impl.h @@ -0,0 +1,64 @@ +#ifndef PERK_IMPL_H +#define PERK_IMPL_H + +#include <stdint.h> +#include <endian.h> + +/* internal structures */ +struct perk_ctx { + int argc; + char ** argv; + char ** envp; + const char * fname; + int status; + int flags; + int fd; + FILE * fout; + FILE * tmp; + struct pe_raw_image map; +}; + +#if (BYTE_ORDER == LITTLE_ENDIAN) + +static inline uint16_t pe_read_short(const unsigned char * raw) +{ + return *(uint16_t *)raw; +} + +static inline uint32_t pe_read_long(const unsigned char * raw) +{ + return *(uint32_t *)raw; +} + +static inline uint64_t pe_read_quad(const unsigned char * raw) +{ + return *(uint64_t *)raw; +} + +#else + +static inline uint16_t pe_read_short(unsigned char * raw) +{ + uint16_t x = *(uint16_t *)raw; + return x<<8 | x>>8; +} + +static inline uint32_t pe_swap_long(uint32_t x) +{ + return x<<24 | (x<<8) & 0xff0000 | (x>>8) & 0xff00 | x>>24; +} + +static inline uint32_t pe_read_long(unsigned char * raw) +{ + return pe_swap_long(*(uint32_t *)raw); +} + +static inline uint64_t pe_read_quad(unsigned char * raw) +{ + uint64_t x = *(uint64_t *)raw; + return ((uint64_t)pe_swap_long(x)<<32) | pe_swap_long(x>>32); +} + +#endif + +#endif diff --git a/src/main/pe_get_image_meta.c b/src/main/pe_get_image_meta.c new file mode 100644 index 0000000..454f233 --- /dev/null +++ b/src/main/pe_get_image_meta.c @@ -0,0 +1,184 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +static int pe_free_image_meta_impl (struct pe_image_meta * meta, int status) +{ + if (!meta) return 0; + + free(meta->sectbl); + free(meta); + + return status; +} + +int pe_free_image_meta (struct pe_image_meta * meta) +{ + return pe_free_image_meta_impl(meta,0); +} + +int pe_get_named_section_index (const struct pe_image_meta * m, const char * name) +{ + int i; for (i=0; i<m->coff.num_of_sections; i++) + if (!(strcmp(name,m->sectbl[i].name))) + return i; + + return -1; +} + +int pe_get_block_section_index (const struct pe_image_meta * m, const struct pe_block * block) +{ + int i; + uint32_t low,high; + + for (i=0; i<m->coff.num_of_sections; i++) { + low = m->sectbl[i].virtual_addr; + high = low + m->sectbl[i].virtual_size; + + if ((block->rva >= low) && (block->rva + block->size <= high)) + return i; + } + + return -1; +} + +int pe_get_image_meta (const struct pe_raw_image * image, struct pe_image_meta ** meta) +{ + int i,j,s,status; + struct pe_image_meta * m; + char * base = image->addr; + + if (!(m = calloc(1,sizeof(*m)))) + return errno; + + m->ados = (struct pe_image_dos_hdr *)base; + + if ((status = (pe_read_dos_header(m->ados,&m->dos)))) + return pe_free_image_meta_impl(m,status); + + m->acoff = (struct pe_coff_file_hdr *)(base + m->dos.dos_lfanew); + + if ((status = (pe_read_coff_header(m->acoff,&m->coff)))) + return pe_free_image_meta_impl(m,status); + + m->aopt = (union pe_opt_hdr *)((char *)m->acoff + sizeof(m->coff)); + + if ((status = (pe_read_optional_header(m->aopt,&m->opt)))) + return pe_free_image_meta_impl(m,status); + + m->asectbl = (struct pe_sec_hdr *)((char *)m->aopt + m->coff.size_of_opt_hdr); + + if (!(m->sectbl = calloc(m->coff.num_of_sections,sizeof(*(m->sectbl))))) + return pe_free_image_meta_impl(m,status); + + for (i=0; i<m->coff.num_of_sections; i++) + pe_read_section_header(&m->asectbl[i],&m->sectbl[i]); + + /* .edata */ + i = pe_get_named_section_index(m,".edata"); + s = pe_get_block_section_index(m,&m->opt.dirs.export_tbl); + + if ((i >= 0) && (i != s)) + return pe_free_image_meta_impl(m,PERK_MALFORMED_IMAGE); + + if (i >= 0 ) { + m->hedata = &m->sectbl[i]; + m->aedata = (struct pe_export_hdr *)(base + m->sectbl[i].ptr_to_raw_data); + } else if (s >= 0) { + m->hedata = &m->sectbl[s]; + m->aedata = (struct pe_export_hdr *)(base + m->sectbl[s].ptr_to_raw_data + + m->opt.dirs.export_tbl.rva - m->sectbl[s].virtual_addr); + } + + if (m->aedata) + pe_read_export_header(m->aedata,&m->edata); + + /* .idata */ + struct pe_import_hdr * pidata; + struct pe_import_lookup_item * pitem; + + i = pe_get_named_section_index(m,".idata"); + s = pe_get_block_section_index(m,&m->opt.dirs.import_tbl); + + if ((i >= 0) && (i != s)) + return pe_free_image_meta_impl(m,PERK_MALFORMED_IMAGE); + + if (i >= 0 ) { + m->hidata = &m->sectbl[i]; + m->aidata = (struct pe_import_hdr *)(base + m->sectbl[i].ptr_to_raw_data); + } else if (s >= 0) { + m->hidata = &m->sectbl[s]; + m->aidata = (struct pe_import_hdr *)(base + m->sectbl[s].ptr_to_raw_data + + m->opt.dirs.import_tbl.rva - m->sectbl[s].virtual_addr); + } + + if (m->aidata) { + /* num of implibs */ + for (pidata=m->aidata; pidata->name_rva[0]; pidata++,m->summary.num_of_implibs++); + + /* import headers */ + if (!(m->idata = calloc(m->summary.num_of_implibs,sizeof(*(m->idata))))) + return pe_free_image_meta_impl(m,status); + + for (i=0; i<m->summary.num_of_implibs; i++) { + pe_read_import_header(&m->aidata[i],&m->idata[i]); + + m->idata[i].name = base + m->hidata->ptr_to_raw_data + + m->idata[i].name_rva - m->hidata->virtual_addr; + + m->idata[i].aitems = (struct pe_import_lookup_item *)(base + m->hidata->ptr_to_raw_data + + m->idata[i].import_lookup_tbl_rva - m->hidata->virtual_addr); + + printf("%s\n",m->idata[i].name); + + /* items */ + m->idata[i].count = 0; + for (pitem=m->idata[i].aitems; *(uint32_t *)pitem->u.hint_name_tbl_rva; pitem++) + m->idata[i].count++; + + if (!(m->idata[i].items = calloc(m->idata[i].count,sizeof(*(m->idata[i].items))))) + return pe_free_image_meta_impl(m,status); + + for (j=0; j<m->idata[i].count; j++) { + if ((status = pe_read_import_lookup_item( + &(m->idata[i].aitems[j]), + &(m->idata[i].items[j]), + m->opt.std.magic))) + return pe_free_image_meta_impl(m,status); + + switch (m->opt.std.magic) { + case PE_MAGIC_PE32: + m->idata[i].items[j].flags = m->idata[i].items[j].u.import_lookup_entry_32; + break; + + case PE_MAGIC_PE32_PLUS: + m->idata[i].items[j].flags = (m->idata[i].items[j].u.import_lookup_entry_64 >> 32); + break; + } + + struct pe_hint_name_entry * pentry = (struct pe_hint_name_entry *)(base + m->hidata->ptr_to_raw_data + + m->idata[i].items[j].u.hint_name_tbl_rva - m->hidata->virtual_addr); + + if (m->idata[i].items[j].flags) + m->idata[i].items[j].hint = pe_read_short(pentry->hint); + else { + m->idata[i].items[j].name = (char *)pentry->name; + printf("%s\n",m->idata[i].items[j].name); + } + } + } + } + + /* image */ + m->image.addr = image->addr; + m->image.size = image->size; + + /* all done */ + *meta = m; + return 0; +} diff --git a/src/main/pe_map_raw_image.c b/src/main/pe_map_raw_image.c new file mode 100644 index 0000000..8ae95d9 --- /dev/null +++ b/src/main/pe_map_raw_image.c @@ -0,0 +1,40 @@ +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <limits.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <perk/perk.h> + +int pe_map_raw_image (int fd, const char * fname, struct pe_raw_image * map) +{ + struct stat stat; + int nfd, ret; + + if ((nfd = !fd)) + fd = open(fname,O_RDONLY | O_CLOEXEC); + + if ((fd < 0) || (fstat(fd,&stat) < 0)) + return errno; + + map->size = stat.st_size; + map->addr = (char *)mmap(0,map->size,PROT_READ,MAP_PRIVATE,fd,0); + + if (map->addr == MAP_FAILED) { + map->addr = 0; + ret = PERK_MAP_ERROR; + } else + ret = 0; + + if (nfd) close(fd); + + return ret; +} + +int pe_unmap_raw_image (struct pe_raw_image * map) +{ + return munmap(map->addr, map->size); +}; diff --git a/src/main/perk.c b/src/main/perk.c new file mode 100644 index 0000000..5fe8f17 --- /dev/null +++ b/src/main/perk.c @@ -0,0 +1,116 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <unistd.h> +#include <fcntl.h> +#include <limits.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +static int perk_parse_opts(struct perk_ctx * ctx) +{ + int i; + char * ch; + const char ** popt; + + for (i=1; i<ctx->argc; i++) { + ch = ctx->argv[i]; + + if (*ch == '-') { + switch (*++ch) { + case 'i': + popt = &ctx->fname; + break; + case 'h': + ctx->flags = PERK_HELP; + return 0; + default: + ctx->status = PERK_BAD_OPT; + return ctx->status; + } + + while ((*++ch == '\t') || (*ch == ' ')); + + if (!*ch) { + if (++i < ctx->argc) + *popt = ctx->argv[i]; + else + ctx->status = PERK_BAD_OPT_VAL; + } else + *popt = ch; + } else if (!ctx->fname) + ctx->fname = ch; + else + ctx->status = PERK_BAD_OPT; + + } + + return ctx->status; +} + + +static int perk_map_input(struct perk_ctx * ctx) +{ + ctx->fd = open(ctx->fname,O_RDONLY | O_CLOEXEC); + + if (ctx->fd < 0) { + ctx->status = PERK_IO_ERROR; + return ctx->status; + } + + ctx->status = pe_map_raw_image(ctx->fd,0,&ctx->map); + + return ctx->status; +} + + +static int perk_exit(struct perk_ctx * ctx) +{ + if (ctx->map.addr) + pe_unmap_raw_image(&ctx->map); + + return ctx->status; +} + + +static int perk_run(struct perk_ctx * ctx) +{ + struct pe_image_meta * meta; + + if (perk_map_input(ctx)) + return perk_exit(ctx); + + if ((ctx->status = pe_get_image_meta(&ctx->map,&meta))) + return perk_exit(ctx); + + /* pre-alpha default output */ + pe_output_export_symbols( + meta, + PERK_OUTPUT_FORMAT_LIST | PERK_OUTPUT_FIELD_NAME, + stdout); + + ctx->status = pe_free_image_meta(meta); + + return perk_exit(ctx); +} + +static int perk_main(int argc, char * argv[], char * envp[]) +{ + struct perk_ctx ctx = {argc,argv,envp}; + + if (perk_parse_opts(&ctx)) + return ctx.status; + else + return perk_run(&ctx); +} + +#ifdef PERK_APP +extern __typeof(perk_main) main __attribute__((alias("perk_main"))); +#endif diff --git a/src/output/pe_output_export_symbols.c b/src/output/pe_output_export_symbols.c new file mode 100644 index 0000000..192bca3 --- /dev/null +++ b/src/output/pe_output_export_symbols.c @@ -0,0 +1,24 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <perk/perk.h> + +int pe_output_export_symbols (const struct pe_image_meta * m, uint32_t flags, FILE * f) +{ + uint32_t offset; + uint32_t * symrva; + int i; + + if (!m->hedata) return 0; + + offset = m->hedata->virtual_addr - m->hedata->ptr_to_raw_data; + symrva = (uint32_t *)(m->image.addr + (m->edata.name_ptr_rva - offset)); + + for (i=0; i<m->edata.num_of_name_ptrs; i++) + fprintf(f,"%s\n",(char *)(m->image.addr + symrva[i] - offset)); + + return 0; +} diff --git a/src/reader/pe_read_coff_header.c b/src/reader/pe_read_coff_header.c new file mode 100644 index 0000000..e7bdf8a --- /dev/null +++ b/src/reader/pe_read_coff_header.c @@ -0,0 +1,37 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_coff_header(const struct pe_coff_file_hdr * p, struct pe_meta_coff_file_hdr * m) +{ + if ((p->signature[0] != 'P') || (p->signature[1] != 'E') + || *(uint16_t *)&p->signature[2]) + return PERK_BAD_COFF_HEADER; + + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(m,p,sizeof(*p)); + + #else + + m->signature[0] = p->signature[0]; + m->signature[1] = p->signature[1]; + m->signature[2] = p->signature[2]; + m->signature[3] = p->signature[3]; + + m->machine = pe_read_short(p->machine); + m->num_of_sections = pe_read_short(p->num_of_sections); + + m->time_date_stamp = pe_read_long(p->time_date_stamp); + m->ptr_to_sym_tbl = pe_read_long(p->ptr_to_sym_tbl); + m->num_of_syms = pe_read_long(p->num_of_syms); + + m->size_of_opt_hdr = pe_read_short(p->size_of_opt_hdr); + m->characteristics = pe_read_short(p->characteristics); + + #endif + + return 0; +}; diff --git a/src/reader/pe_read_dos_header.c b/src/reader/pe_read_dos_header.c new file mode 100644 index 0000000..75b7d31 --- /dev/null +++ b/src/reader/pe_read_dos_header.c @@ -0,0 +1,52 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_dos_header(const struct pe_image_dos_hdr * p, struct pe_meta_image_dos_hdr * m) +{ + int i; + + if ((p->dos_magic[0] != 'M') || (p->dos_magic[1] != 'Z')) + return PERK_BAD_DOS_HEADER; + + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(m,p,sizeof(*p)); + + #else + + m->dos_magic[0] = p->dos_magic[0]; + m->dos_magic[1] = p->dos_magic[1]; + + m->dos_cblp = pe_read_short(p->dos_cblp); + m->dos_cp = pe_read_short(p->dos_cp); + m->dos_crlc = pe_read_short(p->dos_crlc); + m->dos_cparhdr = pe_read_short(p->dos_cparhdr); + m->dos_minalloc = pe_read_short(p->dos_minalloc); + m->dos_maxalloc = pe_read_short(p->dos_maxalloc); + m->dos_ss = pe_read_short(p->dos_ss); + m->dos_sp = pe_read_short(p->dos_sp); + m->dos_csum = pe_read_short(p->dos_csum); + m->dos_ip = pe_read_short(p->dos_ip); + m->dos_cs = pe_read_short(p->dos_cs); + m->dos_lfarlc = pe_read_short(p->dos_lfarlc); + m->dos_ovno = pe_read_short(p->dos_ovno); + + + for (i=0; i<4; i++) + m->dos_res[i] = pe_read_short(&p->dos_res[2*i]); + + m->dos_oemid = pe_read_short(p->dos_oemid); + m->dos_oeminfo = pe_read_short(p->dos_oeminfo); + + for (i=0; i<10; i++) + m->dos_res2[i] = pe_read_short(&p->dos_res2[2*i]); + + m->dos_lfanew = pe_read_long(p->dos_lfanew); + + #endif + + return 0; +}; diff --git a/src/reader/pe_read_export_header.c b/src/reader/pe_read_export_header.c new file mode 100644 index 0000000..6a959c9 --- /dev/null +++ b/src/reader/pe_read_export_header.c @@ -0,0 +1,32 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_export_header(const struct pe_export_hdr * p, struct pe_meta_export_hdr * m) +{ + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(m,p,sizeof(*p)); + + #else + + m->export_flags = pe_read_long(p->export_flags); + m->time_date_stamp = pe_read_long(p->time_date_stamp); + + m->major_ver = pe_read_short(p->major_ver); + m->minor_ver = pe_read_short(p->minor_ver); + + m->name_rva = pe_read_long(p->name_rva); + m->ordinal_base = pe_read_long(p->ordinal_base); + m->addr_tbl_entries = pe_read_long(p->addr_tbl_entries); + m->num_of_name_ptrs = pe_read_long(p->num_of_name_ptrs); + m->export_addr_tbl_rva = pe_read_long(p->export_addr_tbl_rva); + m->name_ptr_rva = pe_read_long(p->name_ptr_rva); + m->ordinal_tbl_rva = pe_read_long(p->ordinal_tbl_rva); + + #endif + + return 0; +}; diff --git a/src/reader/pe_read_import_header.c b/src/reader/pe_read_import_header.c new file mode 100644 index 0000000..7d71143 --- /dev/null +++ b/src/reader/pe_read_import_header.c @@ -0,0 +1,46 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_import_header(const struct pe_import_hdr * p, struct pe_meta_import_hdr * m) +{ + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(m,p,sizeof(*p)); + + #else + + m->import_lookup_tbl_rva = pe_read_long(p->import_lookup_tbl_rva); + m->time_date_stamp = pe_read_long(p->time_date_stamp); + m->forwarder_chain = pe_read_long(p>forwarder_chain); + m->name_rva = pe_read_long(p->name_rva); + m->import_addr_tbl_rva = pe_read_long(p>import_addr_tbl_rva); + + #endif + + m->name = 0; + m->aitems = 0; + + return 0; +}; + +int pe_read_import_lookup_item( + const struct pe_import_lookup_item * p, + struct pe_meta_import_lookup_item * m, + uint32_t magic) +{ + switch (magic) { + case PE_MAGIC_PE32: + m->u.import_lookup_entry_64 = pe_read_long(p->u.import_lookup_entry_32); + return 0; + + case PE_MAGIC_PE32_PLUS: + m->u.import_lookup_entry_64 = pe_read_quad(p->u.import_lookup_entry_64); + return 0; + + default: + return PERK_BAD_IMAGE_TYPE; + } +}; diff --git a/src/reader/pe_read_optional_header.c b/src/reader/pe_read_optional_header.c new file mode 100644 index 0000000..701c6a9 --- /dev/null +++ b/src/reader/pe_read_optional_header.c @@ -0,0 +1,139 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_optional_header(const union pe_opt_hdr * p, struct pe_meta_opt_hdr * m) +{ + struct pe_opt_hdr_std * astd; + struct pe_opt_hdr_vers * avers; + struct pe_opt_hdr_align * aalign; + struct pe_opt_hdr_img * aimg; + struct pe_opt_hdr_ldr * aldr; + struct pe_opt_hdr_dirs * adirs; + size_t sdirs; + + m->std.magic = pe_read_short(p->opt_hdr_32.magic); + memset(&m->dirs,0,sizeof(m->dirs)); + + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(&m->std,p,sizeof(struct pe_meta_opt_hdr_std)); + + switch (m->std.magic) { + case PE_MAGIC_PE32: + memcpy(&m->vers,&p->opt_hdr_32.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers)); + memcpy(&m->align,&p->opt_hdr_32.section_align,sizeof(struct pe_meta_opt_hdr_align)); + memcpy(&m->img,&p->opt_hdr_32.size_of_image,sizeof(struct pe_meta_opt_hdr_img)); + memcpy(&m->ldr,&p->opt_hdr_32.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr)); + + if (m->ldr.rva_and_sizes > 0x10) + return PERK_BAD_IMAGE_TYPE; + else + memcpy(&m->dirs,&p->opt_hdr_32.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs)); + + break; + + case PE_MAGIC_PE32_PLUS: + memcpy(&m->vers,&p->opt_hdr_64.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers)); + memcpy(&m->align,&p->opt_hdr_64.section_align,sizeof(struct pe_meta_opt_hdr_align)); + memcpy(&m->img,&p->opt_hdr_64.size_of_image,sizeof(struct pe_meta_opt_hdr_img)); + memcpy(&m->ldr,&p->opt_hdr_64.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr)); + + if (m->ldr.rva_and_sizes > 0x10) + return PERK_BAD_IMAGE_TYPE; + else + memcpy(&m->dirs,&p->opt_hdr_64.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs)); + + break; + + default: + return PERK_BAD_IMAGE_TYPE; + }; + + #else + + astd = (struct pe_opt_hdr_std *)p; + + switch (m->std.magic) { + case PE_MAGIC_PE32: + avers = (struct pe_opt_hdr_std *)&p->opt_hdr_32.major_os_ver; + aalign = (struct pe_opt_hdr_std *)&p->opt_hdr_32.section_align; + aimg = (struct pe_opt_hdr_img *)&p->opt_hdr_32.size_of_image; + aldr = (struct pe_opt_hdr_ldr *)&p->opt_hdr_32.loader_flags; + adirs = (struct pe_opt_hdr_dirs *)&p->opt_hdr_32.export_tbl; + break; + + case PE_MAGIC_PE32_PLUS: + avers = (struct pe_opt_hdr_std *)&p->opt_hdr_64.major_os_ver; + aalign = (struct pe_opt_hdr_std *)&p->opt_hdr_64.section_align; + aimg = (struct pe_opt_hdr_img *)&p->opt_hdr_64.size_of_image; + aldr = (struct pe_opt_hdr_ldr *)&p->opt_hdr_64.loader_flags; + adirs = (struct pe_opt_hdr_dirs *)&p->opt_hdr_64.export_tbl; + break; + + default: + return PERK_BAD_IMAGE_TYPE; + } + + /* std */ + m->std.major_linker_ver = astd->major_linker_ver; + m->std.minor_linker_ver = astd->minor_linker_ver; + + m->std.size_of_code = pe_read_long(astd->size_of_code); + m->std.size_of_initialized_data = pe_read_long(astd->size_of_initialized_data); + m->std.size_of_uninitialized_data = pe_read_long(astd->size_of_uninitialized_data); + m->std.entry_point = pe_read_long(astd->entry_point); + m->std.base_of_code = pe_read_long(astd->base_of_code); + + /* vers */ + m->vers.major_os_ver = pe_read_short(avers->major_os_ver); + m->vers.minor_os_ver = pe_read_short(avers->minor_os_ver); + m->vers.major_image_ver = pe_read_short(avers->major_image_ver); + m->vers.minor_image_ver = pe_read_short(avers->minor_image_ver); + m->vers.major_subsys_ver = pe_read_short(avers->major_subsys_ver); + m->vers.minor_subsys_ver = pe_read_short(avers->minor_subsys_ver); + + m->vers.win32_ver = pe_read_long(avers->win32_ver); + + /* align */ + m->align.section_align = pe_read_long(aalign->section_align); + m->align.file_align = pe_read_long(aalign->file_align); + + /* img */ + m->img.size_of_image = pe_read_long(aimg->size_of_image); + m->img.size_of_headers = pe_read_long(aimg->size_of_headers); + m->img.checksum = pe_read_long(aimg->checksum); + + m->img.subsystem = pe_read_short(aimg->subsystem); + m->img.dll_characteristics = pe_read_short(aimg->dll_characteristics); + + /* ldr */ + m->ldr.loader_flags = pe_read_long(aldr->loader_flags); + m->ldr.rva_and_sizes = pe_read_long(aldr->rva_and_sizes); + + #endif + + switch (m->std.magic) { + case PE_MAGIC_PE32: + m->mem.base_of_data = pe_read_long(p->opt_hdr_32.base_of_data); + m->mem.image_base = pe_read_long(p->opt_hdr_32.image_base); + m->mem.size_of_stack_reserve = pe_read_long(p->opt_hdr_32.size_of_stack_reserve); + m->mem.size_of_stack_commit = pe_read_long(p->opt_hdr_32.size_of_stack_commit); + m->mem.size_of_heap_reserve = pe_read_long(p->opt_hdr_32.size_of_heap_reserve); + m->mem.size_of_heap_commit = pe_read_long(p->opt_hdr_32.size_of_heap_commit); + break; + + case PE_MAGIC_PE32_PLUS: + m->mem.base_of_data = (uint64_t)-1; + m->mem.image_base = pe_read_quad(p->opt_hdr_64.image_base); + m->mem.size_of_stack_reserve = pe_read_quad(p->opt_hdr_64.size_of_stack_reserve); + m->mem.size_of_stack_commit = pe_read_quad(p->opt_hdr_64.size_of_stack_commit); + m->mem.size_of_heap_reserve = pe_read_quad(p->opt_hdr_64.size_of_heap_reserve); + m->mem.size_of_heap_commit = pe_read_quad(p->opt_hdr_64.size_of_heap_commit); + break; + }; + + return 0; +}; diff --git a/src/reader/pe_read_section_header.c b/src/reader/pe_read_section_header.c new file mode 100644 index 0000000..1a37f63 --- /dev/null +++ b/src/reader/pe_read_section_header.c @@ -0,0 +1,37 @@ +#include <endian.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_impl.h" + +int pe_read_section_header(const struct pe_sec_hdr * p, struct pe_meta_sec_hdr * m) +{ + /* name: meta struct conveniently contains null termination */ + memset(m,0,sizeof(m->name)); + memcpy(m,p,sizeof(p->name)); + + /* todo: long name support */ + m->long_name = 0; + + #if (BYTE_ORDER == LITTLE_ENDIAN) + + memcpy(&m->virtual_size,&p->virtual_size,sizeof(*p)-sizeof(p->name)); + + #else + + m->virtual_size = pe_read_long(p->virtual_size); + m->virtual_addr = pe_read_long(p->virtual_addr); + m->size_of_raw_data = pe_read_long(p->size_of_raw_data); + m->ptr_to_raw_data = pe_read_long(p->ptr_to_raw_data); + m->ptr_to_relocs = pe_read_long(p->ptr_to_relocs); + m->ptr_to_line_nums = pe_read_long(p->ptr_to_linu_nums); + + m->num_of_relocs = pe_read_short(p->num_of_relocs); + m->num_of_line_nums = pe_read_short(p->num_of_line_nums); + + m->characteristics = pe_read_long(p->characteristics); + + #endif + + return 0; +}; |