// process_util.h : include utilities for manage folders // // Author: Gongbing // // Date: 2016-09-25 #pragma once #include #include #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); };