564 lines
12 KiB
C++
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;
|
|
}
|
|
|