CS起源pointermap找基址+工具函数测试
這是我的愛好,但我不會(huì)用這些技術(shù)做越界的事情,希望您也是。
這是我的愛好,但我不會(huì)用這些技術(shù)做越界的事情,希望您也是。
這是我的愛好,但我不會(huì)用這些技術(shù)做越界的事情,希望您也是。
一、MemHackLib庫(kù)
參考casuallibrary項(xiàng)目,整了個(gè)閹割版,刪掉了我不會(huì)的C++語法,只保留了vector和模板函數(shù),這兩個(gè)工具還是很實(shí)用的。這個(gè)庫(kù)剛開始整,只有外部讀寫內(nèi)存的功能,以后慢慢加。
主函數(shù)
這里演示了庫(kù)的基本功能,獲取玩家基址,然后鎖血1000.其實(shí)庫(kù)的功能差不多就這些了,后期會(huì)加入AOB掃描的功能,然后適配一下64位,也沒什么別的了。
MemHackLib.hpp
#pragma once/* * 參考項(xiàng)目:https://github.com/CasualCoder91/CasualLibrary * 日期:2021年8月21日 * 作者:hambaga * * 我編寫這個(gè)庫(kù)時(shí)會(huì)兼容多字節(jié)字符集和Unicode字符集;也嘗試兼容64位,但沒有測(cè)試過,以后用這個(gè)庫(kù)開發(fā)64位外掛時(shí)會(huì)完善的。 * */#include <Windows.h> #include <iostream> #include <stdio.h> #include <TlHelp32.h> #include <tchar.h> #include <vector>// ---------------------------------------------------------------------------------------------------------------- // External hack, just use this api in a external program... // ----------------------------------------------------------------------------------------------------------------// Open process and return pid BOOL OpenProcessWithName(const TCHAR* ProcessName, HANDLE* Process, DWORD* Pid) {HANDLE hSnapshot;hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hSnapshot){std::cerr << "CreateToolhelp32Snapshot failed, error code: " << GetLastError() << "\n";return FALSE;}PROCESSENTRY32 process;process.dwSize = sizeof(PROCESSENTRY32);BOOL first = Process32First(hSnapshot, &process);while (first){if (!_tcscmp(ProcessName, process.szExeFile)){*Process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);if (*Process != NULL){*Pid = process.th32ProcessID;return TRUE;}}first = Process32Next(hSnapshot, &process);}CloseHandle(hSnapshot);return FALSE; }// Get a dll address or main exe address. HMODULE GetModuleBase(const TCHAR* ModuleName, DWORD Pid) {HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, Pid);MODULEENTRY32 ModuleEntry;ModuleEntry.dwSize = sizeof(ModuleEntry);do{if (!_tcscmp(ModuleName, ModuleEntry.szModule)){CloseHandle(hSnapshot);return ModuleEntry.hModule;}} while (Module32Next(hSnapshot, &ModuleEntry));return NULL; }// Get an object address by specify some offsets. uintptr_t GetObjectAddress(HANDLE ProcessHandle, uintptr_t Address, const std::vector<uintptr_t>& Offsets) {for (size_t i = 0; i < Offsets.size(); i++){if (!ReadProcessMemory(ProcessHandle, (BYTE*)Address, &Address, sizeof(Address), NULL)){std::cerr << "ReadProcessMemory failed at reading " << std::hex << Address << "\n";}Address += Offsets[i];}return Address; }template <typename T> BOOL ExternalRead(HANDLE ProcessHandle, const uintptr_t& Address, BOOL ReadableCheck, T *ReadData) {if (ReadableCheck){MEMORY_BASIC_INFORMATION mbi;VirtualQueryEx(ProcessHandle, (LPCVOID)Address, &mbi, sizeof(mbi));if (!(mbi.State & MEM_COMMIT)){return FALSE;}} ReadProcessMemory(ProcessHandle, (LPBYTE)Address, ReadData, sizeof(T), NULL);return TRUE; }template <typename T> BOOL ExternalWrite(HANDLE ProcessHandle, const uintptr_t& Address, BOOL WritableCheck, T WriteData) {if (WritableCheck){MEMORY_BASIC_INFORMATION mbi;VirtualQueryEx(ProcessHandle, (LPCVOID)Address, &mbi, sizeof(mbi));if (!(mbi.State & MEM_COMMIT)){return FALSE;}if (mbi.Protect & (PAGE_GUARD | PAGE_NOCACHE | PAGE_NOACCESS | PAGE_READONLY)){if (!VirtualProtectEx(ProcessHandle, mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect)) {return FALSE;}WriteProcessMemory(ProcessHandle, (LPBYTE*)Address, &WriteData, sizeof(T), NULL);DWORD dwOldProtect;VirtualProtectEx(ProcessHandle, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect);return TRUE;}}WriteProcessMemory(ProcessHandle, (LPBYTE)Address, &WriteData, sizeof(T), NULL);return TRUE; }// ---------------------------------------------------------------------------------------------------------------- // Internal hack, just use this api in a dll, and use some other tool to inject this dll into the game... // ----------------------------------------------------------------------------------------------------------------二、如何使用 pointermap 找玩家基址
如果您不知道什么是 指針掃描 ,建議您先看一下CE教程,把CE內(nèi)置的教程過一遍。pointermap我的理解是把多個(gè)指針掃描的結(jié)果放在一起比較,原理不清楚,反正效果就是篩選過程比普通指針掃描更快,搜出來的結(jié)果更少。下面演示一下CS起源怎么找基址,我這里用的是steam的CS起源,估計(jì)和破解版也沒什么區(qū)別。
2-1 找血量
只要找到血量,看看誰訪問/修改了血量,根據(jù)指令的偏移,就能找到玩家基址。開一局游戲吧:
找到十幾個(gè)地址,其中只有一個(gè)是真正的血量:
全部拉下來,用二分法修改+鎖定:
我這里將下半?yún)^(qū)這幾個(gè)鎖定成1000,如果我無敵了,說明真正的血量就是這里邊其中一個(gè),那么上半?yún)^(qū)的就可以刪掉了;否則,真正的血量就在上半?yún)^(qū),那么把下半?yún)^(qū)刪掉。重復(fù)這個(gè)步驟,可以快速找到真正的血量地址:
2-2 查偏移
看看誰訪問了血量:
如果你附加進(jìn)程CE崩潰了,只需設(shè)置一下使用VEH調(diào)試器即可:
現(xiàn)在我們知道血量的偏移是E4,那么玩家地址就是-E4,但是先不急,我們要找基址。待會(huì)再用這個(gè)E4。
2-3 生成 pointermap
找到血量后,右鍵生成pointermap:
生成pointermap1后,指針掃描:
選擇 use pointer map,使用剛才生成的pointermap1:
指定一下最后一個(gè)偏移 E4
選擇PTR文件保存路徑后,開始掃描
第一次掃描結(jié)束,重啟游戲,CE不關(guān)。
第二次啟動(dòng)游戲,用二分法找到血量。
生成pointermap :
第二次指針掃描,有幾個(gè)地方要設(shè)置,首先要使用剛才生成的pointermap2,然后勾選compare result,與上次游戲的pointermap1對(duì)比,設(shè)置地址為上次游戲的血量地址,然后開始掃描:
得到了18000個(gè)結(jié)果,第一次是16萬個(gè):
再來一次,重啟游戲,找到血量:
生成pointermap3:
指針掃描,使用pointermap3,和前兩個(gè)pointermap對(duì)比:
開始掃描:
得到了13000個(gè)結(jié)果:
似乎再重復(fù)也沒什么大變化了,找?guī)讉€(gè)偏移少的試試:
只要找到一個(gè)可以用的就行了,結(jié)果越少越準(zhǔn)確。
總結(jié)
以上是生活随笔為你收集整理的CS起源pointermap找基址+工具函数测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bat脚本+vs2019编译openss
- 下一篇: 使用 rsync / scp 命令下载l