imul 指令的第三个操作数是一个内存地址,它的原始值是多少?

Third operand of imul instruction is a memory address, what was its original value?

我目前正在从游戏中逆向哈希函数并遇到这个:

Game.exe+1F745D - 69 C0 93 01 00 01 - imul eax,eax,Game.exe+C00193

指令本身不是问题,它用三个操作数多次签名:目标、源 1 和源 2。 Source1 和 Source2 相互相乘,结果存储在目标操作数中。

当我试图对此进行逆向工程时,我想知道这个操作码在源代码中会是什么样子?
我怀疑开发人员在他们的代码中放入 BASE_ADDRESS+C00193...?
(该游戏的基地址是 0x00400000 顺便说一句,地址是静态的)

游戏正在将哈希函数的结果与硬编码值进行比较。所以我认为游戏开发者不太可能想要一个不可预测的结果。

Afaik 第三个操作数是立即数,如果我没记错的话,这意味着它“按原样”对待第三个操作数。所以第三个操作数的值不是那个内存地址的值(应该是 0),而是 base_address+C00193.

的总和

所以当我在我的代码中这样做时:hash *= 0x00400000 + 0xc00193;它确实有效,但原始源代码中的值是多少?
我已经完全实现了该功能,如果需要,我可以 post。

我的猜测是反汇编程序在这里试图变得聪明并假设常量是一个内存地址,但实际上它可能不是。从技术上讲,内存地址也只是一个数字。如果它们“看起来像一个”,反汇编器将尝试将它们显示为内存地址。 (在许多情况下,这些启发式方法非常有用,但有时它们可​​能会产生误导。)根据您发布的字节数 (93 01 00 01),它实际上是 0x1000193.

原来的代码大概是:

hash *= 0x1000193

这表明它是一个 32 位 FNV hash 函数,如下所示:

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;
}