拥有密钥和二进制文件,我如何反转/解密流加密?

逆向工程 加密 解密 密码学 C# 密码分析
2021-06-11 03:41:58

我想问一下您是否有任何想法或方法来逆向工程解密算法以找到相反的加密函数。我确实拥有所有必需的密钥和字段,当然还有解密源代码,我已经对其进行了逆向工程。

我已经分析了代码并且有点知道它是如何工作的,但无法弄清楚如何反转(在取消加密的意义上)它。

以下信息可供我使用:

// I have all these fields (filled correctly)

    public byte[] Keychain;
    public uint Step, Mul, HeaderXor, Key;

解密函数如下所示:

public void Decrypt(byte[] packet) {
        fixed (byte* pp = packet, pk = Keychain) {
            uint size = (uint)GetPacketSize(packet);
            uint header = (first) ? /* Checks if it is a partial packet (It isnt!)*/
                0x000eb7e2 :
                *((uint*)&pp[0]) ^ HeaderXor; 
                // HeaderXor is an unsigned int
                // It also changes after each decryption and if the key changes

            if (first) 
                first = false;

            uint token = *((uint*)&pp[0]);
            *((uint*)&pp[0]) = header;
            token &= 0x3FFF;    // Get only last 14 bits
            token *= Mul * 4;   
            // Mul is an unsigned int and changes sometimes
            token = *((uint*)&pk[token]);

            uint i, r, t;
            size -= r = (size - 8) & 3; // Make size dividable by 4

            for (i = 8; i < size; i += 4) {
                t = *((uint*)&pp[i]);
                token ^= t;
                *((uint*)&pp[i]) = token;

                t &= 0x3FFF;
                token = *((uint*)&pk[t * Mul * 4]);
            }

            t = 0xFFFFFFFF >> 8 * (4 - (int)r);
            token &= t;
            *((uint*)&pp[i]) ^= token; // If something is left over ( if size - 8 == 5 then size & 3 has rest of 1)
            * ((uint*)&pp[4]) = 0;

            Step++;
            Step &= 0x3FFF;
            HeaderXor = *((uint*)&pk[Step * Mul * 4]);
        }
    }

结果示例:

// Encrypted data
// 5b 54 34 23
// cc c2 5a a3
// 81 7e d6 27
// 36 c4 8f 36
// b9 3b 6f ce
// f4 8e 72 5b
// 
// Decrypted data
// e2 b7 18 00
// 00 00 00 00
// be 00 56 00
// 2f 00 58 00
// 30 00 59 00
// 31 00 01 00

那么,你有什么办法吗?也许这个源代码可以提供更多信息,但它的服务器到客户端:

https://bitbucket.org/dignityteam/minerva/src/e149a219b6783070de71820ea359f1b27cebda63/src/ObjectBuddy/Cryption.cs?at=develop&fileviewer=file-view-default

我认为,服务器到客户端的加密不是正确的。我上面发布的解密代码确实返回了正确的结果,但与您在链接页面上看到的不同。

1个回答

好消息,你很幸运!

您面对的是一个流密码为什么这么好?因为流密码的构建方式使它们非常容易被逆转——流密码的解密和加密功能实际上是相同的功能。

流密码是一种对称密钥密码,其中明文数字与伪随机密码数字流(密钥流)相结合。在流密码中,每个明文数字一次用密钥流的相应数字加密一个,以给出密文流的数字。由于每个数字的加密取决于密码的当前状态,因此它也称为状态密码。在实践中,一个数字通常是一个位,而组合操作是一个异或(XOR)。

流密码基本上生成字节序列(或流),这些字节以逐字节方式与消息混合,几乎总是使用XOR操作。您的函数也是如此,请参阅行token ^= t;由于两个相同值的异或运算会相互抵消,因此在接收端再次将加密消息的一个字节与相同的流进行异或实际上会对其进行解密。

如果您首先拥有生成流所需的密钥和所有输入,只需再次应用相同的函数即可为您提供原始消息。