Blame src/reader/pe_read_optional_header.c

e2e2c2
/***************************************************************/
e2e2c2
/*  perk: PE Resource Kit                                      */
e2e2c2
/*  Copyright (C) 2015--2016  Z. Gilboa                        */
e2e2c2
/*  Released under GPLv2 and GPLv3; see COPYING.PERK.          */
e2e2c2
/***************************************************************/
e2e2c2
c0fbae
#include <string.h>
c0fbae
c0fbae
#include <perk/perk.h>
2d6c77
#include "perk_endian_impl.h"
413f56
#include "perk_reader_impl.h"
c0fbae
2d6c77
static int pe_read_optional_header_little_endian(const union pe_opt_hdr * p, struct pe_meta_opt_hdr * m)
c0fbae
{
c0fbae
	m->std.magic = pe_read_short(p->opt_hdr_32.magic);
c0fbae
	memset(&m->dirs,0,sizeof(m->dirs));
c0fbae
c0fbae
	memcpy(&m->std,p,sizeof(struct pe_meta_opt_hdr_std));
c0fbae
c0fbae
	switch (m->std.magic) {
c0fbae
		case PE_MAGIC_PE32:
c0fbae
			memcpy(&m->vers,&p->opt_hdr_32.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers));
c0fbae
			memcpy(&m->align,&p->opt_hdr_32.section_align,sizeof(struct pe_meta_opt_hdr_align));
c0fbae
			memcpy(&m->img,&p->opt_hdr_32.size_of_image,sizeof(struct pe_meta_opt_hdr_img));
c0fbae
			memcpy(&m->ldr,&p->opt_hdr_32.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr));
c0fbae
c0fbae
			if (m->ldr.rva_and_sizes > 0x10)
c0fbae
				return PERK_BAD_IMAGE_TYPE;
c0fbae
			else
c0fbae
				memcpy(&m->dirs,&p->opt_hdr_32.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs));
c0fbae
c0fbae
			break;
c0fbae
c0fbae
		case PE_MAGIC_PE32_PLUS:
c0fbae
			memcpy(&m->vers,&p->opt_hdr_64.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers));
c0fbae
			memcpy(&m->align,&p->opt_hdr_64.section_align,sizeof(struct pe_meta_opt_hdr_align));
c0fbae
			memcpy(&m->img,&p->opt_hdr_64.size_of_image,sizeof(struct pe_meta_opt_hdr_img));
c0fbae
			memcpy(&m->ldr,&p->opt_hdr_64.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr));
c0fbae
c0fbae
			if (m->ldr.rva_and_sizes > 0x10)
c0fbae
				return PERK_BAD_IMAGE_TYPE;
c0fbae
			else
c0fbae
				memcpy(&m->dirs,&p->opt_hdr_64.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs));
c0fbae
c0fbae
			break;
c0fbae
c0fbae
		default:
c0fbae
			return PERK_BAD_IMAGE_TYPE;
c7189e
	}
c0fbae
2d6c77
	return 0;
2d6c77
}
c0fbae
2d6c77
static int pe_read_optional_header_big_endian(const union pe_opt_hdr * p, struct pe_meta_opt_hdr * m)
2d6c77
{
b5f7f5
	struct pe_opt_hdr_std *		astd;
b5f7f5
	struct pe_opt_hdr_vers *	avers;
b5f7f5
	struct pe_opt_hdr_align *	aalign;
b5f7f5
	struct pe_opt_hdr_img *		aimg;
b5f7f5
	struct pe_opt_hdr_ldr *		aldr;
b5f7f5
2d6c77
	m->std.magic = pe_read_short(p->opt_hdr_32.magic);
2d6c77
	memset(&m->dirs,0,sizeof(m->dirs));
2d6c77
c0fbae
	astd = (struct pe_opt_hdr_std *)p;
c0fbae
c0fbae
	switch (m->std.magic) {
c0fbae
		case PE_MAGIC_PE32:
b5f7f5
			avers	= (struct pe_opt_hdr_vers *)&p->opt_hdr_32.major_os_ver;
b5f7f5
			aalign	= (struct pe_opt_hdr_align *)&p->opt_hdr_32.section_align;
c0fbae
			aimg	= (struct pe_opt_hdr_img *)&p->opt_hdr_32.size_of_image;
c0fbae
			aldr	= (struct pe_opt_hdr_ldr *)&p->opt_hdr_32.loader_flags;
c0fbae
			break;
c0fbae
c0fbae
		case PE_MAGIC_PE32_PLUS:
b5f7f5
			avers	= (struct pe_opt_hdr_vers *)&p->opt_hdr_64.major_os_ver;
b5f7f5
			aalign	= (struct pe_opt_hdr_align *)&p->opt_hdr_64.section_align;
c0fbae
			aimg	= (struct pe_opt_hdr_img *)&p->opt_hdr_64.size_of_image;
c0fbae
			aldr	= (struct pe_opt_hdr_ldr *)&p->opt_hdr_64.loader_flags;
c0fbae
			break;
c0fbae
c0fbae
		default:
c0fbae
			return PERK_BAD_IMAGE_TYPE;
c0fbae
	}
c0fbae
c0fbae
	/* std */
b5f7f5
	m->std.major_linker_ver			= astd->major_linker_ver[0];
b5f7f5
	m->std.minor_linker_ver			= astd->minor_linker_ver[0];
c0fbae
c0fbae
	m->std.size_of_code			= pe_read_long(astd->size_of_code);
c0fbae
	m->std.size_of_initialized_data		= pe_read_long(astd->size_of_initialized_data);
c0fbae
	m->std.size_of_uninitialized_data	= pe_read_long(astd->size_of_uninitialized_data);
c0fbae
	m->std.entry_point			= pe_read_long(astd->entry_point);
c0fbae
	m->std.base_of_code			= pe_read_long(astd->base_of_code);
c0fbae
c0fbae
	/* vers */
c0fbae
	m->vers.major_os_ver			= pe_read_short(avers->major_os_ver);
c0fbae
	m->vers.minor_os_ver			= pe_read_short(avers->minor_os_ver);
c0fbae
	m->vers.major_image_ver			= pe_read_short(avers->major_image_ver);
c0fbae
	m->vers.minor_image_ver			= pe_read_short(avers->minor_image_ver);
c0fbae
	m->vers.major_subsys_ver		= pe_read_short(avers->major_subsys_ver);
c0fbae
	m->vers.minor_subsys_ver		= pe_read_short(avers->minor_subsys_ver);
c0fbae
c0fbae
	m->vers.win32_ver			= pe_read_long(avers->win32_ver);
c0fbae
c0fbae
	/* align */
c0fbae
	m->align.section_align			= pe_read_long(aalign->section_align);
c0fbae
	m->align.file_align			= pe_read_long(aalign->file_align);
c0fbae
c0fbae
	/* img */
c0fbae
	m->img.size_of_image			= pe_read_long(aimg->size_of_image);
c0fbae
	m->img.size_of_headers			= pe_read_long(aimg->size_of_headers);
c0fbae
	m->img.checksum				= pe_read_long(aimg->checksum);
c0fbae
c0fbae
	m->img.subsystem			= pe_read_short(aimg->subsystem);
c0fbae
	m->img.dll_characteristics		= pe_read_short(aimg->dll_characteristics);
c0fbae
c0fbae
	/* ldr */
c0fbae
	m->ldr.loader_flags			= pe_read_long(aldr->loader_flags);
c0fbae
	m->ldr.rva_and_sizes			= pe_read_long(aldr->rva_and_sizes);
c0fbae
2d6c77
	return 0;
2d6c77
}
2d6c77
2d6c77
int pe_read_optional_header(const union pe_opt_hdr * p, struct pe_meta_opt_hdr * m)
2d6c77
{
2d6c77
	int ret;
2d6c77
2d6c77
	if (PERK_LITTLE_ENDIAN) {
2d6c77
		if ((ret = pe_read_optional_header_little_endian(p,m)))
2d6c77
			return ret;
2d6c77
	} else {
2d6c77
		if ((ret = pe_read_optional_header_big_endian(p,m)))
2d6c77
			return ret;
2d6c77
	}
c0fbae
c0fbae
	switch (m->std.magic) {
c0fbae
		case PE_MAGIC_PE32:
c0fbae
			m->mem.base_of_data		= pe_read_long(p->opt_hdr_32.base_of_data);
c0fbae
			m->mem.image_base		= pe_read_long(p->opt_hdr_32.image_base);
c0fbae
			m->mem.size_of_stack_reserve	= pe_read_long(p->opt_hdr_32.size_of_stack_reserve);
c0fbae
			m->mem.size_of_stack_commit	= pe_read_long(p->opt_hdr_32.size_of_stack_commit);
c0fbae
			m->mem.size_of_heap_reserve	= pe_read_long(p->opt_hdr_32.size_of_heap_reserve);
c0fbae
			m->mem.size_of_heap_commit	= pe_read_long(p->opt_hdr_32.size_of_heap_commit);
c0fbae
			break;
c0fbae
c0fbae
		case PE_MAGIC_PE32_PLUS:
c0fbae
			m->mem.base_of_data		= (uint64_t)-1;
c0fbae
			m->mem.image_base		= pe_read_quad(p->opt_hdr_64.image_base);
c0fbae
			m->mem.size_of_stack_reserve	= pe_read_quad(p->opt_hdr_64.size_of_stack_reserve);
c0fbae
			m->mem.size_of_stack_commit	= pe_read_quad(p->opt_hdr_64.size_of_stack_commit);
c0fbae
			m->mem.size_of_heap_reserve	= pe_read_quad(p->opt_hdr_64.size_of_heap_reserve);
c0fbae
			m->mem.size_of_heap_commit	= pe_read_quad(p->opt_hdr_64.size_of_heap_commit);
c0fbae
			break;
c7189e
	}
c0fbae
c0fbae
	return 0;
b5f7f5
}