我最近一直试图在编译代码中对各种加密算法进行逆向工程,我发现了这段代码。它是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;
}
注意:应用的操作似乎是对称的。
答案 0 :(得分: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
。不可能解密错误的值,因为代码处理打包的消息并提取在解密之前应该解密的部分。循环只运行两次,因为商不可能超过int
的大小(因为输入是int
)。