如何从字节码中获取指针

逆向工程 拆卸 部件 指针
2021-06-14 12:32:59

当结构发生变化以更新内存结构偏移量时,当新版本出现时,我一直在对游戏进行指针扫描。我决定尝试使用签名扫描来尝试使我的偏移量更耐更改。

当前游戏版本中的指针扫描时 0x1034EF8 是我试图获得的偏移量。我附加了一个调试器和从这个地址读取的函数,并提出了一个独特的模式。当我进行模式扫描时,会发现并按预期返回此模式。

我遇到的问题是将这个汇编指令内存地址 461EE300 转换为这个偏移量 0x1034EF8。作弊引擎能够做这样的事情所以它一定是可能的,以下是从作弊引擎复制并粘贴的,它向我显示了 461EE300 地址的 game_x64.exe + 1034EF8。

如何将 461EE300 转换为 game_x64.exe + 1034EF8 并提取 1034EF8?

//90 - nop
//48 83 43 50 F8 - add qword ptr[rbx + 50],-08
//48 8B 0D 461EE300 - mov rcx,[game_x64.exe + 1034EF8]
//4C 8B 05 471EE300 - mov r8,[game_x64.exe + 1034F00]
//49 3B C8 - cmp rcx, r8
public static readonly Pattern MyPattern = new Pattern(new byte[]
{
0x90,
0x48, 0x83, 0x43, 0x50, 0xF8,
0x48, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00,
0x4C, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00,
0x49, 0x3B, 0xC8
}, "xxxxxxxxx????xxx????xxx");
3个回答

让我们看看 Cheat Engine 如何计算它的偏移量:

4C 8B 05 471EE300 翻译成 mov r8,QWORD PTR [rip+0xe31e47]

如您所见,该值取决于 rip(指令指针)。您可以在指令字节中看到偏移量的实际字节。由于 Cheat Engine 知道该指令在内存中的实际位置,因此它们使用图像基础作为相对偏移量。

所以他们可能会以这样的方式转换它:

(instruction_address - image_base + offset) + image_base = instruction_address + offset

那么 461EE300 是否等于可执行文件的基数 + 0x1034F00?

是的

它比你想象的要简单得多。461EE300 是变量的相对偏移量。需要将相对偏移量添加到 rip-register。并且您已经拥有 rip-register 的值。这是您找到的模式的地址。

因此,只需使用 461EE300 添加您的模式地址,您就拥有了您的变量。

经过更多的挖掘和使用 Nodwald 的一些新想法后,谢谢您,这是解决方案。

//Match the pattern finding its location relative to the module start address
var matches = MemoryTool.FindPatterns(MemoryTool.GetProcessId(), MemoryTool.Pattern);
Process proc = Process.GetProcessesByName("ProcessName")[0];
IntPtr startOffset = proc.MainModule.BaseAddress;
var processStart = startOffset.ToInt64(); ;
//use the match plus the offset to the memory location to read the address I was trying to translate
var memoryValueOffset = matches[0] + 9;
//Read the value of the memory address
var memoryValue = _poeInterface.Memory.ReadInt(processStart + memoryValueOffset);
//Find the offset memory address of the next assembly function
var nextInstructionOffset = matches[0] + 13;
//find the full address value of that address in memory
var nextAddressFull = nextInstructionOffset + processStart;
//add the next address full value to the relative offset address value from earlier
var nextAddressPlusOffset = nextAddressFull + memoryValue;
//Win... this is our offset in memory
var fullMemoryOffset = nextAddressPlusOffset;
//This is the origional offset we were looking for - 0x1034EF8
var relativeOffset = fullMemoryOffset - processStart;