|
|
e2e2c2 |
/***************************************************************/
|
|
|
e2e2c2 |
/* perk: PE Resource Kit */
|
|
|
425fb8 |
/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */
|
|
|
e2e2c2 |
/* Released under GPLv2 and GPLv3; see COPYING.PERK. */
|
|
|
e2e2c2 |
/***************************************************************/
|
|
|
e2e2c2 |
|
|
|
c0fbae |
#include <string.h>
|
|
|
c0fbae |
|
|
|
c0fbae |
#include <perk/perk.h>
|
|
|
d6e02b |
#include <perk/perk_consts.h>
|
|
|
d6e02b |
#include <perk/perk_structs.h>
|
|
|
2d6c77 |
#include "perk_endian_impl.h"
|
|
|
413f56 |
#include "perk_reader_impl.h"
|
|
|
c0fbae |
|
|
|
8cb34f |
static int pe_read_optional_header_structs(const union pe_raw_opt_hdr * p, struct pe_meta_opt_hdr * m)
|
|
|
2d6c77 |
{
|
|
|
659299 |
unsigned int i;
|
|
|
659299 |
struct pe_block * pdir;
|
|
|
659299 |
const unsigned char * mark;
|
|
|
4348f3 |
const unsigned char * etbl;
|
|
|
659299 |
|
|
|
8cb34f |
struct pe_raw_opt_hdr_std * astd;
|
|
|
8cb34f |
struct pe_raw_opt_hdr_vers * avers;
|
|
|
8cb34f |
struct pe_raw_opt_hdr_align * aalign;
|
|
|
8cb34f |
struct pe_raw_opt_hdr_img * aimg;
|
|
|
8cb34f |
struct pe_raw_opt_hdr_ldr * aldr;
|
|
|
b5f7f5 |
|
|
|
c6ac1a |
m->oh_std.coh_magic = pe_read_short(p->opt_hdr_32.coh_magic);
|
|
|
2d6c77 |
|
|
|
c6ac1a |
switch (m->oh_std.coh_magic) {
|
|
|
c0fbae |
case PE_MAGIC_PE32:
|
|
|
8cb34f |
astd = (struct pe_raw_opt_hdr_std *)p;
|
|
|
9b6975 |
avers = (struct pe_raw_opt_hdr_vers *)&p->opt_hdr_32.coh_major_os_ver;
|
|
|
9b6975 |
aalign = (struct pe_raw_opt_hdr_align *)&p->opt_hdr_32.coh_section_align;
|
|
|
9b6975 |
aimg = (struct pe_raw_opt_hdr_img *)&p->opt_hdr_32.coh_size_of_image;
|
|
|
9b6975 |
aldr = (struct pe_raw_opt_hdr_ldr *)&p->opt_hdr_32.coh_loader_flags;
|
|
|
4348f3 |
etbl = p->opt_hdr_32.coh_export_tbl;
|
|
|
c0fbae |
break;
|
|
|
c0fbae |
|
|
|
c0fbae |
case PE_MAGIC_PE32_PLUS:
|
|
|
8cb34f |
astd = (struct pe_raw_opt_hdr_std *)p;
|
|
|
9b6975 |
avers = (struct pe_raw_opt_hdr_vers *)&p->opt_hdr_64.coh_major_os_ver;
|
|
|
9b6975 |
aalign = (struct pe_raw_opt_hdr_align *)&p->opt_hdr_64.coh_section_align;
|
|
|
9b6975 |
aimg = (struct pe_raw_opt_hdr_img *)&p->opt_hdr_64.coh_size_of_image;
|
|
|
9b6975 |
aldr = (struct pe_raw_opt_hdr_ldr *)&p->opt_hdr_64.coh_loader_flags;
|
|
|
4348f3 |
etbl = p->opt_hdr_64.coh_export_tbl;
|
|
|
c0fbae |
break;
|
|
|
c0fbae |
|
|
|
c0fbae |
default:
|
|
|
ff121d |
return PERK_ERR_BAD_IMAGE_TYPE;
|
|
|
c0fbae |
}
|
|
|
c0fbae |
|
|
|
c0fbae |
/* std */
|
|
|
c6ac1a |
m->oh_std.coh_major_linker_ver = astd->coh_major_linker_ver[0];
|
|
|
c6ac1a |
m->oh_std.coh_minor_linker_ver = astd->coh_minor_linker_ver[0];
|
|
|
c0fbae |
|
|
|
c6ac1a |
m->oh_std.coh_size_of_code = pe_read_long(astd->coh_size_of_code);
|
|
|
c6ac1a |
m->oh_std.coh_size_of_inited_data = pe_read_long(astd->coh_size_of_inited_data);
|
|
|
c6ac1a |
m->oh_std.coh_size_of_uninited_data = pe_read_long(astd->coh_size_of_uninited_data);
|
|
|
c6ac1a |
m->oh_std.coh_entry_point = pe_read_long(astd->coh_entry_point);
|
|
|
c6ac1a |
m->oh_std.coh_base_of_code = pe_read_long(astd->coh_base_of_code);
|
|
|
c0fbae |
|
|
|
c0fbae |
/* vers */
|
|
|
c6ac1a |
m->oh_vers.coh_major_os_ver = pe_read_short(avers->coh_major_os_ver);
|
|
|
c6ac1a |
m->oh_vers.coh_minor_os_ver = pe_read_short(avers->coh_minor_os_ver);
|
|
|
c6ac1a |
m->oh_vers.coh_major_image_ver = pe_read_short(avers->coh_major_image_ver);
|
|
|
c6ac1a |
m->oh_vers.coh_minor_image_ver = pe_read_short(avers->coh_minor_image_ver);
|
|
|
c6ac1a |
m->oh_vers.coh_major_subsys_ver = pe_read_short(avers->coh_major_subsys_ver);
|
|
|
c6ac1a |
m->oh_vers.coh_minor_subsys_ver = pe_read_short(avers->coh_minor_subsys_ver);
|
|
|
c0fbae |
|
|
|
c6ac1a |
m->oh_vers.coh_win32_ver = pe_read_long(avers->coh_win32_ver);
|
|
|
c0fbae |
|
|
|
c0fbae |
/* align */
|
|
|
c6ac1a |
m->oh_align.coh_section_align = pe_read_long(aalign->coh_section_align);
|
|
|
c6ac1a |
m->oh_align.coh_file_align = pe_read_long(aalign->coh_file_align);
|
|
|
c0fbae |
|
|
|
c0fbae |
/* img */
|
|
|
c6ac1a |
m->oh_img.coh_size_of_image = pe_read_long(aimg->coh_size_of_image);
|
|
|
c6ac1a |
m->oh_img.coh_size_of_headers = pe_read_long(aimg->coh_size_of_headers);
|
|
|
c6ac1a |
m->oh_img.coh_checksum = pe_read_long(aimg->coh_checksum);
|
|
|
c0fbae |
|
|
|
c6ac1a |
m->oh_img.coh_subsystem = pe_read_short(aimg->coh_subsystem);
|
|
|
c6ac1a |
m->oh_img.coh_dll_characteristics = pe_read_short(aimg->coh_dll_characteristics);
|
|
|
c0fbae |
|
|
|
c0fbae |
/* ldr */
|
|
|
c6ac1a |
m->oh_ldr.coh_loader_flags = pe_read_long(aldr->coh_loader_flags);
|
|
|
c6ac1a |
m->oh_ldr.coh_rva_and_sizes = pe_read_long(aldr->coh_rva_and_sizes);
|
|
|
c0fbae |
|
|
|
659299 |
/* dirs */
|
|
|
c6ac1a |
if (m->oh_ldr.coh_rva_and_sizes > 0x10)
|
|
|
659299 |
return PERK_ERR_BAD_IMAGE_TYPE;
|
|
|
659299 |
|
|
|
c6ac1a |
if (m->oh_ldr.coh_rva_and_sizes < 0x10)
|
|
|
c6ac1a |
memset(&m->oh_dirs,0,sizeof(m->oh_dirs));
|
|
|
659299 |
|
|
|
4348f3 |
mark = etbl;
|
|
|
c6ac1a |
pdir = &m->oh_dirs.coh_export_tbl;
|
|
|
659299 |
|
|
|
c6ac1a |
for (i=0; i<m->oh_ldr.coh_rva_and_sizes; i++) {
|
|
|
a402c4 |
pdir[i].dh_rva = pe_read_long(&mark[i*8]);
|
|
|
a402c4 |
pdir[i].dh_size = pe_read_long(&mark[i*8+4]);
|
|
|
659299 |
}
|
|
|
659299 |
|
|
|
2d6c77 |
return 0;
|
|
|
2d6c77 |
}
|
|
|
2d6c77 |
|
|
|
8cb34f |
int pe_read_optional_header(const union pe_raw_opt_hdr * p, struct pe_meta_opt_hdr * m)
|
|
|
2d6c77 |
{
|
|
|
2d6c77 |
int ret;
|
|
|
2d6c77 |
|
|
|
56cb69 |
if ((ret = pe_read_optional_header_structs(p,m)))
|
|
|
56cb69 |
return ret;
|
|
|
c0fbae |
|
|
|
c6ac1a |
switch (m->oh_std.coh_magic) {
|
|
|
c0fbae |
case PE_MAGIC_PE32:
|
|
|
c6ac1a |
m->oh_mem.coh_base_of_data = pe_read_long(p->opt_hdr_32.coh_base_of_data);
|
|
|
c6ac1a |
m->oh_mem.coh_image_base = pe_read_long(p->opt_hdr_32.coh_image_base);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_stack_reserve = pe_read_long(p->opt_hdr_32.coh_size_of_stack_reserve);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_stack_commit = pe_read_long(p->opt_hdr_32.coh_size_of_stack_commit);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_heap_reserve = pe_read_long(p->opt_hdr_32.coh_size_of_heap_reserve);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_heap_commit = pe_read_long(p->opt_hdr_32.coh_size_of_heap_commit);
|
|
|
c0fbae |
break;
|
|
|
c0fbae |
|
|
|
c0fbae |
case PE_MAGIC_PE32_PLUS:
|
|
|
c6ac1a |
m->oh_mem.coh_base_of_data = (uint64_t)-1;
|
|
|
c6ac1a |
m->oh_mem.coh_image_base = pe_read_quad(p->opt_hdr_64.coh_image_base);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_stack_reserve = pe_read_quad(p->opt_hdr_64.coh_size_of_stack_reserve);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_stack_commit = pe_read_quad(p->opt_hdr_64.coh_size_of_stack_commit);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_heap_reserve = pe_read_quad(p->opt_hdr_64.coh_size_of_heap_reserve);
|
|
|
c6ac1a |
m->oh_mem.coh_size_of_heap_commit = pe_read_quad(p->opt_hdr_64.coh_size_of_heap_commit);
|
|
|
c0fbae |
break;
|
|
|
c7189e |
}
|
|
|
c0fbae |
|
|
|
c0fbae |
return 0;
|
|
|
b5f7f5 |
}
|