#pragma once // #include // #include // #include #include // #include // #include // #include #include // #include // #include // #include #include // enum EPagePermissions // { // Execute = PAGE_EXECUTE, // ExecuteRead = PAGE_EXECUTE_READ, // ExecuteReadWrite = PAGE_EXECUTE_READWRITE, // ExecuteWriteCopy = PAGE_EXECUTE_WRITECOPY, // Read = PAGE_READONLY, // ReadWrite = PAGE_READWRITE, // WriteCopy = PAGE_WRITECOPY, // WriteCombine = PAGE_WRITECOMBINE // }; // struct PatternInfo // { // const char *Pattern; // EPagePermissions Permissions; // }; namespace PatternScan { // struct PatternByte // { // struct PatternNibble // { // unsigned char data; // bool wildcard; // } nibble[2]; // }; // static std::string formathexpattern(std::string patterntext) // { // std::string result; // int len = patterntext.length(); // for (int i = 0; i < len; i++) // if (patterntext[i] == '?' || isxdigit(patterntext[i])) // result += toupper(patterntext[i]); // return result; // } // static int hexchtoint(char ch) // { // if (ch >= '0' && ch <= '9') // return ch - '0'; // else if (ch >= 'A' && ch <= 'F') // return ch - 'A' + 10; // else if (ch >= 'a' && ch <= 'f') // return ch - 'a' + 10; // return 0; // } // static bool patterntransform(std::string patterntext, std::vector &pattern) // { // pattern.clear(); // patterntext = formathexpattern(patterntext); // int len = patterntext.length(); // if (!len) // return false; // if (len % 2) //not a multiple of 2 // { // patterntext += '?'; // len++; // } // PatternByte newByte; // for (int i = 0, j = 0; i < len; i++) // { // if (patterntext[i] == '?') //wildcard // { // newByte.nibble[j].wildcard = true; //match anything // } // else //hex // { // newByte.nibble[j].wildcard = false; // newByte.nibble[j].data = hexchtoint(patterntext[i]) & 0xF; // } // j++; // if (j == 2) //two nibbles = one byte // { // j = 0; // pattern.push_back(newByte); // } // } // return true; // } // static bool patternmatchbyte(unsigned char byte, const PatternByte &pbyte) // { // int matched = 0; // unsigned char n1 = (byte >> 4) & 0xF; // if (pbyte.nibble[0].wildcard) // matched++; // else if (pbyte.nibble[0].data == n1) // matched++; // unsigned char n2 = byte & 0xF; // if (pbyte.nibble[1].wildcard) // matched++; // else if (pbyte.nibble[1].data == n2) // matched++; // return (matched == 2); // } // size_t patternfind(std::string pattern, int offset) // { // std::vector searchpattern; // std::string::iterator end_pos = std::remove(pattern.begin(), pattern.end(), ' '); // pattern.erase(end_pos, pattern.end()); // SYSTEM_INFO sysinf; // GetSystemInfo(&sysinf); // DWORD startAddress = (DWORD)sysinf.lpMinimumApplicationAddress; // unsigned char *data = (unsigned char *)startAddress; // //MEMORY_BASIC_INFORMATION mbi; // if (!patterntransform(pattern.c_str(), searchpattern)) // return (size_t)-1; // //#define MEMORY_READABLE (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE) // //#define MEMORY_WRITABLE (PAGE_READWRITE | PAGE_EXECUTE_READWRITE) // //#define MEMORY_EXECUTABLE (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE) // size_t searchpatternsize = searchpattern.size(); // for (size_t i = 0, pos = 0; i < 0x7FFFFFFF; i++) //search for the pattern // { // //if (VirtualQuery((LPVOID)i, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0 // // && ((mbi.State != MEM_COMMIT) || !(mbi.Protect & MEMORY_READABLE) || (mbi.Protect & PAGE_GUARD))) // // //&& mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD)) // //{ // if (patternmatchbyte(data[i], searchpattern.at(pos))) //check if our pattern matches the current byte // { // pos++; // if (pos == searchpatternsize) //everything matched // { // if (offset >= 0) // return startAddress + i - searchpatternsize + 1 + offset; // if (offset < 0) // return startAddress + i - searchpatternsize + 1 - offset; // } // } // else if (pos > 0) //fix by Computer_Angel // { // i -= pos; // pos = 0; //reset current pattern position // } // /*} // else // i += mbi.RegionSize;*/ // } // return (size_t)-1; // } // // Find all occurences of the Pattern until a wildcard is hit // std::vector FindAllOccurences(std::vector pattern, std::vector streamToSearch) // { // std::vector positions; // // Length of the pattern to look for // unsigned int patternLength = pattern.size(); // // Total length of file to look through // unsigned int totalLength = streamToSearch.size(); // // First Byte of the pattern to look for // //unsigned char* firstMatchByte; // auto firstMatchByte = std::strtol(reinterpret_cast(pattern[0]), nullptr, 16); // std::vector parsedPattern; // parsedPattern.reserve(pattern.size()); // for (auto &pat : pattern) // { // parsedPattern.push_back((unsigned char)std::strtoul(reinterpret_cast(pat), nullptr, 16)); // } // for (unsigned int i = 0; i < totalLength; i++) // { // //auto cmp = (unsigned char)streamToSearch[i]; // //auto cmp2 = (unsigned char)firstMatchByte; // //auto cmp2 = std::strtol(reinterpret_cast(streamToSearch.data()[i]), nullptr, 16); // //auto second = streamToSearch; // //memcpy(&firstMatchByte, streamToSearch[i], sizeof (unsigned char*)); // // If the first Byte of the Searchpattern is at the current location of i // // and the totalLength - i is greater or equal to the pattern length // //if(i == 0x00000000000dca41) // //{ // //Q_ASSERT(false); // //} // if ((unsigned char)streamToSearch[i] == firstMatchByte && totalLength - i >= patternLength) // //if (pattern.data()[0] == *(streamToSearch.begin() +i) && totalLength - i >= patternLength) // { // std::vector match; //[patternLength]; // match.resize(patternLength); // memcpy(&match[0], &streamToSearch[i], patternLength); // // If the current range of the search matches the searchPattern // // add the current position(i) to the positionList and break // if (memcmp(match.data(), parsedPattern.data(), patternLength) == 0) // { // positions.push_back(static_cast(i)); // } // else // { // memset(&match, 0, patternLength); // } // } // } // return positions; // } // // Find all occurences of the Pattern until a wildcard is hit // std::vector FindAllOccurences(std::vector pattern, uintptr_t startAddress, uintptr_t totalSize = 0x7FFFFFFF) // { // std::vector positions; // // Length of the pattern to look for // unsigned int patternLength = pattern.size(); // // Total length of file to look through // unsigned int totalLength = totalSize - startAddress; // // First Byte of the pattern to look for // //unsigned char* firstMatchByte; // auto firstMatchByte = std::strtol(reinterpret_cast(pattern[0]), nullptr, 16); // std::vector parsedPattern; // parsedPattern.reserve(pattern.size()); // for (auto &pat : pattern) // { // parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast(pat), nullptr, 16)); // } // for (unsigned int i = 0; i < totalLength; i++) // { // if ((*(PBYTE)startAddress + i) == firstMatchByte && totalLength - i >= patternLength) // { // std::vector match; //[patternLength]; // match.resize(patternLength); // memcpy(&match[0], (LPVOID)(*(PBYTE)startAddress + i), patternLength); // // If the current range of the search matches the searchPattern // // add the current position(i) to the positionList and break // if (memcmp(match.data(), parsedPattern.data(), patternLength) == 0) // { // positions.push_back(static_cast(i)); // } // else // { // memset(&match, 0, patternLength); // } // } // } // return positions; // } // // Search the given Pattern iconst n the given& char-vector // uintptr_t SearchBytePattern(const std::string &pattern, std::vector streamToSearch, int offset) // { // std::istringstream buf(pattern); // std::istream_iterator beg(buf), end; // std::vector tokens(beg, end); // std::vector patternArray; // patternArray.reserve(tokens.size()); // for (auto &data : tokens) // { // patternArray.push_back(_strdup(data.c_str())); // } // std::vector temp; // for (unsigned int i = 0; i < tokens.size(); i++) // { // // Using QString for the "startsWith function // // auto value = QString(patternArray[i]); // // if(!value.startsWith('?', Qt::CaseInsensitive)) // auto value = std::string(patternArray[i]); // if (!_strnicmp(value.c_str(), "?", sizeof("?"))) // { // temp.push_back(patternArray[i]); // } // else // break; // } // auto occurences = FindAllOccurences(temp, streamToSearch); // std::vector parsedPattern; // parsedPattern.reserve(patternArray.size()); // for (auto &pat : patternArray) // { // parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast(pat), nullptr, 16)); // } // std::vector check(patternArray.size()); // for (auto &occ : occurences) // { // memset(check.data(), 0, patternArray.size()); // memcpy(check.data(), &streamToSearch[occ], patternArray.size()); // for (unsigned int o = 0; o < patternArray.size(); o++) // { // // If the current Patterncharacter is a wildcard, go to next index // if (isalnum(*patternArray[o]) == 0) // == 0 || isalpha(*patternArray[0]) == 0) // continue; // // Convert current Patternindex // char pat = (char)std::stoul(std::string(patternArray[o]), nullptr, 16); // // Compare memory, if equal, result is 0 // int mem = memcmp(&check[o], &pat, 1); // // If memory is not equal, the pattern doesn't match // if (mem != 0) // { // break; // } // // o can only be the size of the pattern if it matches // if (o == patternArray.size() - 1) // { // if (offset < 0) // return occ - offset; // if (offset > 0) // return occ + offset; // return occ; // } // } // } // // No result found // return 0; // } // uintptr_t SearchBytePattern(uintptr_t startAddress, uintptr_t fileSize, const std::string &pattern, int offset) // { // MODULEINFO miInfos = {NULL}; // HMODULE hmModule = GetModuleHandle(NULL); // if (hmModule) // { // GetModuleInformation(GetCurrentProcess(), hmModule, &miInfos, sizeof(MODULEINFO)); // } // std::istringstream buf(pattern); // std::istream_iterator beg(buf), end; // std::vector tokens(beg, end); // std::vector patternArray; // patternArray.reserve(tokens.size()); // for (auto &data : tokens) // { // patternArray.push_back(_strdup(data.c_str())); // } // std::vector temp; // for (unsigned int i = 0; i < tokens.size(); i++) // { // // Using QString for the "startsWith function // auto value = std::string(patternArray[i]); // if (_strnicmp(value.c_str(), "?", sizeof("?"))) // { // temp.push_back(patternArray[i]); // } // else // break; // } // auto occurences = FindAllOccurences(temp, startAddress); // std::vector parsedPattern; // parsedPattern.reserve(patternArray.size()); // for (auto &pat : patternArray) // { // parsedPattern.push_back((unsigned char)std::strtol(reinterpret_cast(pat), nullptr, 16)); // } // std::vector check(patternArray.size()); // for (auto &occ : occurences) // { // memset(check.data(), 0, patternArray.size()); // memcpy(check.data(), (LPVOID)(startAddress + occ), patternArray.size()); // for (unsigned int o = 0; o < patternArray.size(); o++) // { // // If the current Patterncharacter is a wildcard, go to next index // if (isalnum(*patternArray[o]) == 0) // == 0 || isalpha(*patternArray[0]) == 0) // continue; // // Convert current Patternindex // char pat = (char)std::stoul(std::string(patternArray[o]), nullptr, 16); // // Compare memory, if equal, result is 0 // int mem = memcmp(&check[o], &pat, 1); // // If memory is not equal, the pattern doesn't match // if (mem != 0) // { // break; // } // // o can only be the size of the pattern if it matches // if (o == patternArray.size() - 1) // { // if (offset < 0) // return occ - offset; // if (offset > 0) // return occ + offset; // return occ; // } // } // } // // No result found // return 0; // } // /** // * \brief Returns first occurrence of byte pattern in a module // * \param module Base address of module // * \param signature IDA-style byte pattern // * \return Pointer to first occurrence // * \see CSGOSimple by MarkHC // */ // inline std::uint8_t *patternScan(void *module, std::string signature) // { // static auto pattern_to_byte = [](const char *pattern) { // auto bytes = std::vector{}; // auto start = const_cast(pattern); // auto end = const_cast(pattern) + strlen(pattern); // for (auto current = start; current < end; ++current) // { // if (*current == '??') // { // ++current; // if (*current == '??') // ++current; // bytes.push_back(-1); // } // else // bytes.push_back(strtoul(current, ¤t, 16)); // } // return bytes; // }; // auto dosHeader = (PIMAGE_DOS_HEADER)module; // auto ntHeaders = (PIMAGE_NT_HEADERS)((std::uint8_t *)module + dosHeader->e_lfanew); // auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage; // auto patternBytes = pattern_to_byte(signature.c_str()); // auto scanBytes = reinterpret_cast(module); // auto s = patternBytes.size(); // auto d = patternBytes.data(); // for (auto i = 0ul; i < sizeOfImage - s; ++i) // { // bool found = true; // for (auto j = 0ul; j < s; ++j) // { // if (scanBytes[i + j] != d[j] && d[j] != -1) // { // found = false; // break; // } // } // if (found) // return &scanBytes[i]; // } // return nullptr; // } // static std::vector ParseSignature(std::string &pattern) // { // std::vector bytes; // for (unsigned int i = 0; i < pattern.length(); i += 2) // { // std::string byteString = pattern.substr(i, 2); // char byte = (char)strtol(byteString.c_str(), NULL, 16); // bytes.push_back(byte); // } // return bytes; // } // static DWORD FindMySignature(const char *szModule, std::string szSignature, int offset) // { // /*AllocConsole(); // freopen("CONIN$", "r", stdin); // freopen("CONOUT$", "w", stdout); // freopen("CONOUT$", "w", stderr);*/ // MODULEINFO modInfo; // GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &modInfo, sizeof(MODULEINFO)); // DWORD startAddress = (DWORD)modInfo.lpBaseOfDll; // DWORD endAddress = startAddress + modInfo.SizeOfImage; // std::string pattern = szSignature; // std::string::iterator end_pos = std::remove(szSignature.begin(), szSignature.end(), ' '); // szSignature.erase(end_pos, szSignature.end()); // //const char* pat = szSignature.c_str(); // auto pat = ParseSignature(szSignature); // DWORD firstMatch = 0; // //std::vector check(sizeof(szSignature)); // //auto firstMatchByte = std::strtol(&pat[0], nullptr, 16); // auto firstMatchByte = (int)pat[0]; // std::cout << std::hex << (int)*(unsigned char *)startAddress << '\n'; // std::cout << "Pattern to search for: " << szSignature << '\n'; // std::cout << "Length of Pattern: " << szSignature.length() << '\n'; // std::cout << "FirstMatchByte: " << std::hex << firstMatchByte << '\n'; // SYSTEM_INFO sysinf; // GetSystemInfo(&sysinf); // MEMORY_BASIC_INFORMATION mbi; // //startAddress += 0x4F318C; // /*for (int i = 0; i < pat.size(); i++) // std::cout << (int)pat[i];*/ // for (DWORD pCur = startAddress; pCur < 0x7FFFFFFF; pCur++) // { // if (VirtualQuery((LPVOID)pCur, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0 // //&& ((mBI.State != MEM_COMMIT) || !(mBI.Protect & MEMORY_READABLE) || (mBI.Protect & PAGE_GUARD))) // && mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD)) // { // //CREDITS: learn_more // #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])) // const char *patt = pattern.c_str(); // if (!*patt) // return firstMatch; // if (*(PBYTE)patt == '\?' || *(BYTE *)pCur == getByte(patt)) // { // if (!firstMatch) // firstMatch = pCur; // if (!patt[2]) // return firstMatch; // if (*(PWORD)patt == '\?\?' || *(PBYTE)patt != '\?') // patt += 3; // else // patt += 2; //one ? // } // else // { // patt = szSignature.c_str(); // firstMatch = 0; // } // if ((int)*(unsigned char *)pCur == (int)firstMatchByte && endAddress - pCur >= szSignature.length()) // { // //if (pattern.data()[0] == *(streamToSearch.begin() +i) && totalLength - i >= patternLength) // for (unsigned int o = 0; o < pat.size(); o++) // { // // If the current Patterncharacter is a wildcard, go to next index // //if (isalnum(szSignature[o]) == 0)// == 0 || isalpha(*patternArray[0]) == 0) // if (pat[o] == strtol("??", 0, 16)) // { // //std::cout << "Current Patternindex is a wildcard: " << pat[o] << '\n'; // continue; // } // auto currentPat = (int)pat[o]; // /*std::cout << '\n\n'; // std::cout << "Startaddress: 0x" << std::hex << (DWORD)modInfo.lpBaseOfDll << '\n'; // std::cout << "Currentaddress: 0x" << std::hex << pCur + o << '\n'; // std::cout << "Current Byte is: " << std::hex << (int)*(unsigned char*)(pCur + o) << '\n'; // std::cout << "Current Pattern is: " << std::hex << currentPat << '\n'; // std::cout << '\n';*/ // if ((int)*(unsigned char *)(pCur + o) != currentPat) // { // //std::cout << "Cur Val: 0x" << std::hex << (int)*(unsigned char*)(pCur + o) << " Pattern: 0x" << std::hex << currentPat << '\n'; // break; // } // // o can only be the size of the pattern if it matches // if (o == pat.size() - 1) // { // if (offset < 0) // return pCur - offset; // if (offset > 0) // return pCur + offset; // return pCur; // } // } // } // } // else // pCur += mbi.RegionSize; // } // return NULL; // } static uintptr_t FindSignature(const char *szModule, const char *szSignature) { //CREDITS: learn_more #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])) MODULEINFO modInfo; GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(szModule), &modInfo, sizeof(MODULEINFO)); uintptr_t startAddress = (uintptr_t)modInfo.lpBaseOfDll; uintptr_t endAddress = startAddress + modInfo.SizeOfImage; const char *pat = szSignature; uintptr_t firstMatch = 0; for (uintptr_t pCur = startAddress; pCur < endAddress; pCur++) { if (!*pat) return firstMatch; if (*(PBYTE)pat == '\?' || *(BYTE *)pCur == getByte(pat)) { if (!firstMatch) firstMatch = pCur; if (!pat[2]) return firstMatch; if (*(PWORD)pat == '\?\?' || *(PBYTE)pat != '\?') //if (*(PWORD)pat == '\?' || *(PBYTE)pat != '\?') pat += 3; else pat += 2; //one ? } else { pat = szSignature; firstMatch = 0; } } return 0; } } // namespace PatternScan