反向解密算法

逆向工程 密码学
2021-06-25 12:46:20

我一直在努力为特定软件反汇编解密算法。它的工作方式是序列密钥包含所有适当的信息,在输出纯文本数据的算法中得到处理(它实际上是二进制数据,但这在这里并不重要)。

我现在想创建一个算法来重新加密任意数据。

经过一些工作,我设法大大减少了解密过程的代码库。下面是它的工作原理 :

BigUnsigned hash_func(BigUnsigned serial, BigUnsigned running_value, BigUnsigned encrypt_key)
{
    return (serial * running_value) - (((serial * running_value) / encrypt_key) * encrypt_key);
}

void do_the_thing()
{
    BigUnsigned key1 = hash_func(buSerial, buSerial, buEncryptKey);
    BigUnsigned key2 = hash_func(buSerial, key1, buEncryptKey);

    BigUnsigned result = 1;
    int key_select = 0;
    unsigned int weird_number = 0xc3530000;
    for(int i = 0; i < 8; ++i, weird_number *= 4){
        result = hash_func(result, result, buEncryptKey);
        result = hash_func(result, result, buEncryptKey);
        if(weird_number >> 30){
            key_select++;
            if(key_select < 3){
                result = hash_func(result, key2, buEncryptKey);
            }else{
                result = hash_func(result, buSerial, buEncryptKey);
                if(key_select == 4){
                    key_select = 0;
                }
            }
        }
    }
}

两个buSerialbuEncryptKey16个无符号整型(512位)。我不知道如何创建一种算法来加密新数据。我的问题是 key2 是根据我事先不知道的最终结果生成的。

我正在使用这个 BigInt 库

1个回答

您是否有更多信息,尤其是 buEncryptKey 的一两个示例?那是质数吗?

我问的原因是:你hash_func是一个模函数,它计算(serial*running_value) % encrypt_key. 这使得key1 = serial^2%encrypt_keykey2 = serial*(serial^2%encrypt_key)%encrypt_key = serial^3 % encrypt_key多项式模质素数常用于 CRC 计算,或Fletcher's checksum

循环的其余部分根据 中的某些位计算(result^4 % encrypt_key), 然后result*(serial^3) % encrypt_key, 或(result*serial % encrypt_key)weird_number

但是,您的 key_select 似乎有点可疑 - 您能否确保以这种方式计算 key_select,而不仅仅是(weird_number >> 30) & 0x03? weird_number在循环中处理的方式将使在每一轮中检查它的 2 位是合乎逻辑的(这与与 4 的乘法一致),并且我希望 Weld_number 中的 2 位用于选择您的 if - 其他情况;现在在你的代码中,一次使用 2 位的weird_number 是没有意义的。(另外,不屏蔽高位是没有意义的,但是因为奇怪的数字无论如何只是一个 2 字节的整数,它们会在每次移位时被丢弃)。

一旦你的函数的数学计算正确,你就可以在互联网上找到它,或者 math.stackexchange.com 或 crypto.stackexchange.com 的人可能有一个使用这个算法的指针,以及如何使用创建一个匹配的反向函数。

更新

<咆哮>

今天在工作中遇到一个完全不相关的问题,我检查了两个不同的 SSL 客户端证书的内容。其中一个说:模数(大十六进制数),指数:0xbf0453。另一个说:模数(不同的大十六进制数),指数:0xcd01b7。然后我想到了你,weird_number并有了一个想法。然后我用谷歌搜索了 rsa 算法。现在,我想我知道发生了什么。

</rant>

来自维基百科关于使用 RSA 签署消息的信息:

当 Bob 收到签名的消息时,他 [...] 将签名提升到 e (modulo n) [...] 的幂,并将结果散列值与消息的实际散列值进行比较。

这正是你的算法正在做的。它通过在每个循环中计算 x^4,然后根据指数的 2 位分解 x 或 x^3 来优化数学。这似乎是蒙哥马利阶梯技术的一种变体,即一次使用 2 位而不是一位。

e是您的weird_number(50003,仅使用高 16 位),并且n是您的encrypt_key. (您可能希望通过让您的 BigInteger 库计算serial^50003 % encrypt_key)结果并将结果与​​您的“纯文本数据”进行比较来确保我是正确的,我实际上并没有检查它。)

要计算输入,您需要签名算法,来自维基百科的同一段:

Alice 希望向 Bob 发送一条签名消息。她可以使用她自己的私钥来这样做。她生成消息的散列值,将其提升到 d (modulo n) [...] 的幂,并将其作为“签名”附加到消息中。

要计算输入,您需要n(您拥有的)和d(您没有的)。要计算d,您需要将n其分解为两个生成素数 ( p, q) where n=pq这符合 Wolfram Alpha 所说n的不是素数,但不幸的是,找到这些数字很困难——毕竟,该算法被设计为不可破解的。然而,512 位不再是最先进的,crypto.stackexchange.com 的人说512 位数字的因式分解今天非常可行

不过,您可能需要投入更多时间才能实现目标。很抱歉传达坏消息。