代码:

for( int i = 0; i < 0x10; i++ ) {
   serialvar = (((magic1 * i + serialvar) << 0x10) ^ serialvar) + 0x13371337;
   serialvar = (((i * magic1 + serialvar) >> 0x10) ^ serialvar) + 0x73317331;
}

我知道,为了扭转某些事物,所有事情都必须以相反的顺序进行。但是,我很困惑,因为这非常复杂,并且似乎需要一个先验值才能反转当前值,否则将无法获得当前值?而且我们正在移位位,因此有可能永远丢失值。
IE。如果forward为x + 1,则向后为x - 1

现在,如果我们拥有serialvar的最终值,是否可以反转此循环以找到未知值serialvar?

最佳答案

与这里的答案相反,这是可以解决的,而无需任何强加于人。

循环和加法很容易反转。剩下的是这两个异或运算:

serialvar ^= (magic1 * i + serialvar) << 0x10;
serialvar ^= (i * magic1 + serialvar) >> 0x10;

让我们将0x10低位称为低部分,将0x10高位称为高部分。

在第一个操作中,很容易看到下部不受影响。但这也是此操作中唯一重要的部分,因为较高的部分被移出了。因此,此操作实际上是它自己的逆运算。

第二个操作稍微复杂一些。这次,高部分不受影响。除了加法i * magic1 + serialvar的低位部分溢出并将总和的高位部分加1的情况外,您几乎不需要关心低位部分。

因此,此操作始终采用以下两种形式之一:
serialvar ^= (i * magic1 + (serialvar & 0xFFFF0000)) >> 0x10; // no overflow
serialvar ^= (i * magic1 + (serialvar & 0xFFFF0000) + 0x10000) >> 0x10;

现在,每种形式都不依赖于serialvar的低位部分,因此每种形式都是其自身的逆形式。因此,您可以简单地尝试这两种方法,并通过应用原始操作来验证哪种方法正确。

完整的代码如下:
serialvar = key;

// compute an inverse
for (int i = 0xF; i >= 0; --i) {
    serialvar -= 0x73317331;

    unsigned int serialvar0 = serialvar ^ ((i * magic1 + (serialvar & 0xFFFF0000)) >> 0x10);
    unsigned int serialvar1 = serialvar ^ ((i * magic1 + (serialvar & 0xFFFF0000) + 0x10000) >> 0x10);

    if (serialvar == (serialvar0 ^ ((i * magic1 + serialvar0) >> 0x10)))
        serialvar = serialvar0;
    else
        serialvar = serialvar1;

    serialvar -= 0x13371337;
    serialvar ^= (magic1 * i + serialvar) << 0x10;
}

cout << hex << serialvar << endl;

// verification
for (int i = 0; i < 0x10; i++) {
    serialvar = (((magic1 * i + serialvar) << 0x10) ^ serialvar) + 0x13371337;
    serialvar = (((i * magic1 + serialvar) >> 0x10) ^ serialvar) + 0x73317331;
}

if (serialvar == key)
    cout << "success" << endl;

如果两项检查均成功,则可能存在多个逆,但我没有对此进行研究,因为这并不是必须的。

10-02 05:03