1

我最近一直在尝试对编译代码中的各种加密算法进行逆向工程,我偶然发现了这段代码。它是 RSA 算法的一部分。我注意到密钥大小太小而无法加密/解密它应该加密/解密的数据(在本例中为int),因此代码将消息分成两部分,分别加密/解密,然后将它们加在一起。我已经提取了拆分和连接消息的代码段,并对其进行了试验。它使用的数值似乎取决于n模数。那么,这个方案到底是什么,它是如何工作的?

uint n = 32437;
uint origVal = 12345;
uint newVal = 0;

for (int i = 0; i < 2; ++i)
{
    ulong num = (ulong)origVal * 43827549;
    //uint num2 = ((origVal - (uint)(num >> 32)) / 2 + (uint)(num >> 32)) >> 14;
    uint num2 = (origVal + (uint)(num >> 32)) / 32768;
    origVal -= num2 * n;                
    // RSA encrypt/decrypt here
    newVal *= n;
    newVal += origVal;
    origVal = num2;
}

// Put newVal into origVal, to reverse
origVal = newVal;
newVal = 0;

for (int i = 0; i < 2; ++i)
{
    ulong num = (ulong)origVal * 43827549;
    //uint num2 = ((origVal - (uint)(num >> 32)) / 2 + (uint)(num >> 32)) >> 14;
    uint num2 = (origVal + (uint)(num >> 32)) / 32768;
    origVal -= num2 * n;                
    // RSA encrypt/decrypt here
    newVal *= n;
    newVal += origVal;
    origVal = num2;
}

注意:似乎应用的操作是对称的。

4

1 回答 1

1

在使用各种值后origVal,我发现for循环后的前三行只是一个除法,紧随其后的行是模运算。线条

ulong num = (ulong)origVal * 43827549;
//uint num2 = ((origVal - (uint)(num >> 32)) / 2 + (uint)(num >> 32)) >> 14;
uint num2 = (origVal + (uint)(num >> 32)) / 32768;

翻译成

uint valDivN = origVal / n;

origVal -= num2 * n;

进入

origVal = origVal % n;


所以for循环内的最终代码如下所示:

uint valDivN = origVal / n;
origVal = origVal % n;
// RSA encrypt/decrypt here
newVal*= n;
newVal+= origVal;
origVal = valDivN;


分析

此代码通过取原始值的模,对其进行转换,然后将其乘以 来拆分值,并将n前一个商的转换附加到结果上。行uint valDivN = origVal / n;newVal*= n;形式的逆运算。您可以将输入消息视为具有两个“框”。循环运行后,您将转换后的值放入相反的“盒子”中。当消息被解密时,“盒子”中的两个值被反向转换,并放在它们在“盒子”中的原始位置。除数的原因n是将被加密/解密的值保持在 下n,因为您可以使用 RSA 加密的最大值不大于n. 解密错误值的可能性不大,因为代码会处理打包的消息并在解密之前提取应解密的部分。循环只运行两次,因为商不可能超过 an 的大小int(因为输入是 an int)。

于 2013-07-18T15:25:24.010 回答