希望我没大错误。
代码:
标题:如何破解 RSA-1024?—— Asprotect 1.0/1.1/1.11c
作者:Amenesia//TKM!(翻译:forgot/iPB)
0. 译注
========
结论如何无所谓,关键是学习研究弱点攻击的方法。
一些代码我调整了缩进,用 notepad 排版,并加入一点注释。
精力有限,只翻译前半部分,后面基本一样。
1. 引子
=======
为学习基础知识,我决定研究一些著名的壳及其弱点。
首先是被Recca早在几年前就发现的弱点的ASProtect。我们知
道Recca曾经利用随机数生成器的弱点破解了ASProtect的注册
方案,现在一起看看吧……
2. Asprotect 1.0/1.1 [固定密钥]
===============================
创建一个项目的时候会产生一些参数并保存在projec
t_name.aspr 文件中。其中比较重要的是用base64算法编码的
A,D,E和N(从右至左保存)。
-------------------------------------------------------
A = INDtrZliM4t...0czFJpN42UQ==
D = U2atlST1lQ...kHcbIGwJU8=
E = EQAAAAAA...AAAAAAAA=
N = X7lD2zsvq3QW...ha6mOrdvULEAM8=
-------------------------------------------------------
然后计算注册密钥:
-------------------------------------------------------
1 - H1 = RipeMD-160(A)
2 - H2 = MD5(注册信息—H1)
3 - Key = RSA(D,N, [H2—注册信息—H1])
-------------------------------------------------------
密钥看起来像这个样子:
-------------------------------------------------------
PYgt/87koSvbYPluc+/crrilfWI+ssZSU7UhgCLmK3D1C+x+
EX9n7ukwM5sKmI+nsH66V7L28BFTziNz5DOPLRHAqnI11wN5
Nd/dm0Esw20mm66V7L28BFTziNz55DOP4kzt+bie/rW4grgG
+e8/hsIuotMqUXguWKBnOXsoQ89Kg92T0MkB4FCZYuZQo=
-------------------------------------------------------
这个注册方案似乎很安全。
2.1 如何产生D,N和E?
====================
这个过程在 RSAVR.dll 实现:
-------------------------------------------------------
1 - 产生两个素数P和Q(512位)
1.1 - 产生一个512位随机数
1.2 - 找到最接近它的下一个素数(很慢)
2 - 计算 N = P * Q
3 - 计算 D = E^(-1)phi(N)(E = 17)
-------------------------------------------------------
所以如果我们能找到P和Q就能分解N。
(译注:^求次方,phi应该是欧拉函数)
2.2 如何产生P和Q?
=================
-------------------------------------------------------
unsigned long _rand()
{
//随机化seed
Seed *= 214013;
Seed += 2531011;
return( ((Seed >> 16) & 0x7FFF) );
}
unsigned long RandInt()
{
//产生一个随机数
for ( i=0; i<4; i++)
{
rval = ((rval << 8) +_ rand());
}
return(rval);
}
//计算 seed!!!关键!!!
Seed = (time() + ThreadId()) xor TickCount();
//计算P
for ( ri=0; ri<16; ri++)
{
BigNumber1[ri] = RandInt();
}
BigNumber1[ri] = BigNumber1[ri] xor C0000000h;
P = nextPrime(BigNumber1);
//计算Q
for ( ri=0; ri<16; ri++)
{
BigNumber2[ri] = RandInt();
}
BigNumber2[ri] = BigNumber2[ri] xor C0000000h;
Q = nextPrime(BigNumber2);
-------------------------------------------------------
因此若我们能猜到(time() + ThreadId()) xor Tick
Count()的值就能获得P和Q。
(译注:nextPrime() 求离参数最近的下一个素数。)
2.3 攻击
========
不知Recca是怎么找那个seed的,似乎蛮力攻击是唯
一的方法(有 2^32 种可能):
-------------------------------------------------------
1 - 选择一个 seed
2 - 计算 BigNumber1 和 BigNumber2
3 - 寻找P = nextPrime(BigNumber1)
Q = nextPrime(BigNumber2)
4 - 若 N != P * Q 则换另外的 seed
-------------------------------------------------------
不过素数测试花费的时间是可怕的,尝试2^32个不同
的 seed 几乎不可能。
2.3.1 缩小范围
==============
第一个改进方法是基于 ThreadId 和 TickCount 通
常很小的事实。所以 seed 高位一般都是 time() 值。因此,
我们可以只考察接近软件发布日期的 seed。
(译注:忍不住赞)
2.3.2 改进算法
==============
素数测试很慢,我们不得不找一个并不计算 P 和 Q
值的情况下就能检测是否是正确 seed 的算法。窍门就是修改
nextPrime() 函数使之只计算 BigNumber1 和 BigNumber2 的
低位双字。
P = BigNumber1 + Delta1 (Delta1 <= 2^64)
Q = BigNumber2 + Delta2 (Delta2 <= 2^64)
N = P * Q = (BigNumber1 + Delta1) * (BigNumber2 + Delta2)
N = BigNumber1 * BigNumber2 + Delta3 (Delta3 <= 2^(512+64+2))
因此:N高位 = BigNumber1高位 * BigNumber2高位
(译注:Delta是增量,因为 nextPrime 是下一个素数,因此
是数后面加一个增量,至于Delta的范围,我还没想去证明。)
算法:
-------------------------------------------------------
1 - 选择一个 seed
2 - 计算 BigNumber1高位 和 BigNumber2高位
3 - 若 N高位 != BigNumber1高位 * BigNumber2高位
换另外的 seed
4 - 计算 BigNumber1 和 BigNumber2(避免冲撞值)
5 - 计算 P = nextPrime( BigNumber1 )
Q = nextPrime( BigNumber2 )
6 - 若 N! = P * Q 换另外的 seed
-------------------------------------------------------
2.4 例子
========
ASProtect 1.1 用它自己加壳,再难找到更好的例子
啦。检查一下我们的的算法是否有效。
N 和 E 保存在被加密的程序中:
N = EB1D4EADA4815F6277519791BFFA8B4C0B872D1C436515AB
D9572B22BF6A03FECB4E5CC49AF1EE35C31344617A1210663056
90529B9CE7F13ED2D37CD7034A3EDD096853EC61243BCCAC5A58
800B0330A4DD85E9AA237F2F2AE60CA049B1D2777B2E0C5FF51E
058382A86C3EC12F7AB41642022772FF2A2D3DBA704725702199
E = 17
ASProtect 在 2000 10月 发布,所以我们选择 39000000h
作为最小的 seed。我们找到了一个冲撞值 398BBB72h,一分钟后找
到 399BACC4h(花了一小时检测 2^32 种可能):
D = l8F1EGKSQWCw9Et5klCpkm9/TIQFw0xOxibd+bQNndzGYoIX
4PmHXcdZtN3VWRQfuYS/cLeEf0i+kG3Cd7kaqKCkBO3xiAFgZMf
vW8D+bov+AfjDICITq5/Lhex7PykLGtUNnH8LSsmIDSWqldwX3Q
9o8U4HcJSjSJIfS4bumc=
....