指针链¶
我刚才描述的偏移链叫做指针链,看起来像这样:
这个指针链中的第一个值(start)叫做内存指针。它是一个开启这条链的地址。其余的值(offset1、offset2 等等)构成了通往目标数值的路径,叫做指针路径。
下面的伪代码展示了如何读取一条指针链:
int readPointerChain(chain) {
ret = read(chain[0])
for i = 1, chain.len - 1, 1 {
offset = chain[i]
ret = read(ret + offset)
}
return ret
}
这段代码创建了函数 readPointerPath(),它接受一个名为 chain 的指针链作为参数。函数 readPointerPath() 把 chain 中的指针路径当作从地址 ret 开始的一系列内存偏移量,ret 最初设置为①处的内存指针。然后它循环遍历这些偏移量,在每次迭代中把 ret 更新为 read(ret + offset) 的结果,完成后返回 ret。下面的伪代码展示了循环展开后的 readPointerPath() 是如何运行的。
list<int> chain = {0xDEADBEEF, 0xAB, 0x10, 0xCC}
value = readPointerPath(chain)
// 函数调用展开为下面这些
ret = read(0xDEADBEEF) // chain[0]
ret = read(ret + 0xAB)
ret = read(ret + 0x10)
int value = ret
这个函数在四个不同的地址上调用 read 四次——chain 中每个元素一次。
注 许多游戏黑客更喜欢就地编写链读取代码,而不是把它们封装成像 readPointerPath() 这样的函数。