Files
luckyware/LuckywareCode/LuckywareStub/ExInfector/winhook.h
T
2026-08-27 11:23:03 -06:00

753 lines
22 KiB
C

/**
* windows dyamic hook util functions wrappers
* v0.3.3, developed by devseed
*
* macros:
* WINHOOK_IMPLEMENT, include defines of each function
* WINHOOK_SHARED, make function export
* WINHOOK_STATIC, make function static
* WINHOOK_NOINLINE, don't use inline function
* WINHOOK_NO3RDLIB, don't use 3rd lib for inlinehook
* WINHOOK_USEDYNBIND, use dynamic binding for winapi api
*/
#ifndef _WINHOOK_H
#define _WINHOOK_H
#define WINHOOK_VERSION 330
#ifdef USECOMPAT
#include "commdef_v100.h"
#else
#include "commdef.h"
#endif // USECOMPAT
// define specific macro
#ifdef WINHOOK_API
#undef WINHOOK_API
#endif
#ifdef WINHOOK_API_DEF
#undef WINHOOK_API_DEF
#endif
#ifdef WINHOOK_API_EXPORT
#undef WINHOOK_API_EXPORT
#endif
#ifdef WINHOOK_API_INLINE
#undef WINHOOK_API_INLINE
#endif
#ifdef WINHOOK_STATIC
#define WINHOOK_API_DEF static
#else
#define WINHOOK_API_DEF extern
#endif // WINHOOK_STATIC
#ifdef WINHOOK_SHARED
#define WINHOOK_API_EXPORT EXPORT
#else
#define WINHOOK_API_EXPORT
#endif // WINHOOK_SHARED
#ifdef WINHOOK_NOINLINE
#define WINHOOK_API_INLINE
#else
#define WINHOOK_API_INLINE INLINE
#endif // WINHOOK_NOINLINE
#define WINHOOK_API WINHOOK_API_DEF WINHOOK_API_EXPORT WINHOOK_API_INLINE
#ifdef __cplusplus
extern "C" {
#endif
#include <windows.h>
/**
* start a exe and inject dll into exe
* @return pid
*/
WINHOOK_API
DWORD winhook_startexeinject(LPCSTR exepath, LPSTR cmdstr, LPCSTR dllpath);
/**
* start a exe by CreateProcess
* @return pid
*/
WINHOOK_API
DWORD winhook_startexe(LPCSTR exepath, LPSTR cmdstr)
{
return winhook_startexeinject(exepath, cmdstr, NULL);
}
/**
* get the process handle by exename
*/
WINHOOK_API
HANDLE winhook_getprocess(LPCWSTR exename);
/**
* get the other process image base
*/
WINHOOK_API
size_t winhook_getimagebase(HANDLE hprocess);
/**
* dynamic inject a dll into a process
*/
WINHOOK_API
BOOL winhook_injectdll(HANDLE hprocess, LPCSTR dllname);
/**
* alloc a console for the program
*/
WINHOOK_API
void winhook_installconsole();
/**
* patch addr by buf with bufsize
*/
WINHOOK_API
BOOL winhook_patchmemoryex(HANDLE hprocess,LPVOID addr, const void* buf, size_t bufsize);
WINHOOK_API
BOOL winhook_patchmemory(LPVOID addr, const void* buf, size_t bufsize)
{
return winhook_patchmemoryex(GetCurrentProcess(), addr, buf, bufsize);
}
/**
* batch patch memories
*/
WINHOOK_API
BOOL winhook_patchmemorysex(HANDLE hprocess,
LPVOID addrs[], void* bufs[], size_t bufsizes[], int n);
WINHOOK_API
BOOL winhook_patchmemorys(LPVOID addrs[], void* bufs[], size_t bufsizes[], int n)
{
return winhook_patchmemorysex(GetCurrentProcess(), addrs, bufs, bufsizes, n);
}
/**
* patch memory with pattern,
* @param pattern
* skip '#' line, + for reative address, then multi byte code (hex)
* 00400000: ff 90
* +3f00: 90 90 90 90
* +3f06: 90; +3f08: 90
* @return patch bytes number, error < 0
*/
WINHOOK_API
int winhook_patchmemorypattern(const char *pattern);
/**
* patch memory with pattern 1337 by x64dbg, use rva
* can use ';' instead of '\r' '\n'
*/
WINHOOK_API
int winhook_patchmemory1337ex(HANDLE hprocess,
const char* pattern, size_t base, BOOL revert);
WINHOOK_API
int winhook_patchmemory1337(const char* pattern, size_t base, BOOL revert)
{
return winhook_patchmemory1337ex(GetCurrentProcess(), pattern, base, revert);
}
/**
* patch memory with pattern ips(International Patching System)
* specifications at https://zerosoft.zophar.net/ips.php
* addr is relative to base, big endian
*/
WINHOOK_API
int winhook_patchmemoryipsex(HANDLE hprocess, const char* pattern, size_t base);
WINHOOK_API
int winhook_patchmemoryips(const char* pattern, size_t base)
{
return winhook_patchmemoryipsex(GetCurrentProcess(), pattern, base);
}
/**
* search the pattern like "ab 12 ?? 34"
* @return the matched address
*/
WINHOOK_API
void* winhook_searchmemory(void* addr, size_t memsize,
const char* pattern, size_t *pmatchsize);
WINHOOK_API
void* winhook_searchmemoryex(HANDLE hprocess,
void* addr, size_t memsize, const char* pattern, size_t* pmatchsize);
/**
* winhook_iathookmodule is for windows dll,
* @param moduleDllName is which dll to hook iat
*/
WINHOOK_API
BOOL winhook_iathookpe(LPCSTR targetDllName, void* mempe, PROC pfnOrg, PROC pfnNew);
WINHOOK_API
BOOL winhook_iathookmodule(LPCSTR targetDllName, LPCSTR moduleDllName, PROC pfnOrg, PROC pfnNew)
{
return winhook_iathookpe(targetDllName, GetModuleHandle(moduleDllName), pfnOrg, pfnNew);
}
/**
* iat dynamiclly hook,
* replace the @param pfgNew with @param pfnOrg function
* @param targetDllName like "user32.dll", "kernel32.dll"
*/
WINHOOK_API
BOOL winhook_iathook(LPCSTR targetDllName, PROC pfnOrg, PROC pfgNew)
{
return winhook_iathookmodule(targetDllName, NULL, pfnOrg, pfgNew);
}
/**
* inline hooks wrapper,
* @param pfnTargets -> @param pfnNews, save origin pointers in @param pfnOlds
* @return: success hook numbers
*/
WINHOOK_API
int winhook_inlinehooks(PVOID pfnTargets[], PVOID pfnNews[], PVOID pfnOlds[], int n);
WINHOOK_API
int winhook_inlineunhooks(PVOID pfnTargets[], PVOID pfnNews[], PVOID pfnOlds[], int n);
#ifdef WINHOOK_IMPLEMENTATION
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <psapi.h>
#ifdef WINHOOK_USEDYNBIND
#ifndef WINDYN_IMPLEMENTATION
#define WINDYN_IMPLEMENTATION
#endif // WINDYN_IMPLEMENTATION
#ifndef WINDYN_STATIC
#define WINDYN_STATIC
#endif // WINDYN_STATIC
#ifdef USECOMPAT
#include "windyn_v150.h"
#else
#include "windyn.h"
#endif // USECOMPAT
#define strlen inl_strlen
#define _stricmp inl_stricmp
#define _wcsicmp inl_wcsicmp
#define GetModuleHandleA windyn_GetModuleHandleA
#define LoadLibraryA windyn_LoadLibraryA
#define GetProcAddress windyn_GetProcAddress
#define VirtualAllocEx windyn_VirtualAllocEx
#endif // WINHOOK_USEDYNBIND
// loader functions
DWORD winhook_startexeinject(LPCSTR exepath, LPSTR cmdstr, LPCSTR dllpath)
{
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(STARTUPINFOA);
if (!CreateProcessA(exepath, cmdstr,NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
return 0;
if (dllpath) // inject dll to process
{
size_t n = 0;
HANDLE hprocess = pi.hProcess;
HANDLE hthread = pi.hThread;
LPVOID injectaddr = VirtualAllocEx(hprocess,
0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
size_t oepva = 0;
// prepare shellcode
CONTEXT context = { 0 };
context.ContextFlags = CONTEXT_ALL;
GetThreadContext(hthread, &context);
#ifdef _WIN64
uint8_t injectcode[] = {0x50,0x53,0x51,0x52,0xe8,0x2d,0x00,0x00,0x00,0x48,0x8d,0x58,0xf7,0x48,0x83,0xec,0x28,0x48,0x8b,0x8b,0x43,0x00,0x00,0x00,0x48,0x8b,0x83,0x4b,0x00,0x00,0x00,0xff,0xd0,0x48,0x83,0xc4,0x28,0x48,0x8b,0x83,0x3b,0x00,0x00,0x00,0x49,0x89,0xc7,0x5a,0x59,0x5b,0x58,0x41,0xff,0xe7,0x48,0x8b,0x04,0x24,0xc3,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 };
oepva = context.Rip;
context.Rip = (ULONGLONG)injectaddr;
#else
uint8_t injectcode[] = {0x50,0x53,0xe8,0x1e,0x00,0x00,0x00,0x8d,0x58,0xf9,0x8b,0x83,0x2d,0x00,0x00,0x00,0x50,0x8b,0x83,0x31,0x00,0x00,0x00,0xff,0xd0,0x8b,0x83,0x29,0x00,0x00,0x00,0x89,0xc7,0x5b,0x58,0xff,0xe7,0x8b,0x04,0x24,0xc3,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 };
oepva = context.Eip; // origin eip at RtlUserThreadStart
context.Eip = (DWORD)injectaddr;
#endif
SetThreadContext(hthread, &context);
char name_kernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', '\0'};
HMODULE kernel32 = GetModuleHandleA(name_kernel32);
char name_LoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };
FARPROC pfnLoadlibraryA = GetProcAddress(kernel32, name_LoadLibraryA);
size_t* pretva = (size_t*)(injectcode
+ sizeof(injectcode) - 3 * sizeof(size_t));
size_t *pdllnameva = (size_t*)(injectcode
+ sizeof(injectcode) - 2 * sizeof(size_t));
size_t* ploadlibraryva = (size_t*)(injectcode
+ sizeof(injectcode) - 1 * sizeof(size_t));
*pretva = (size_t)oepva;
*pdllnameva = (size_t)((size_t)injectaddr + sizeof(injectcode));
*ploadlibraryva = (size_t)pfnLoadlibraryA;
uint8_t* addr = (uint8_t*)injectaddr;
WriteProcessMemory(hprocess, addr,
injectcode, sizeof(injectcode), (SIZE_T*)&n); // copy shellcode
addr += sizeof(injectcode);
WriteProcessMemory(hprocess, addr,
dllpath, strlen(dllpath) + 1, (SIZE_T*)&n); // copy dll name
}
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
return pi.dwProcessId;
}
HANDLE winhook_getprocess(LPCWSTR exename)
{
// Create toolhelp snapshot.
DWORD pid = 0;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
// Walkthrough all processes.
if (Process32First(snapshot, &process))
{
do
{
if (_wcsicmp((const wchar_t*)process.szExeFile, exename) == 0)
{
pid = process.th32ProcessID;
break;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
if (pid != 0) return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
return NULL; // Not found
}
size_t winhook_getimagebase(HANDLE hprocess)
{
//if (hprocess == GetCurrentProcess()) return (size_t)GetModuleHandleA(NULL);
HMODULE modules[1024]; // Array that receives the list of module handles
DWORD nmodules = 0;
char modulename[MAX_PATH] = {0};
if (!EnumProcessModules(hprocess, modules, sizeof(modules), &nmodules))
return 0; // impossible to read modules
if (!GetModuleFileNameExA(hprocess, modules[0], modulename, sizeof(modulename)))
return 0; // impossible to get module info
return (size_t)modules[0]; // module 0 is apparently always the EXE itself
}
BOOL winhook_injectdll(HANDLE hprocess, LPCSTR dllname)
{
LPVOID addr = VirtualAllocEx(hprocess,
0, 0x100, MEM_COMMIT, PAGE_READWRITE);
SIZE_T count;
if (addr == NULL) return FALSE;
WriteProcessMemory(hprocess,
addr, dllname, strlen(dllname)+1, (SIZE_T*)&count);
char name_kernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', '\0' };
HMODULE kernel32 = GetModuleHandleA(name_kernel32);
char name_LoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };
FARPROC pfnLoadlibraryA = GetProcAddress(kernel32, name_LoadLibraryA);
HANDLE hthread = CreateRemoteThread(hprocess, NULL, 0,
(LPTHREAD_START_ROUTINE)pfnLoadlibraryA, addr, 0, NULL);
if (hthread == NULL) return FALSE;
WaitForSingleObject(hthread, -1);
VirtualFreeEx(hprocess, addr, 0x100, MEM_COMMIT);
return TRUE;
}
void winhook_installconsole()
{
AllocConsole();
freopen("CONOUT$", "w", stdout);
}
// dynamic hook functions
BOOL winhook_patchmemoryex(HANDLE hprocess, LPVOID addr, const void* buf, size_t bufsize)
{
if (addr == NULL || buf == NULL) return FALSE;
DWORD oldprotect;
BOOL ret = VirtualProtectEx(hprocess, addr, bufsize, PAGE_EXECUTE_READWRITE, &oldprotect);
if (ret)
{
size_t n = 0;
WriteProcessMemory(hprocess, addr, buf, bufsize, (SIZE_T*)&n);
VirtualProtectEx(hprocess, addr, bufsize, oldprotect, &oldprotect);
}
return ret;
}
BOOL winhook_patchmemorysex(HANDLE hprocess, LPVOID addrs[], void* bufs[], size_t bufsizes[], int n)
{
int ret = 0;
for (int i = 0; i < n; i++)
{
ret += winhook_patchmemoryex(hprocess, addrs[i], bufs[i], bufsizes[i]);
}
return ret;
}
int winhook_patchmemorypattern(const char *pattern)
{
if (!pattern) return -1;
size_t imagebase = (size_t)GetModuleHandleA(NULL);
int res = 0;
int flag_rel = 0;
int j = 0;
while (pattern[j]) j++;
int patternlen = j;
DWORD oldprotect;
for(int i=0; i<patternlen; i++)
{
if(pattern[i]=='#')
{
while(pattern[i]!='\n' && i<patternlen) i++;
continue;
}
else if (pattern[i] == '\n' || pattern[i] == '\r')
{
continue;
}
else if (pattern[i]=='+')
{
flag_rel = 1;
i++;
}
while (pattern[i]==' ') i++;
size_t addr = 0;
int flag_nextline = 0;
for (;pattern[i]!=':' && i<patternlen; i++)
{
char c = pattern[i];
if(c>='0' && c<='9') c -= '0';
else if (c>='A' && c<='Z') c = c -'A' + 10;
else if (c>='a' && c<='z') c = c -'a' + 10;
else if (c=='\r' || c=='\n') {flag_nextline=1;break;}
else if (c==' ') continue;
else return -2;
addr = (addr<<4) + c;
}
if(flag_nextline) continue;
if(flag_rel) addr += imagebase;
int n = 0;
int v = 0;
int start = i++;
for(int j=0;j<2;j++)
{
n = 0;
for(;pattern[i]!='\n' && i<patternlen;i++)
{
char c = pattern[i];
if(c>='0' && c<='9') c -= '0';
else if (c>='A' && c<='Z') c = c - 'A' + 10;
else if (c>='a' && c<='z') c = c - 'a' + 10;
else if (c==';') break;
else continue;
n++;
if (j != 0)
{
v = (v << 4) + c;
if (!(n & 1))
{
*(uint8_t*)(addr + (n>>1) -1) = v;
v = 0;
res++;
}
}
}
if(n&1) return -3;
if (j == 0)
{
i = start;
VirtualProtect((void*)addr, n>>1, PAGE_EXECUTE_READWRITE, &oldprotect);
}
else VirtualProtect((void*)addr, n>>1, oldprotect, &oldprotect);
}
flag_rel = 0;
}
return res;
}
int winhook_patchmemory1337ex(HANDLE hprocess, const char* pattern, size_t base, BOOL revert)
{
#define IS_ENDLINE(c) (c==';' || c=='\r' || c=='\n')
enum FLAG1337 {
RVA1337,
OLDBYTE1337,
NEWBYTE1337
} flag1337 = RVA1337;
if (hprocess == NULL) return -1;
int res = 0;
int i = 0;
while (pattern[i]) i++;
int patternlen = i;
i = 0;
while (pattern[i] != '>') i++; // title line
while (!IS_ENDLINE(pattern[i])) i++;
while (IS_ENDLINE(pattern[i])) i++;
size_t rva = 0;
uint8_t oldbyte = 0, newbyte = 0;
for (; i < patternlen; i++)
{
char c = pattern[i];
if (c == ':') // oldbyte indicator
{
flag1337 = OLDBYTE1337;
}
else if (c == '-') // newbyte indicator
{
if (pattern[i + 1] != '>') return -1;
flag1337 = NEWBYTE1337;
i++;
}
else if (IS_ENDLINE(c)) // flush patch
{
if (flag1337 == RVA1337) continue;
uint8_t* patchbyte = revert ? &oldbyte : &newbyte;
winhook_patchmemoryex(hprocess, (LPVOID)(base + rva), patchbyte, 1);
flag1337 = RVA1337;
rva = 0;
oldbyte = 0;
newbyte = 0;
res++;
}
else if (c == ' ')
{
continue;
}
else
{
if (c >= '0' && c <= '9') c -= '0';
else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
else continue;
switch (flag1337)
{
case RVA1337:
rva = (rva << 4) | (uint8_t)c;
break;
case OLDBYTE1337:
oldbyte = (oldbyte << 4) | (uint8_t)c;
break;
case NEWBYTE1337:
newbyte = (newbyte << 4) | (uint8_t)c;
break;
}
}
}
return res;
}
int winhook_patchmemoryipsex(HANDLE hprocess, const char* pattern, size_t base)
{
#define BYTE3_TO_UINT_BIGENDIAN(bp) \
(((unsigned int)(bp)[0] << 16) & 0x00FF0000) | \
(((unsigned int)(bp)[1] << 8) & 0x0000FF00) | \
((unsigned int)(bp)[2] & 0x000000FF)
#define BYTE2_TO_UINT_BIGENDIAN(bp) \
(((unsigned int)(bp)[0] << 8) & 0xFF00) | \
((unsigned int) (bp)[1] & 0x00FF)
if(strncmp(pattern, "PATCH", 5) !=0 ) return -1;
int res = 0;
const uint8_t* p = (uint8_t*)pattern + 5;
while (strncmp((char*)p, "EOF", 3) != 0)
{
unsigned int offset = BYTE3_TO_UINT_BIGENDIAN(p);
unsigned int size = BYTE2_TO_UINT_BIGENDIAN(p + 3);
p += 5;
if (size == 0) // use RLE compress
{
unsigned int size_rle = BYTE2_TO_UINT_BIGENDIAN(p);
return -2; // not implemented yet
}
else
{
size_t addr = base + offset;
winhook_patchmemoryex(hprocess, (LPVOID)addr, p, size);
p += size;
res += size;
}
}
return res;
}
void* winhook_searchmemory(void* addr,
size_t memsize, const char* pattern, size_t* pmatchsize)
{
size_t i = 0;
int matchend = 0;
void* matchaddr = NULL;
while (i < memsize)
{
int j = 0;
int matchflag = 1;
matchend = 0;
while (pattern[j])
{
if (pattern[j] == 0x20)
{
j++;
continue;
}
char _c1 = (((char*)addr)[i+matchend]>>4) & 0x0f;
_c1 = _c1 < 10 ? _c1 + '0' : (_c1 - 10) + 'A';
char _c2 = (((char*)addr)[i+matchend]&0xf) & 0x0f;
_c2 = _c2 < 10 ? _c2 + '0' : (_c2 - 10) + 'A';
if (pattern[j] != '?')
{
if (_c1 != pattern[j] && _c1 + 0x20 != pattern[j])
{
matchflag = 0;
break;
}
}
if (pattern[j + 1] != '?')
{
if (_c2 != pattern[j+1] && _c2 + 0x20 != pattern[j+1])
{
matchflag = 0;
break;
}
}
j += 2;
matchend++;
}
if (matchflag)
{
matchaddr = (void*)((uint8_t*)addr + i);
break;
}
i++;
}
if (pmatchsize) *pmatchsize = matchend;
return matchaddr;
}
void* winhook_searchmemoryex(HANDLE hprocess,
void* addr, size_t memsize, const char* pattern, size_t* pmatchsize)
{
void* buf = VirtualAlloc(NULL, memsize, MEM_COMMIT, PAGE_READWRITE);
size_t bufsize = 0;
ReadProcessMemory(hprocess, addr, buf, memsize, (SIZE_T*)&bufsize);
void* matchaddr = winhook_searchmemory(buf, memsize, pattern, pmatchsize);
VirtualFree(buf, 0, MEM_RELEASE);
if (!matchaddr) return matchaddr;
size_t offset = (size_t)matchaddr - (size_t)buf;
return (void*)((uint8_t*)addr + offset);
}
BOOL winhook_iathookpe(LPCSTR targetDllName, void* mempe, PROC pfnOrg, PROC pfnNew)
{
size_t imagebase = (size_t)mempe;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)imagebase;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)
((uint8_t*)imagebase + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader;
PIMAGE_DATA_DIRECTORY pDataDirectory = pOptHeader->DataDirectory;
PIMAGE_DATA_DIRECTORY pImpEntry =
&pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR pImpDescriptor =
(PIMAGE_IMPORT_DESCRIPTOR)(imagebase + pImpEntry->VirtualAddress);
DWORD dwOldProtect = 0;
for (; pImpDescriptor->Name; pImpDescriptor++)
{
// find the dll IMPORT_DESCRIPTOR
LPCSTR pDllName = (LPCSTR)(imagebase + pImpDescriptor->Name);
if (!_stricmp(pDllName, targetDllName)) // ignore case
{
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(imagebase + pImpDescriptor->FirstThunk);
// find the iat function va
for (; pFirstThunk->u1.Function; pFirstThunk++)
{
if (pFirstThunk->u1.Function == (size_t)pfnOrg)
{
VirtualProtect((LPVOID)&pFirstThunk->u1.Function, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect);
pFirstThunk->u1.Function = (size_t)pfnNew;
VirtualProtect((LPVOID)&pFirstThunk->u1.Function, 4, dwOldProtect, &dwOldProtect);
return TRUE;
}
}
}
}
return FALSE;
}
#ifndef WINHOOK_NO3RDLIB
#ifndef MINHOOK_IMPLEMENTATION
#define MINHOOK_IMPLEMENTATION
#define MINHOOK_STATIC
#endif // MINHOOK_IMPLEMENTATION
#ifdef USECOMPAT
#include "stb_minhook_v1331.h"
#else
#include "stb_minhook.h"
#endif
int winhook_inlinehooks(PVOID pfnTargets[], PVOID pfnNews[], PVOID pfnOlds[], int n)
{
int i;
MH_Initialize();
for(i=0; i<n ;i++)
{
MH_STATUS status;
if(!pfnNews[i] || !pfnTargets[i]) continue;
status = MH_CreateHook(pfnTargets[i], pfnNews[i], &pfnOlds[i]);
if(status!= MH_OK) return i;
status = MH_EnableHook(pfnTargets[i]);
if(status!= MH_OK) return i;
}
return i;
}
int winhook_inlineunhooks(PVOID pfnTargets[], PVOID pfnNews[], PVOID pfnOlds[], int n)
{
int i;
for(i=0; i<n ;i++)
{
if(!pfnNews[i] || !pfnTargets[i]) continue;
MH_DisableHook(pfnTargets[i]);
}
if(MH_Uninitialize() != MH_OK) return 0;
return i;
}
#endif // WINHOOK_NO3RDLIB
#endif // MINHOOK_IMPLEMENTATION
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _WINHOOK_H
/**
* history:
* v0.1, initial version
* v0.2, add make this to single file
* v0.2.2, add WINHOOK_STATIC, WINHOOK_SHARED macro
* v0.2.3, change name to winhook.h and add guard for function name
* v0.2.4, add winhook_searchmemory
* v0.2.5, add minhook backend, compatible withh gcc, tcc
* v0.2.6, support function to patch or search other process memory
* v0.2.7, add win_startexeinject, fix winhook_searchmemoryex match bug
* v0.3, use javadoc style, add winhook_patchmemorypattern
* v0.3.1, add winhook_patchmemory1337, winhook_patchmemoryips
* v0.3.2, improve macro style, chaneg some of macro to function
* v0.3.3, seperate some macro to commdef
*/