#include "Utils.h" #include #include #include #include #include #include #include #include #include #include #pragma comment(lib, "Dbghelp.lib") #pragma comment(lib,"Wtsapi32.lib") #pragma warning(disable: 4267) #pragma warning(disable: 4244) #pragma warning(disable: 4018) DWORD NtBuildVersion() { static DWORD res = 0; if (!res) { typedef LONG(NTAPI* fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); fnRtlGetVersion pRtlGetVersion = NULL; while (pRtlGetVersion == 0) { HMODULE ntdll = GetModuleHandleA("ntdll.dll"); if (ntdll) { pRtlGetVersion = (fnRtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion"); } } RTL_OSVERSIONINFOW osversion{}; pRtlGetVersion(&osversion); res = osversion.dwBuildNumber; } return res; } std::vector ParserPattern(std::string text) { #define IS_HEX(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) #define HEX_TO_VALUE(c) (((c) >= '0' && (c) <= '9') ? (c) - '0' : ((c) >= 'a' && (c) <= 'f') ? (c) - 'a' + 10 : ((c) >= 'A' && (c) <= 'F') ? (c) - 'A' + 10 : 0) std::vector result; bool firstChar = TRUE; PATTERNVALUE val = { 0 }; for (char c : text) { if (IS_HEX(c)) { if (firstChar) { val.left = HEX_TO_VALUE(c); firstChar = FALSE; } else { val.right = HEX_TO_VALUE(c); result.push_back(val); val = { 0 }; firstChar = TRUE; } } else if (c == '?' || c == '*') { if (firstChar) { val.left = 0; val.ignore_left = 1; firstChar = FALSE; } else { val.right = 0; val.ignore_right = 1; result.push_back(val); val = { 0 }; firstChar = TRUE; } } else if (!firstChar && val.ignore_left) { val.right = 0; val.ignore_right = 1; result.push_back(val); val = { 0 }; firstChar = TRUE; } else { firstChar = TRUE; } } if (!firstChar && (val.left != 0 || val.ignore_left != 0)) { val.right = 0; val.ignore_right = 1; result.push_back(val); } #undef IS_HEX #undef HEX_TO_VALUE return result; } void* FindU64(const char* szModule, ULONG64 value) { MODULEINFO mi{ }; if (GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &mi, sizeof(mi))) { unsigned char* begin = (unsigned char*)mi.lpBaseOfDll; DWORD size = mi.SizeOfImage; for (unsigned char* p = begin; p <= (begin + size) - 8; p++) { if (*(ULONG64*)p == value) { return p; } } } return NULL; } void* FindPattern(const char* szModule, std::string sPattern, int offset) { std::vector pattern = ParserPattern(sPattern); if (pattern.size() == 0) return NULL; MODULEINFO mi{ }; if (GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &mi, sizeof(mi))) { unsigned char* begin = (unsigned char*)mi.lpBaseOfDll; DWORD size = mi.SizeOfImage; for (unsigned char* curr = begin + offset; curr <= (begin + size) - pattern.size(); curr++) { for (int i = 0; i < pattern.size(); i++) { if (pattern[i].ignore == 0x11) continue; if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt; if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt; } return curr; nxt:; } } return NULL; } std::vector FindAllPattern(const char* szModule, std::string sPattern, int offset) { std::vector result = std::vector(); std::vector pattern = ParserPattern(sPattern); if (pattern.size() == 0) return result; MODULEINFO mi{ }; HMODULE m = NULL; if (szModule) m = LoadLibraryA(szModule); else m = GetModuleHandle(NULL); if (!m) { printf("GetModule Infomation Failed!\n"); return result; } if (GetModuleInformation(GetCurrentProcess(), m, &mi, sizeof(mi))) { unsigned char* begin = (unsigned char*)mi.lpBaseOfDll; DWORD size = mi.SizeOfImage; for (unsigned char* curr = begin + offset; curr <= (begin + size) - pattern.size(); curr++) { for (int i = 0; i < pattern.size(); i++) { if (pattern[i].ignore == 0x11) continue; if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt; if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt; } result.push_back(curr); nxt:; } } else { printf("GetModule Infomation Failed!\n"); } return result; } void* FindPattern(void* _begin, std::string sPattern, int search_size, int offset) { std::vector pattern = ParserPattern(sPattern); if (pattern.size() == 0) return NULL; unsigned char* begin = (unsigned char*)_begin; for (unsigned char* curr = begin + offset; curr <= (begin + search_size) - pattern.size(); curr++) { for (int i = 0; i < pattern.size(); i++) { if (pattern[i].ignore == 0x11) continue; if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt; if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt; } return curr; nxt:; } return NULL; } std::vector FindAllPattern(void* _begin, std::string sPattern, int search_size, int offset) { std::vector result = std::vector(); std::vector pattern = ParserPattern(sPattern); if (pattern.size() == 0) return result; unsigned char* begin = (unsigned char*)_begin; for (unsigned char* curr = begin + offset; curr <= (begin + search_size) - pattern.size(); curr++) { for (int i = 0; i < pattern.size(); i++) { if (pattern[i].ignore == 0x11) continue; if (!pattern[i].ignore_left && ((curr[i] & 0xF0) >> 4) != pattern[i].left)goto nxt; if (!pattern[i].ignore_right && (curr[i] & 0x0F) != pattern[i].right)goto nxt; } result.push_back(curr); nxt:; } return result; } void PrintHex(void* ptr, int count, int splitLine) { const char keys[] = "0123456789ABCDEF"; uint8_t* tmp = (uint8_t*)ptr; for (uint8_t* b = tmp; b < tmp + count; b += splitLine) { for (int j = 0; j < splitLine && b + j < tmp + count; j++) { printf("%c%c ", keys[b[j] / 0x10], keys[b[j] % 0x10]); } printf("\n"); } } void PrintHex(void* ptr, int count) { const char keys[] = "0123456789ABCDEF"; uint8_t* tmp = (uint8_t*)ptr; for (uint8_t* b = tmp; b < tmp + count; b++) { printf("%c%c ", keys[*b / 0x10], keys[*b % 0x10]); } } void MakePermute(std::vector nums, std::vector>& result, int start) { if (start == nums.size() - 1) { result.push_back(nums); return; } for (int i = start; i < nums.size(); i++) { std::swap(nums[start], nums[i]); MakePermute(nums, result, start + 1); std::swap(nums[start], nums[i]); } } std::wstring GetErrorMessage(DWORD err) { LPWSTR errorMsgBuffer = NULL; DWORD size = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, (LPWSTR)&errorMsgBuffer, 0, nullptr ); if (size > 0) { std::wstring emsg = std::wstring(errorMsgBuffer); LocalFree(errorMsgBuffer); return emsg; } return L"Unknown error"; } PIMAGE_NT_HEADERS RtlImageNtHeader(PVOID Base) { static PIMAGE_NT_HEADERS(*_RtlImageNtHeader)(PVOID Base) = NULL; if (_RtlImageNtHeader == NULL) { HMODULE NtBase = GetModuleHandleA("ntdll.dll"); _RtlImageNtHeader = (decltype(_RtlImageNtHeader))GetProcAddress(NtBase, "RtlImageNtHeader"); } return _RtlImageNtHeader(Base); } SIZE_T GetSectionSize(_In_ PVOID DllBase) { PIMAGE_NT_HEADERS pNTHeader = RtlImageNtHeader(DllBase); PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD64)pNTHeader + sizeof(IMAGE_NT_HEADERS64)); ULONG nAlign = pNTHeader->OptionalHeader.SectionAlignment; SIZE_T ImageSize = (pNTHeader->OptionalHeader.SizeOfHeaders + nAlign - 1) / nAlign * nAlign; for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; ++i) { int CodeSize = pSectionHeader[i].Misc.VirtualSize; int LoadSize = pSectionHeader[i].SizeOfRawData; int MaxSize = (LoadSize > CodeSize) ? (LoadSize) : (CodeSize); int SectionSize = (pSectionHeader[i].VirtualAddress + MaxSize + nAlign - 1) / nAlign * nAlign; if (ImageSize < SectionSize) ImageSize = SectionSize; } return ImageSize; } void EnableDump() { SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); SetUnhandledExceptionFilter([](EXCEPTION_POINTERS* exceptionInfo) -> LONG { char processPath[MAX_PATH]; GetModuleFileNameA(NULL, processPath, MAX_PATH); HANDLE hDumpFile = CreateFileA("crash_dump.dmp", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hDumpFile != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION dumpInfo; dumpInfo.ThreadId = GetCurrentThreadId(); dumpInfo.ExceptionPointers = exceptionInfo; dumpInfo.ClientPointers = TRUE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL); CloseHandle(hDumpFile); } return EXCEPTION_CONTINUE_SEARCH; }); } List CaptureStackTraceEx() { List result = List(); const int MAX_STACKTRACE = 64; void* stack[MAX_STACKTRACE] = {}; WORD numFrames = RtlCaptureStackBackTrace(0, MAX_STACKTRACE, stack, NULL); for (int i = 0; i < MAX_STACKTRACE; ++i) { DWORD64 address = reinterpret_cast(stack[i]); result.Add((void*)address); } return result; } #ifdef ZLIB_VERSION std::vector Compress(uint8_t* buffer, int len) { std::vector result = std::vector(); uLong destLen = compressBound(len); unsigned char* ostream = (unsigned char*)malloc(destLen); int res = compress(ostream, &destLen, (const unsigned char*)buffer, len); if (res == Z_BUF_ERROR) { return result; } if (res == Z_MEM_ERROR) { return result; } int ldx = result.size(); result.resize(destLen); memcpy(&result.operator[](ldx), ostream, destLen); return result; } std::vector Decompress(uint8_t* buffer, int len, int maxlen) { uLong destLen = maxlen; std::vector result = std::vector(); uint8_t* o2stream = new uint8_t[maxlen]; int des = uncompress(o2stream, &destLen, buffer, len); result.resize(destLen); memcpy(result.data(), o2stream, destLen); return result; } std::vector GDecompress(std::vector compressedBytes) { std::vector uncompressedBytes = std::vector(); if (compressedBytes.size() == 0)return uncompressedBytes; unsigned full_length = compressedBytes.size(); unsigned half_length = compressedBytes.size() / 2; unsigned uncompLength = full_length; char* uncomp = (char*)calloc(sizeof(char), uncompLength); z_stream strm; strm.next_in = (Bytef*)compressedBytes.data(); strm.avail_in = compressedBytes.size(); strm.total_out = 0; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; bool done = false; if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { free(uncomp); return uncompressedBytes; } while (!done) { if (strm.total_out >= uncompLength) { char* uncomp2 = (char*)calloc(sizeof(char), uncompLength + half_length); memcpy(uncomp2, uncomp, uncompLength); uncompLength += half_length; free(uncomp); uncomp = uncomp2; } strm.next_out = (Bytef*)(uncomp + strm.total_out); strm.avail_out = uncompLength - strm.total_out; int err = inflate(&strm, Z_SYNC_FLUSH); if (err == Z_STREAM_END) done = true; else if (err != Z_OK) { break; } } if (inflateEnd(&strm) != Z_OK) { free(uncomp); return uncompressedBytes; } for (size_t i = 0; i < strm.total_out; ++i) { uncompressedBytes.push_back(uncomp[i]); } free(uncomp); return uncompressedBytes; } std::vector GCompress(std::vector input) { std::vector res = std::vector(); res.resize(input.size()); z_stream zs; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = (uInt)input.size(); zs.next_in = (Bytef*)input.data(); zs.avail_out = (uInt)input.size(); zs.next_out = (Bytef*)res.data(); deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); deflate(&zs, Z_FINISH); deflateEnd(&zs); res.resize(zs.total_out); return res; } std::vector GDecompress(uint8_t* compressedBytes, ULONG len) { std::vector uncompressedBytes = std::vector(); if (len == 0)return uncompressedBytes; unsigned full_length = len; unsigned half_length = len / 2; unsigned uncompLength = full_length; char* uncomp = (char*)calloc(sizeof(char), uncompLength); z_stream strm; strm.next_in = compressedBytes; strm.avail_in = len; strm.total_out = 0; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; bool done = false; if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { free(uncomp); return uncompressedBytes; } while (!done) { if (strm.total_out >= uncompLength) { char* uncomp2 = (char*)calloc(sizeof(char), uncompLength + half_length); memcpy(uncomp2, uncomp, uncompLength); uncompLength += half_length; free(uncomp); uncomp = uncomp2; } strm.next_out = (Bytef*)(uncomp + strm.total_out); strm.avail_out = uncompLength - strm.total_out; int err = inflate(&strm, Z_SYNC_FLUSH); if (err == Z_STREAM_END) done = true; else if (err != Z_OK) { break; } } if (inflateEnd(&strm) != Z_OK) { free(uncomp); return uncompressedBytes; } for (size_t i = 0; i < strm.total_out; ++i) { uncompressedBytes.push_back(uncomp[i]); } free(uncomp); return uncompressedBytes; } std::vector GCompress(uint8_t* input, ULONG len) { std::vector res = std::vector(); res.resize(len); z_stream zs; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = (uInt)len; zs.next_in = (Bytef*)input; zs.avail_out = (uInt)len; zs.next_out = (Bytef*)res.data(); deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); deflate(&zs, Z_FINISH); deflateEnd(&zs); res.resize(zs.total_out); return res; } std::vector GCompress(std::initializer_list input) { return GCompress((uint8_t*)input.begin(), input.size()); } std::vector GCompress(std::initializer_list* input) { return GCompress((uint8_t*)input->begin(), input->size()); } std::string MakeDialogFilterStrring(std::string description, std::vector filter) { std::string result = description; result.append("("); for (auto& str : filter) { result.append(str); result.append(";"); } result.append(")"); result.append(1, '\0'); for (auto& str : filter) { result.append(str); result.append(";"); } result.append(2, '\0'); return result; } std::string MakeDialogFilterStrring(std::string description, std::string filter) { std::string result = description; result.append("("); result.append(filter); result.append(")"); result.append(1, '\0'); result.append(filter); result.append(2, '\0'); return result; } #endif