Blame src/reader/pe_read_optional_header.c

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
}