doc_and_tools/tools/sdk/include/process/pe_util.h

224 lines
10 KiB
C++

// process_util.h : include utilities for manage folders
//
// Author: Gongbing
//
// Date: 2016-09-25
#pragma once
#include <string>
#include <vector>
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
// hook utils
namespace pe_util
{
__declspec(novtable) struct IObscurityCall : public ref_util::IRef
{
// params must not be NULL but the API was no parameter
COM_API_DECLARE(long, invoke(void** params, int* ret_val = NULL)); // return error code
};
#pragma pack(push)
#pragma pack(1)
typedef struct _hook_instruction_info
{
// e.g. in instruction 'E912345678', then bytes = 5, rel_addr_off = 1, rel_addr_size = 4
unsigned long bytes : 6; // all bytes in this instruction
unsigned long far_bytes : 3; // the far jumping instruction bytes if this was a near jumping instruction
unsigned long rel_addr_off : 3; // relative address offset to instruction in this
unsigned long rel_addr_size : 3; // relative address size of this instruction, ZERO is none
unsigned char far_instruction[8]; // far jumping instruction, relative address size always be 4 bytes (int)
unsigned long far_adden; // the jumping offset should added this value for converting near jumping to far jumping
}HOOKII, *LPHOOKII;
typedef struct _group_icon_entry
{
unsigned char width;
unsigned char height;
unsigned char color_count;
unsigned char reserved;
unsigned short planes;
unsigned short bits_per_pixel;
unsigned long bytes;
unsigned short id;
}GROUPICONENTRY, *LPGROUPICONENTRY;
typedef struct _group_icon // for RT_GROUP_ICON
{
unsigned short reserved;
unsigned short res_type; // 1 for icon
unsigned short entries;
GROUPICONENTRY entry[1];
}GROUPICON, *LPGROUPICON;
#pragma pack(pop)
PORT_API(LPVOID) allocate_code_buffer(size_t size);
PORT_API(void) free_code_buffer(LPVOID code_buf);
PORT_API(int) get_min_code_buffer_bytes(void);
// function: calculate hooking info at hook_addr
// hook_addr: the address will be hooked
// lphii: the hooking instruction info, at least 6 elements
// size: [in] - count of lphii, [out] - valid elements in lphii
// bytes: to receive the minimum bytes to be moved for hooking
// return: error code
PORT_API(int) calculate_hook_bytes(const BYTE* hook_addr, LPHOOKII lphii, int* size, int* bytes);
PORT_API(LPVOID) move_src_code_for_hook(LPVOID src_code, LPHOOKII lphii, int count, LPVOID given_buf = NULL, int bytes = 0);
// hook_addr: the instruction address which you should hooking at
// new_addr: your hooking codes which would jump from hood_addr
// origin_code: to receive origin codes at hook_addr. or the given address for hook junk if was not NULL, then the moved_bytes contains the size of the buffer when in
// moved_bytes: to receive copied bytes from hook_addr. it can contains the origin_code buffer bytes if origin_code is not NULL
PORT_API(int) hook_at(DWORD_PTR hook_addr, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes);
PORT_API(int) hook_at(const char* module_name, const char* api, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes, int api_offset = 0);
PORT_API(int) hook_with_shellcode(DWORD_PTR hook_addr, unsigned char* shellcodes, size_t shell_codes_bytes); // // RVA in shellcodes will not be handled !!!
PORT_API(int) unhook_at(DWORD_PTR unhook_addr, DWORD_PTR* origin_code, int bytes_moved);
PORT_API(int) unhook_at(const char* module_name, const char* api, DWORD_PTR *origin_code, int bytes_moved, int api_offset = 0);
// hook_bef: call method must be '__stdcall', and the parameters are pointers that points to the parameter of the origin api
// hook_after: call method must be '__stdcall', and the first parameter is the return value of origin api whenever the origin api return value or not
// and following the parameters is the same as origin api
//
// e.g. system api: HANDLE WINAPI CreateFileW(_In_ LPCWSTR lpFileName,
// _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,
// _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
// _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes,
// _In_opt_ HANDLE hTemplateFile);
// hook_bef: void __stdcall hook_bef(LPCWSTR* lpFileName,
// DWORD* dwDesiredAccess, DWORD* dwShareMode,
// LPSECURITY_ATTRIBUTES* lpSecurityAttributes,
// DWORD* dwCreationDisposition, DWORD* dwFlagsAndAttributes,
// HANDLE* hTemplateFile
// void* user_data);
// or can be void __stdcall hook_bef(void* user_data) if no_param_for_hook_before was true;
//
// hook_after: void __stdcall hook_after(HANDLE* ret, LPCWSTR lpFileName,
// DWORD dwDesiredAccess, DWORD dwShareMode,
// LPSECURITY_ATTRIBUTES lpSecurityAttributes,
// DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
// HANDLE hTemplateFile
// void* user_data);
//
//
PORT_API(void*) any_hook_at(FARPROC api, size_t param_count, bool stdcall, FARPROC hook_bef = NULL, bool hook_bef_without_param = false, FARPROC hook_after = NULL, void* user_data = NULL);
PORT_API(void) free_any_hook(void* any_hook);
PORT_API(IObscurityCall*) create_obscurity_caller(const wchar_t* module, const char* api, int api_params, bool stdcall);
PORT_API(IObscurityCall*) create_obscurity_caller(HMODULE module, const char* api, int api_params, bool stdcall);
// pe parsing ...
enum pe_address_type
{
PE_ADDR_RELATIVE_TO_FILE = 0,
PE_ADDR_RELATIVE_TO_MEM,
PE_ADDR_ABSOLUTE_ON_DEFAULT_BASE,
};
__declspec(novtable) struct IPe : public ref_util::IRef
{
// params must not be NULL but the API was no parameter
COM_API_DECLARE(long, load_pe(const wchar_t* path_pe)); // return error code
COM_API_DECLARE(long, close(void)); // return error code, owner MUST call this before 'release' when you never use this !!!
COM_API_DECLARE(long, attach(unsigned char* buf, UINT64 bytes)); // return error code
COM_API_DECLARE(long, detach(unsigned char** buf)); // return error code
// cb: data - (const char*)dll_name if flag was DATA_FLAG_FINAL or (const char*)err_msg if flag was DATA_FLAG_ERROR
// or "IAT" if flag was DATA_FLAG_INSTAR
// len - (const char*)api_name
// or IAT sector info(void*[2]) if flag was DATA_FLAG_INSTAR: [0] - (char*)section name, [1] - (UINT64) offset to file
// total - UINT64[2]: [0] - hint, [2] - offset in file(EAT only), [1] - offset in mem set to be '0' if 'only_dll' was true if flag was DATA_FLAG_FINAL or unused if flag was DATA_FLAG_ERROR
// or IAT table info(UINT64[3]) if flag was DATA_FLAG_INSTAR: [0] - offset to file, [1] - offset in memory, [2] - table bytes
// flag - DATA_FLAG_FINAL or DATA_FLAG_INSTAR or DATA_FLAG_ERROR
//
// param - same as the paramenter you passed 'param'
//
// return non 'SET_RESULT_CONTINUE' to stop working
COM_API_DECLARE(long, dump_iat(INTER_MODULE_CALLBACK_VAR(cb), void* param, bool only_dll = false));
COM_API_DECLARE(long, dump_eat(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// cb: data - (const char*)section name
//
// len - bytes of section name
//
// total - UINT64 pos[3]: pos[0] - offset in file, pos[1] - offset in memory, pos[2] - section size in bytes
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, dump_sections(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// cb: data - (const char*)resource name
//
// len - UINT64[2]: [0] - bytes of resource; [1] - (void*)resource_data
//
// total - UINT64[4]: [0] - id; [1] - memory offset; [2] - file offset, [3] - codepage
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, dump_resources(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: convert RVA between memory offset and file offset
//
// parameter: from - source address;
//
// to - to receive the target address
//
// off2rva - true: file offset to memory offset; false: memory offset to file offset
COM_API_DECLARE(long, rva(UINT64 from, UINT64* to, bool off2rva));
// cb: data - (const char*)assembly
//
// len - bytes of assembly
//
// total - UINT[2]: 0 - offset in file of the code, 1 - offset in memory of the assembly
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, find_address_ref(UINT64 addr, INTER_MODULE_CALLBACK_VAR(cb), void* param, short addr_bytes = 4));
COM_API_DECLARE(long, find_iat_ref(const char* dll_name, const char* api_name/*consider as hint if less than 0x10000*/, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(long, find_string_ref(const char* str, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(long, find_string_ref(const wchar_t* str, INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: un-assembly given function begin from 'addr' and ENDING at instruction 'ret' or 'cb' return SET_RESULT_STOP
//
// parameter: addr - given address
//
// addr_type - how to use the address 'addr'
//
// cb - data: (const char*) assembly
// len: bytes of data
// total: UINT64[4]: 0 - file offset; 1 - instruction absolute address; 2 - bytes; [3] - (unsigned char*) codes
// flag: DATA_FLAG_FINAL
// param: same as the paramenter you passed 'param'
// return SET_RESULT_CONTINUE to work until 'ret', or SET_RESULT_STOP to stop immediately
//
// param - parameter for 'cb'
//
// img_base - specify the image base. use default base if it was '0'
COM_API_DECLARE(long, un_assembly(UINT64 addr, enum pe_address_type addr_type, INTER_MODULE_CALLBACK_VAR(cb), void* param, UINT64 img_base = 0));
COM_API_DECLARE(long, un_assembly(const char* export_api_name, INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: to change content at given file offset
//
// cb - data: (const wchar_t*) target file after changed
// len: bytes of data
// total: unused
// flag: DATA_FLAG_FINAL
// param: same as the parameter you passed 'param'
// return: omitted
COM_API_DECLARE(long, change(UINT64 file_off, const unsigned char* data, size_t bytes, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(bool, is_pe_64(void)); // whether the PE is a 64-bits module
COM_API_DECLARE(long, get_entry_point(UINT64* off)); // get offset of entry-point in memory
COM_API_DECLARE(long, get_image_base_addr(UINT64* addr)); // get offset of entry-point in memory
COM_API_DECLARE(long, get_file_time(UINT64* file_time)); // get file compiled time
};
PORT_API(IPe*) create_pe_parser(void);
};