MRI*_*IOT 3 assembly reverse-engineering
我目前正在从游戏中反转哈希函数并遇到以下情况:
Game.exe+1F745D - 69 C0 93 01 00 01 - imul eax,eax,Game.exe+C00193
Run Code Online (Sandbox Code Playgroud)
指令本身不是问题,它的符号乘以三个操作数:目标、源 1 和源 2。Source1 和 Source2 相乘,结果存储在目标操作数中。
当我试图对其进行逆向工程时,我想知道这个操作码在源代码中会是什么样子?
我怀疑开发人员将BASE_ADDRESS+C00193放在他们的代码中......?
(顺便说一下,那个游戏的基地址是 0x00400000,如果重要的话,地址是静态的)
游戏正在将哈希函数的结果与硬编码值进行比较。所以我认为游戏开发者不太可能想要一个不可预测的结果。
Afaik 第三个操作数是一个立即数,如果我没记错的话,这意味着它“按原样”处理第三个操作数。所以第三个操作数的值不是该内存地址处的值(应该是 0),而是 base_address+C00193 的总和。
因此,当我在代码中执行此操作时:hash *= 0x00400000 + 0xc00193;它确实有效,但是原始源代码中的值是什么?
我已经完成了该功能的完整工作实现,如果需要,我可以发布它。
我的猜测是反汇编器在这里试图变得聪明并假设常量是一个内存地址,但实际上它可能不是。从技术上讲,内存地址也只是一个数字。如果它们“看起来像一个”,反汇编器将尝试将它们显示为内存地址。(在许多情况下,这些启发式方法非常有用,但有时它们可能会产生误导。)根据您发布的字节数 ( 93 01 00 01),它实际上是0x1000193.
所以原来的代码大概是:
hash *= 0x1000193
Run Code Online (Sandbox Code Playgroud)
这表明它是一个 32 位FNV 哈希函数,如下所示:
uint32_t fnv32hash(const std::string& str) {
uint32_t hash = 0x811c9dc5;
const uint32_t primeVal = 0x1000193;
for(int i = 0; i < str.size(); i++) {
uint8_t byte = str[i];
hash ^= byte;
hash *= primeVal; // Here is your imul instruction!
}
return hash;
}
Run Code Online (Sandbox Code Playgroud)