C/C++ 外部特征码寻址-hook终结者2过CRC检测
#include "Windows.h" #include "tlhelp32.h" #include "String.h" #include "Shlwapi.h" #include "iostream" using namespace std; HANDLE hProcess; LPVOID lp_address; LPVOID lp_ret_value_address; DWORD lp_ret_jmp; DWORD lp_to_jmp; template <typename T> T Read(LPVOID Address) { T Data; ReadProcessMemory(hProcess, (LPVOID)Address, &Data, sizeof(T), nullptr); return Data; } uintptr_t FindPattern(uintptr_t start, uintptr_t length, const unsigned char* pattern, const char* mask) { size_t pos = 0; auto maskLength = strlen(mask) - 1; auto startAdress = start; for (auto it = startAdress; it < startAdress + length; ++it) { if (Read<unsigned char>(LPVOID(it)) == pattern[pos] || mask[pos] == '?') { if (mask[pos + 1] == '\0') return it - maskLength; pos++; } else pos = 0; } return 0; } //特征码寻址 uintptr_t FindPattern(HMODULE hModule, const unsigned char* pattern, const char* mask) { IMAGE_DOS_HEADER DOSHeader = Read<IMAGE_DOS_HEADER>(hModule); IMAGE_NT_HEADERS NTHeaders = Read<IMAGE_NT_HEADERS>(LPVOID(uintptr_t(hModule) + DOSHeader.e_lfanew)); return FindPattern( reinterpret_cast<uintptr_t>(hModule) + NTHeaders.OptionalHeader.BaseOfCode, reinterpret_cast<uintptr_t>(hModule) + NTHeaders.OptionalHeader.SizeOfCode, pattern, mask); } HMODULE GetProcessModuleHandleByName(DWORD pid, LPCSTR ModuleName) { MODULEENTRY32 ModuleInfo; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); if (!hSnapshot) { return 0; } ZeroMemory(&ModuleInfo, sizeof(MODULEENTRY32)); ModuleInfo.dwSize = sizeof(MODULEENTRY32); if (!Module32First(hSnapshot, &ModuleInfo)) { return 0; } do { if (!lstrcmpi(ModuleInfo.szModule, ModuleName)) { CloseHandle(hSnapshot); return ModuleInfo.hModule; } } while (Module32Next(hSnapshot, &ModuleInfo)); CloseHandle(hSnapshot); return 0; } DWORD GetProcessIDByName(const char* pName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE == hSnapshot) { return NULL; } PROCESSENTRY32 pe = { sizeof(pe) }; for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) { if (strcmp(pe.szExeFile, pName) == 0) { CloseHandle(hSnapshot); return pe.th32ProcessID; } //printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile); } CloseHandle(hSnapshot); return 0; } //内联汇编被写入 inline __declspec(naked) void ret_hook() { __asm { mov edi,edi push ebp mov ebp,esp mov edx, edi } } int main() { SetConsoleTitleA("[Pass CRC ~《终结者2:审判日》 1.123311.297055 ] "); DWORD OldProtect = NULL; int Pid = GetProcessIDByName("zjz.exe"); hProcess = INVALID_HANDLE_VALUE; hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);//游戏进程句柄 cout << "进程ID:" << Pid << endl << endl << "进程句柄:" << hProcess << endl << endl; lp_address = VirtualAllocEx(hProcess, NULL, 128, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //cout << "分配的写入hook的地址:" << lp_address << hex << endl; //bcryptPrimitives.dll+24AFF - CC - int 3 HMODULE hbcryptPrimitives = GetProcessModuleHandleByName(Pid, "bcryptPrimitives.dll"); //这边自己搞检测地址 lp_ret_jmp = (DWORD)hbcryptPrimitives + 0x24B05; lp_to_jmp = (DWORD)hbcryptPrimitives + 0x24B00; //cout << "跳回的地址计算:" << lp_ret_jmp << endl; /*写ret hook*/ if (WriteProcessMemory(hProcess, lp_address, ret_hook, 50, NULL) != 0) { //cout << "写入成功!" << endl; BYTE jmp_e9 = { 0xe9 }; WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x7), (LPVOID)&jmp_e9, 1, NULL); int jmp_ret = (int)lp_ret_jmp - ((DWORD)lp_address + 0x7) - 5; WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x8), (LPVOID)&jmp_ret, 4, NULL); /*to hook*/ BYTE jmp_to_e9 = { 0xe9 }; WriteProcessMemory(hProcess, (LPVOID)lp_to_jmp, (LPVOID)&jmp_to_e9, 1, NULL); int jmp_to_hook = (int)lp_address - lp_to_jmp - 5; WriteProcessMemory(hProcess, (LPVOID)(lp_to_jmp + 0x1), (LPVOID)&jmp_to_hook, 4, NULL); } /*ret jmp*/ cout << "CRC检测已经成功过掉!请尽情开启功能玩耍!" << endl << endl; cout << "微信i-xiaodi 游戏逆向信息安全-xd团队" << endl << endl; cout << "网易云课堂搜索 “游戏逆向的故事” ,关注我们!了解更多内部视频产品!" << endl; getchar(); return 0; }
有同学问的特征码寻址,大致调用方法如下:
//uintptr_t Fnd = FindPattern(hModule, (const unsigned char*)"\x8B\xFF\x55\x8B\xEC\x81\xEC\xC4\x00\x00\x00\xA1",
//"xxxxxxxxxxxx");
关键字:“FindPattern”,外网有很多大佬写,不同的方式都可以,大家可以自己封装,上面代码为我自己封装的,可能会出现一些问题在所难免。
分类:
Code c/c++
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· “你见过凌晨四点的洛杉矶吗?”--《我们为什么要睡觉》
· 编程神器Trae:当我用上后,才知道自己的创造力被低估了多少
· C# 从零开始使用Layui.Wpf库开发WPF客户端
· C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
· 接口重试的7种常用方案!