PdbLib/UpLoader/helper.h
2025-06-05 10:51:52 +08:00

564 lines
12 KiB
C++

#pragma once
#include <Windows.h>
#include <vector>
#include <iostream>
#include <WinInet.h>
#include <sstream>
#include <string>
#include <urlmon.h>
#include <Psapi.h>
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "Wininet.lib")
using namespace std;
#ifndef typeof
#define typeof(x) decltype(x)
#endif // !typeof
#ifndef PROPERTY
#define PROPERTY(t,n) __declspec( property (put = property__set_##n, get = property__get_##n)) t n
#define READONLY_PROPERTY(t,n) __declspec( property (get = property__get_##n) ) t n
#define WRITEONLY_PROPERTY(t,n) __declspec( property (put = property__set_##n) ) t n
#define GET(t,n) t property__get_##n()
#define SET(t,n) void property__set_##n(const t& value)
#endif // !PROPERTY
#ifndef ENCRYPT_SYSTEM_TYPE
#define ENCRYPT_SYSTEM_TYPE(type,name)\
unsigned long long _##name;\
PROPERTY(type, name);\
GET(type, name)\
{\
unsigned long long tmpval = _##name ^ ((unsigned long long)&_##name);\
type result;\
memcpy(&result, &tmpval, sizeof(result));\
return result;\
}\
SET(type, name)\
{\
unsigned long long tmpval = 0;\
memcpy(&tmpval, &value, sizeof(value));\
_##name = tmpval ^ ((unsigned long long)&_##name);\
}
#endif // !ENCRYPT_SYSTEM_TYPE
#ifndef _IMAGE_DEBUG_DIRECTORY_RAW_
#define _IMAGE_DEBUG_DIRECTORY_RAW_
typedef struct _IMAGE_DEBUG_DIRECTORY_RAW {
uint8_t format[4];
uint8_t PdbSignature[16];
uint32_t PdbDbiAge;
uint8_t ImageName[256];
const char* GuidString()
{
char buf[128];
sprintf_s(buf, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",
this->PdbSignature[3], this->PdbSignature[2],
this->PdbSignature[1], this->PdbSignature[0],
this->PdbSignature[5], this->PdbSignature[4],
this->PdbSignature[7], this->PdbSignature[6],
this->PdbSignature[8], this->PdbSignature[9],
this->PdbSignature[10], this->PdbSignature[11],
this->PdbSignature[12], this->PdbSignature[13],
this->PdbSignature[14], this->PdbSignature[15]
);
return buf;
}
} IMAGE_DEBUG_DIRECTORY_RAW, * PIMAGE_DEBUG_DIRECTORY_RAW;
#endif
#pragma region TPattern
class TPattern
{
std::string sMask;
std::string sPattern;
std::vector<uint8_t> bytes;
bool bIdaStyle = false;
private:
void Parse()
{
if (bIdaStyle)
{
ParsePatternIDA();
}
else
{
ParsePattern();
}
}
void ParsePattern()
{
auto uLen = sMask.length();
for (uint32_t i = 0; i < uLen; i++)
{
if (i < uLen && sPattern[i] == 0)
{
sPattern[i] = (char)0xFF;
}
if (sMask[i] == '?')
{
bytes.push_back(0);
}
else
{
auto sub = sPattern.substr(i, 1);
auto byte = uint8_t(sub[0]);
bytes.push_back(byte);
}
}
}
void ParsePatternIDA()
{
auto uLen = sPattern.length();
sMask.clear();
int b = 0;
char x, byteBuf = 0;
for (uint32_t i = 0; i < uLen; i++)
{
char c = (char)sPattern[i];
if (c >= '0' && c <= '9')
{
x = (0x0F & c);
byteBuf += (b) ? x : x << 4;
b++;
}
else if (c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')
{
if (c > 0x46)
{
c -= 0x20;
}
x = c - 0x37;
byteBuf += (b) ? x : x << 4;
b++;
}
else if (c == '?')
{
if (sPattern[i + 1] == '?')
{
i++;
}
bytes.push_back(0);
sMask += '?';
}
if (b > 1)
{
bytes.push_back(byteBuf);
b = 0;
byteBuf = 0;
sMask += 'x';
}
}
}
public:
TPattern(const char* sPattern)
{
bIdaStyle = true;
this->sPattern = sPattern;
Parse();
}
TPattern(const char* sPattern, const char* sMask)
{
this->sMask = sMask;
bytes.resize(this->sMask.length());
memcpy(&bytes[0], sPattern, bytes.size());
Parse();
}
std::vector<uint8_t> Get()
{
return bytes;
}
std::string GetMask()
{
return sMask;
}
size_t Size()
{
return bytes.size();
}
};
static void* Scan(void* pAddress, size_t size, TPattern* pattern)
{
auto pat = pattern->Get();
auto mask = pattern->GetMask();
uint8_t* pByte = (uint8_t*)pAddress;
size_t j = 0;
for (size_t i = 0; i < size; i++)
{
if (IsBadReadPtr(pByte + i, pat.size()))
{
continue;
}
if (pByte[i] == pat[j] || mask[j] == '?')
{
j++;
if (j == pat.size() - 1)
{
return (void*)((uintptr_t)pByte + i - pat.size() + 2);
}
}
else
{
j = 0;
}
}
return nullptr;
}
static void* ScanPattern(const char* szModule, const char* sPattern)
{
TPattern* pattern = new TPattern(sPattern);
OutputDebugStringA(pattern->GetMask().c_str());
MODULEINFO mi{ };
GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &mi, sizeof(mi));
LPVOID dwBaseAddress = mi.lpBaseOfDll;
const auto dwModuleSize = mi.SizeOfImage;
return Scan(dwBaseAddress, dwModuleSize - pattern->Size(), pattern);
}
template<typename T> T FindPattern(const char* szModule, std::string pattern, DWORD_PTR SizeOfImage = NULL)
{
#define INRANGE(x,a,b) (x >= a && x <= b)
#define getBits( x ) (INRANGE((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xa) : (INRANGE(x,'0','9') ? x - '0' : 0))
#define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1]))
HMODULE hModule = GetModuleHandleA(szModule);
const char* pat = pattern.c_str();
DWORD_PTR firstMatch = 0;
DWORD_PTR rangeStart = (T)hModule;
MODULEINFO miModInfo;
if (!SizeOfImage)
GetModuleInformation(GetCurrentProcess(), hModule, &miModInfo, sizeof(MODULEINFO));
DWORD_PTR rangeEnd = SizeOfImage ? rangeStart + SizeOfImage : rangeStart + (DWORD_PTR)miModInfo.SizeOfImage;
for (DWORD_PTR pCur = rangeStart; pCur < rangeEnd; pCur++)
{
if (!*pat)
return (T)firstMatch;
if (*(PBYTE)pat == '\?' || *(BYTE*)pCur == getByte(pat))
{
if (!firstMatch)
firstMatch = pCur;
if (!pat[2])
return (T)firstMatch;
if (*(PWORD)pat == '\?\?' || *(PBYTE)pat != '\?')
pat += 3;
else
pat += 2; //one ?
}
else
{
pat = pattern.c_str();
firstMatch = 0;
}
}
return NULL;
}
#pragma endregion
static char* TCHAR2char(const wchar_t* STR)
{
int size = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, FALSE);
char* str = new char[sizeof(char) * size];
WideCharToMultiByte(CP_ACP, 0, STR, -1, str, size, NULL, FALSE);
return str;
}
static wchar_t* Char2TCHAR(const char* _char)
{
int iLength;
iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0);
wchar_t* tchar = new wchar_t[sizeof(wchar_t) * iLength];
MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, tchar, iLength);
return tchar;
}
static string wstring_to_string(wstring s)
{
return string(TCHAR2char(s.c_str()));
}
static wstring string_to_wstring(string s)
{
return wstring(Char2TCHAR(s.c_str()));
}
static char* ToHex(const char* data, size_t len)
{
const char* key = "0123456789ABCDEF";
char* result = new char[(len * 2) + 1];
result[(len * 2)] = '\0';
for (int i = 0; i < len; i++)
{
result[i * 2] = key[((unsigned char)data[i]) / 0x10];
result[(i * 2) + 1] = key[((unsigned char)data[i]) % 0x10];
}
return result;
}
static char* ToHex(const BYTE* data, size_t len)
{
const char* key = "0123456789ABCDEF";
char* result = new char[(len * 2) + 1];
for (int i = 0; i < len; i++)
{
result[i * 2] = key[((unsigned char)data[i]) / 0x10];
result[(i * 2) + 1] = key[((unsigned char)data[i]) % 0x10];
}
result[len * 2] = '\0';
return result;
}
static vector<BYTE> ParseHex(const char* hex)
{
vector<BYTE> result = vector<BYTE>();
int len = strlen(hex);
BYTE* buffer = new BYTE[len];
bool ish = true;
BYTE val = 0;
for (int i = 0; i < len; i++)
{
bool isval = false;
BYTE v = 0;
if (hex[i] >= '0' && hex[i] <= '9')
{
v = (hex[i] - '0');
isval = true;
}
else if (hex[i] >= 'A' && hex[i] <= 'F')
{
v = 10 + (hex[i] - 'A');
isval = true;
}
else if (hex[i] >= 'a' && hex[i] <= 'f')
{
v = 10 + (hex[i] - 'a');
isval = true;
}
if (isval)
{
if (ish)
{
val = (v << 4) | val;
}
else
{
val = v | val;
result.push_back(val);
val = 0;
}
ish = !ish;
}
}
return result;
}
static initializer_list<char>* ReadAllBytes(const char* filePath)
{
HANDLE pFile;
DWORD fileSize;
char* buffer, * tmpBuf;
DWORD dwBytesRead, dwBytesToRead, tmpLen;
pFile = CreateFileA(filePath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (pFile == INVALID_HANDLE_VALUE)
{
CloseHandle(pFile);
return nullptr;
}
fileSize = GetFileSize(pFile, NULL);
buffer = (char*)malloc(fileSize);
if (!buffer)
{
return nullptr;
}
ZeroMemory(buffer, fileSize);
dwBytesToRead = fileSize;
dwBytesRead = 0;
tmpBuf = buffer;
do {
if (!ReadFile(pFile, tmpBuf, dwBytesToRead, &dwBytesRead, NULL) || dwBytesRead == 0)
break;
dwBytesToRead -= dwBytesRead;
tmpBuf += dwBytesRead;
} while (dwBytesToRead > 0);
CloseHandle(pFile);
return new initializer_list<char>(&buffer[0], &buffer[fileSize]);
}
static BOOL WriteAllBytes(const char* filePath, char* buffer, int len)
{
HANDLE pFile;
char* tmpBuf;
DWORD dwBytesWrite, dwBytesToWrite;
pFile = CreateFileA(filePath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (pFile == INVALID_HANDLE_VALUE)
{
CloseHandle(pFile);
return FALSE;
}
dwBytesToWrite = len;
dwBytesWrite = 0;
tmpBuf = buffer;
do {
WriteFile(pFile, tmpBuf, dwBytesToWrite, &dwBytesWrite, NULL);
dwBytesToWrite -= dwBytesWrite;
tmpBuf += dwBytesWrite;
} while (dwBytesToWrite > 0);
CloseHandle(pFile);
return TRUE;
}
static BOOL WriteAllBytes(const char* filePath, BYTE* buffer, int len)
{
return WriteAllBytes(filePath, (char*)buffer, len);
}
static BOOL WriteAllBytes(const char* filePath, vector<BYTE> buffer)
{
return WriteAllBytes(filePath, (char*)buffer.data(), buffer.size());
}
static BOOL WriteAllBytes(const char* filePath, initializer_list<BYTE> buffer)
{
return WriteAllBytes(filePath, (char*)buffer.begin(), buffer.size());
}
static BOOL WriteAllBytes(const char* filePath, initializer_list<char> buffer)
{
return WriteAllBytes(filePath, (char*)buffer.begin(), buffer.size());
}
static BOOL WriteAllText(const char* filePath, const char* text)
{
return WriteAllBytes(filePath, (char*)text, strlen(text));
}
static vector<BYTE> HttpRequest(const char* url)
{
#define MAXSIZE 4096
vector<BYTE> result = vector<BYTE>();
BYTE* val = new BYTE[MAXSIZE];
ULONG len = 1;
HINTERNET hSession = InternetOpenA(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hSession != NULL)
{
HINTERNET hHttp = InternetOpenUrlA(hSession, url, NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (hHttp != NULL)
{
while (len > 0)
{
InternetReadFile(hHttp, val, MAXSIZE - 1, &len);
if (len > 0)
{
int ldx = result.size();
result.resize(result.size() + len);
memcpy(&result.operator[](ldx), &val[0], len);
}
}
InternetCloseHandle(hHttp);
hHttp = NULL;
}
InternetCloseHandle(hSession);
hSession = NULL;
}
return result;
}
static string WebRequest(const char* url)
{
#define BLOCK_READ 4096
IStream* stream;
HRESULT result = URLOpenBlockingStreamA(0, url, &stream, 0, 0);
if (result != 0)
{
return "";
}
char buffer[BLOCK_READ];
unsigned long bytesRead;
stringstream ss;
stream->Read(buffer, BLOCK_READ, &bytesRead);
while (bytesRead > 0U)
{
ss.write(buffer, (long long)bytesRead);
stream->Read(buffer, BLOCK_READ, &bytesRead);
}
stream->Release();
return ss.str();
}
static BYTE* _get_jmp_address(BYTE* ptr)
{
if (*ptr == 0xE9)
{
return (ptr + 5) + (*(UINT32*)&ptr[1]);
}
return ptr;
}
static int _get_index(BYTE* ptr)
{
if (*(UINT16*)ptr == 0x20FF)
{
return 0;
}
if (*(UINT16*)ptr == 0x60FF)
{
return ptr[2] / sizeof(void*);
}
if (*(UINT16*)ptr == 0xA0FF)
{
return *(UINT32*)&ptr[2] / sizeof(void*);
}
return -1;
}
template<typename T>
static int GetVTableIndex(T funcaddr)
{
void* proc = (void*&)funcaddr;
BYTE* addr = _get_jmp_address((BYTE*)proc);
for (int i = 0; i < 32; i++)
{
if (addr[i] == 0xFF)
{
auto dx = _get_index(&addr[i]);
if (dx >= 0) return dx;
}
}
return -1;
}
static POINT GetMousePos(HWND Hwnd)
{
POINT p;
GetCursorPos(&p);
ScreenToClient(Hwnd, &p);
return p;
}
static bool InRect(POINT point, POINT LOC, SIZE SIZ)
{
int xf = point.x - LOC.x;
int yf = point.y - LOC.y;
return xf >= 0 && xf <= SIZ.cx &&
yf >= 0 && yf <= SIZ.cy;
}