我一直在努力为特定软件拆卸解密算法。它的工作方式是串行密钥包含所有适当的信息,并在输出明文数据的算法中进行运算(实际上是二进制数据,但这在这里并不重要)。

我现在要创建一个可以重新加密任意数据的算法。

经过一些工作,我设法大大减少了解密过程的代码库。它是这样工作的:
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;
                }
            }
        }
    }
}
buSerial都是16个无符号整数(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的校验和中。

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

但是,您的key_select似乎有点混乱-您能否确保以这种方式计算key_select,而不仅仅是(weird_number >> 30) & 0x03weird_number在循环中的处理方式将使其在每一轮中检查2位(与4的乘法相符)是合乎逻辑的,我希望weird_number中的2位可用于选择您的其中一个if-else案件;现在在您的代码中,一次使用2位weird_number没有意义。 (此外,不要将较高的位屏蔽掉也没有意义,但是由于weird_number只是2字节整数,因此每次移位都会被丢弃)。

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

UPDATE




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




来自Wikipedia的关于签名消息的信息使用RSA:


当鲍勃收到签名的消息时,他将签名提高到e的幂(模n),然后将所得的哈希值与消息的实际哈希进行比较。值。


这正是您的算法正在执行的操作。通过在每个循环中计算x ^ 4,然后根据指数的2位,将x或x ^ 3作为因数,可以对数学进行一点优化。这似乎是蒙哥马利阶梯技术的一种变体,它一次使用2位而不是1位。

e是您的weird_number(50003,仅使用了高16位),而n是您的encrypt_key。 (您可能希望让BigInteger库计算serial^50003 % encrypt_key)并将结果与​​“纯文本数据”进行比较,以确保我是正确的,但实际上并没有进行检查。) ,则需要使用维基百科同一段落中的签名算法:


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


要计算输入,您需要n(您有)和d(您没有)。要计算d,需要将n分解为两个生成的质数(pq),其中n=pq。这符合Wolfram Alpha的说法,即n不是素数,但不幸的是,很难找到这些数字-毕竟,该算法被设计为不可破解的。但是,512位不再是最新技术,crypto.stackexchange.com的人说,对512位数字进行因式分解今天已经很可行。有更多的时间实现目标。很抱歉提供坏消息。

评论


谢谢您的帮助。 Wolfram alpha报告ecryptKey不是素数。 key_select确实不是原始的。生成的原始反汇编非常难看,我求助于一些捷径。

–埃里克
15年2月22日在13:08

serial ^ 50003非常长。我看到了一个用于该特定程序的软件,该软件将对新信息进行加密,这些新信息随后将被该程序正确解密(如果您知道我的意思)。也许我忽略了简化过程中的某些内容。

–埃里克
2015年2月24日21:00

serial ^ 50003很长,是真的。但您只需要(serial ^ 50003)%encrypt_key。举一个简单的例子,假设您要计算(7 ^ 11)%5。这等于((7 ^ 3)*(7 ^ 3)*(7 ^ 3)*(7 ^ 2))%5。但这也等于((((7 ^ 3)%5)*((7 ^ 3)%5)*((7 ^ 3)%5)*((7 ^ 2)%5))%5-在每一步之后取余数会使数字小得多,并且不会改变结果。这基本上就是您反汇编的算法。

–贡特拉姆·布洛姆
2015年2月24日在21:11