如上题,如果要对*(p + i) = (*(p + i) * 0xccffbbbb + 0xdeadc0de) ^ 0xdeadbeef + 0xd3906;进行逆向求解,则需要*(p+i)=((*(p+i)^(0xd396d+0xdeadbeef))-0xdeadc0de)/0xccffbbbb。但是如果直接这样运行的话,肯定是不行的,因为“/”是整除,直接会损失掉数据,所以需要用到乘法逆元。
乘法逆元:如果我们有一个数 x,它的乘法逆元是另一 个数 y,使得 x 乘以 y 等于 1。换句话说,如果我们有 x * y = 1,那么 y 就是 x 的乘法逆元。有限域中的每个非零元素都有一个乘法逆 元。具体地说,对于有限域中的元素 a,它的乘法逆元记作 a^(-1),即a * a^(-1) = 1。
乘法逆元的求解需要用到a * a^(-1) ≡ 1 (mod p),其中a是要求的数,a^(-1)是他的乘法逆元,p是模数。python的gmpy2库里面的invert函数可以在输入所求的数和模数后返回乘法逆元。用法是invert(a,p)。
模数:对于两个整数a和b(其中b不为0),a除以b的余数称为a模b,记作a mod b。这里的b就是模数。模数是一个正整数,用于确定取模运算后结果的范围。假设模数是12,任意一个数x,x mod 12的最大值是11,而11+1也就是12刚好等于模数 。假设模数是10,那么任意一个数x, x mod 10的最大值是9,而9+1=10刚好是模数。所以一个数的模数是他取余下的最大值加1。比如0x17的模数是0xff+1,0x12345678的模数是0xffffffff+1。
解题:
上面这题关键就是得到0xccffbbbb的乘法逆元,求乘法逆元用invert函数,代码实现:
from gmpy2 import invert
x = 0xccffbbbb
p = 0xffffffff+1
print(hex(invert(x, p)))
解密脚本:
#include<stdio.h>
int main()
{
int s[]={0xb5073388 , 0xf58ea46f , 0x8cd2d760 , 0x7fc56cda , 0x52bc07da , 0x29054b48 ,
0x42d74750 , 0x11297e95 , 0x5cf2821b , 0x747970da , 0x64793c81};
for(int i=0;i<11;i++)
{
s[i]=((s[i]^(0xd3906+0xdeadbeef))-0xdeadc0de)*0x8d61d173;
//data[i] = ((data[i] ^ (0xdeadbeef + 0xd3906)) - 0xdeadc0de) * 0x8d61d173;
}
unsigned char *k=(unsigned char *)s;
for(int i=0;i<44;i++)
{
printf("%c",*(k+i));
}
}
运行结果: