gshzhsheng 发表于 2020-3-18 19:04

[External Trainer] 外部工具实现原理 太吾绘卷工具 + 源码

本帖最后由 gshzhsheng 于 2020-3-18 19:10 编辑

所谓 External Trainer, 就是我们的工具和游戏不在一个进程,需要进行跨进程修改。

Windows为我们提供了一系列的 External 类 API,我们可以在MSDN中搜索带有Ex的API:



我们可以看到很多External 跨进程的函数。这些我们都可以进行利用,进行跨进程创建,访问,或者读写。

还有几个比较经典的 跨进程 External 访问内存的函数是 CreateRemoteThread, ReadMemoryProcess, WriteMemoryProcess .....

下面以 寻找 太吾绘卷 的基址 作为例子

我已经找到天数的偏移为:
```
std::vector<DWORD> daysOffset = { 0x004A2308, 0x210, 0x170, 0x60, 0x38,0x8, 0x10, 0x8EC};
```
模块为: mono-2.0-bdwgc.dll

首先我们需要找到模块地址
```
ULONGLONG getModuleBaseAddr(TCHAR* name, DWORD pid) {

      HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid); //扫描游戏进程的所有模块

      if (hSnap == INVALID_HANDLE_VALUE)//扫描失败,退出
      {
                DWORD error = GetLastError();
                return NULL;
      }

      MODULEENTRY32 me;
      me.dwSize = sizeof(MODULEENTRY32);

      if (Module32First(hSnap, &me))
      {
                do
                {
                        if (_tcscmp(me.szModule, name) == 0)// 如果找到了我们需要的模块
                        {
                              CloseHandle(hSnap);
                              return (ULONGLONG)(me.modBaseAddr); // 返回此模块地址
                        }
                } while (Module32Next(hSnap, &me));
      }
}
```

接着我们需要通过找到的模块地址和偏移找到天数的地址:
```
ULONGLONG getFinalAddddy(std::vector<DWORD> offsetVector, ULONGLONG BaseAddr, HANDLE hProcess)
{
      DWORD offsetNum = offsetVector.size();// 获取偏移的数量

      ULONGLONG myAddy = BaseAddr;

      for (int i = 0; i < offsetNum - 1; i++)
      {
                ReadProcessMemory(hProcess, LPCVOID(myAddy + offsetVector), &myAddy, sizeof(ULONGLONG), NULL);// 遍历偏移地址
      }

      myAddy += offsetVector;

      return myAddy;
}
```

寻找天数最终的地址:
```
std::vector<DWORD> daysOffset = { 0x004A2308, 0x210, 0x170, 0x60, 0x38,0x8, 0x10, 0x8EC}; // 天数偏移

ULONGLONG bdwgcModuleBaseAddr = getModuleBaseAddr((TCHAR*)(TEXT("mono-2.0-bdwgc.dll")), processId); // 模块地址

ULONGLONG dayAddress = getFinalAddddy(daysOffset, bdwgcModuleBaseAddr, hProcess); // 天数最终地址
```

寻找到最终天数地址我们就可以使用WriteMemoryProcess(),ReadMemoryProcess()进行读写

External Trainer 修改游戏进程的流程如下:



工具雏形:



** 源码地址: **
https://github.com/absolutelycold/TaiWuWarrior

proc.h 解释
```
DWORD getPIDByName(TCHAR* name); // 通过进程名获取Process ID
HANDLE getProcessHandle(DWORD pid); // 通过 pid 获取进程句柄
ULONGLONG getModuleBaseAddr(TCHAR* name, DWORD pid); // 获取模块地址
ULONGLONG getFinalAddddy(std::vector<DWORD> offsetVector, ULONGLONG BaseAddr, HANDLE hProcess); // 通过偏移寻找地址
BOOL writeToMemoryInt(HANDLE hProcess, ULONGLONG addr, DWORD value); // 写入目标进程指定地址 4 字节大小的数据
DWORD readMemoryInt(HANDLE hProcess, ULONGLONG addr); // 读取目标进程指定地址 4 字节大小地址
```

cxh9588 发表于 2020-3-18 19:13

谢谢啦,要研究一下。

sq178178 发表于 2020-3-18 20:11

空上加好的了,绡

lolp2012 发表于 2020-8-10 01:22

谢谢大佬

Tony12589 发表于 2021-5-21 08:57

这游戏如果用作弊器一点意思也没得

sam喵喵 发表于 2021-5-21 15:34

感谢分享,最近刚好在研究内核,可以好好学习下API用法。
请教下大佬,现在游戏都不做内存地址读写保护的吗,如果有保护的一般怎么弄
页: [1]
查看完整版本: [External Trainer] 外部工具实现原理 太吾绘卷工具 + 源码