Blob Blame History Raw
/********************************************************/
/*  ntapi: Native API core library                      */
/*  Copyright (C) 2013--2016  Z. Gilboa                 */
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
/********************************************************/

#include <psxtypes/psxtypes.h>
#include <pemagine/pemagine.h>
#include <ntapi/nt_section.h>
#include <ntapi/nt_process.h>
#include <ntapi/ntapi.h>
#include "ntapi_impl.h"

static nt_sqos const sqos = {
	sizeof(sqos),
	NT_SECURITY_IMPERSONATION,
	NT_SECURITY_TRACKING_DYNAMIC,
	1};

static int32_t __tt_exec_unmap_image(nt_executable_image * image, void * base, int32_t status)
{
	int32_t ret;

	if (base)
		if ((ret = __ntapi->zw_unmap_view_of_section(
				NT_CURRENT_PROCESS_HANDLE,
				base)))
			return ret;

	if (image->hsection)
		if ((ret = __ntapi->zw_close(image->hsection)))
			return ret;

	return status;
}

int32_t	__stdcall __ntapi_tt_exec_unmap_image(nt_executable_image * image)
{
	return __tt_exec_unmap_image(image,image->addr,0);
}


int32_t __stdcall __ntapi_tt_exec_map_image_as_data(nt_executable_image * image)
{
	int32_t				status;
	uint16_t *			pi16;
	uint32_t *			pi32;
	nt_sec_size			sec_size;
	size_t				view_size;
	void *				base;
	void *				hsection;

	struct pe_image_dos_hdr *	dos;
	struct pe_coff_file_hdr *	coff;
	union  pe_opt_hdr *		opt;
	struct pe_sec_hdr *		sec;

	nt_oa oa = {sizeof(oa),
		    0,0,0,0,(nt_sqos *)&sqos};

	base = 0;
	sec_size.quad = 0;
	view_size = image->size;

	if ((status = __ntapi->zw_create_section(
			&hsection,
			NT_SECTION_MAP_READ,
			&oa,
			&sec_size,
			NT_PAGE_READONLY,
			NT_SEC_RESERVE,image->hfile)))
		return status;

	if ((status = __ntapi->zw_map_view_of_section(
			hsection,
			NT_CURRENT_PROCESS_HANDLE,
			&base,
			0,0,0,
			&view_size,
			NT_VIEW_UNMAP,0,
			NT_PAGE_READONLY)))
		return __tt_exec_unmap_image(
			image,base,status);

	if (!(dos = pe_get_image_dos_hdr_addr(base)))
		return 0;

	pi32 = (uint32_t *)dos->dos_lfanew;
	if ((*pi32 + sizeof(*coff)) > view_size)
		return __tt_exec_unmap_image(
			image,base,NT_STATUS_INVALID_IMAGE_FORMAT);

	if (!(coff = pe_get_image_coff_hdr_addr(base)))
		return 0;

	if (!(opt = pe_get_image_opt_hdr_addr(base)))
		return 0;

	sec  = pe_get_image_section_tbl_addr(base);
	pi16 = (uint16_t *)coff->num_of_sections;
	if (((size_t)sec-(size_t)base + *pi16 * sizeof(*sec)) > view_size)
		return __tt_exec_unmap_image(
			image,base,NT_STATUS_INVALID_IMAGE_FORMAT);

	/* subsystem: same offset (pe32, pe32+) */
	pi16 = (uint16_t *)opt;
	image->magic = *pi16;

	pi16 = (uint16_t *)opt->opt_hdr_32.subsystem;
	image->subsystem = *pi16;

	pi16 = (uint16_t *)coff->characteristics;
	image->characteristics = *pi16;

	image->hsection = hsection;
	image->addr = base;
	image->size = view_size;

	return status;
}