写在前面的话:
如果在读本文的时候不了解RSA,那么建议先学习了以后再来,因为文中不会分析RSA的具体实现。
EasyBoot由Borland C++ Builder写成,典型的启动验证。
当注册信息输入完毕后,会把注册码一定程度的加密存放到注册表中:
[HKEY_CURRENT_USER\Software\EasyBoot Systems\EasyBoot\3.0]
所以对RegQueryValueExA下断,当读取'UserName'和'Registration'的时候,我们要留心了。
首先是机械的把注册码解密,所以我们不用关心他的加密过程了,因为。。。
然后呢可以看到用户名和注册码入栈,说明要计算了,来到这里:
00401670 55
push ebp
00401692 6A05
push $05
;空间大小
00401694 6A30
push $30
;初始值
00401696 8D4DE4
lea ecx, [ebp-$1C]
00401699
51 push
ecx
0040169A E821480A00
call 004A5EC0 ;分配一片空间,并且附初值'00000'
004016A2 C645E431 mov
byte ptr [ebp-$1C], $31
004016A6 C645E831
mov byte ptr [ebp-$18], $31
004016AA
C645E900 mov byte
ptr [ebp-$17], $00 ;到这里得到了'10001',记做e
004016AE
6A10 push
$10
004016B0 6A41
push $41
004016B2 8D85CCFCFFFF
lea eax, [ebp+$FFFFFCCC]
004016B8
50 push
eax
004016B9 E802480A00
call 004A5EC0 ;和上面一样,'AAAAAAAAAAAAAAAA'
004016BE 83C40C
add esp, +$0C
004016C1 C685DBFCFFFF31
mov byte ptr [ebp+$FFFFFCDB], $31
004016C8 C685DAFCFFFF44
mov byte ptr [ebp+$FFFFFCDA], $44
004016CF
C685CEFCFFFF30 mov byte ptr [ebp+$FFFFFCCE],
$30
004016D6 C685CFFCFFFF46 mov
byte ptr [ebp+$FFFFFCCF], $46
004016DD C685D1FCFFFF46
mov byte ptr [ebp+$FFFFFCD1], $46
004016E4
C685D0FCFFFF38 mov byte ptr [ebp+$FFFFFCD0],
$38
004016EB C685D3FCFFFF32 mov
byte ptr [ebp+$FFFFFCD3], $32
004016F2 C685D6FCFFFF36
mov byte ptr [ebp+$FFFFFCD6], $36
004016F9
C685D2FCFFFF36 mov byte ptr [ebp+$FFFFFCD2],
$36
00401700 C685D7FCFFFF45 mov
byte ptr [ebp+$FFFFFCD7], $45
00401707 C685D8FCFFFF39
mov byte ptr [ebp+$FFFFFCD8], $39
0040170E
C685D9FCFFFF37 mov byte ptr [ebp+$FFFFFCD9],
$37
00401715 C685CDFCFFFF37 mov
byte ptr [ebp+$FFFFFCCD], $37
0040171C C685DCFCFFFF00
mov byte ptr [ebp+$FFFFFCDC], $00
;得到'A70F8F62AA6E97D1',记做n
00401726 52
push edx
00401727
FF750C push
dword ptr [ebp+$0C] ;保存的是注册码的字符串
0040172A
E8995E0200 call 004275C8
;字符串转换成某种大数的方式存储
00401740 8D85CCFCFFFF lea
eax, [ebp+$FFFFFCCC] ;n
00401746 50
push eax
00401747 E87C5E0200 call
004275C8
;把n转换存储
00401753 8D4DE4
lea ecx, [ebp-$1C]
;e
00401756 51
push ecx
00401757 E86C5E0200
call 004275C8
;把e转换存储
00401763 FF75FC
push dword ptr [ebp-$04]
;e的大数形式
00401766 FF75F8
push dword ptr [ebp-$08]
;n的大数形式
00401769 FF75F4
push dword ptr [ebp-$0C]
;注册码的大数形式
0040176C E8B74C0200
call 00426428
;RSA_EN的函数,不相信可以进去看哦
00401777 8D95E0FEFFFF
lea edx, [ebp+$FFFFFEE0]
;计算的结果,按照大数形式存放的
0040177D 52
push edx
0040177E E865600200
call 004277E8
;还原成为字符串s,然后开始检查
第一步,检查常数:
00401786 C705A8D34B0030000000 mov dword ptr [$004BD3A8],
$00000030 ;把[$004BD3A8]记做变量x = $30
00401790
0FBE8DE0FEFFFF movsx ecx, byte ptr [ebp+$FFFFFEE0]
00401797 83F934
cmp ecx, +$34
0040179A 7506
jnz 004017A2
0040179C
FF05A8D34B00 inc dword ptr [$004BD3A8]
;if s[1]='4' then inc(x)
004017A2 0FBE85E1FEFFFF movsx eax,
byte ptr [ebp+$FFFFFEE1]
004017A9 83F835
cmp eax, +$35
004017AC 7506
jnz 004017B4
004017AE FF05A8D34B00 inc
dword ptr [$004BD3A8]
;if s[2]='5' then inc(x)
004017B4 0FBE95E6FEFFFF
movsx edx, byte ptr [ebp+$FFFFFEE6]
004017BB 83FA32
cmp edx, +$32
004017BE 7C0C
jl 004017CC
004017C0 0FBE8DE6FEFFFF
movsx ecx, byte ptr [ebp+$FFFFFEE6]
004017C7 83F932
cmp ecx, +$32
004017CA 7E06
jle 004017D2
004017CC FF0DA8D34B00
dec dword ptr [$004BD3A8]
;if s[7]<>'2' then dec(x)
004017D2
0FBE85E8FEFFFF movsx eax, byte ptr [ebp+$FFFFFEE8]
004017D9 83F835
cmp eax, +$35
004017DC 7506
jnz 004017E4
004017DE
FF05A8D34B00 inc dword ptr [$004BD3A8]
;if s[9]='5' then inc(x)
004017E4 0FBE95E9FEFFFF movsx edx,
byte ptr [ebp+$FFFFFEE9]
004017EB 83FA61
cmp edx, +$61
004017EE 7506
jnz 004017F6
004017F0 FF05A8D34B00 inc
dword ptr [$004BD3A8]
;if s[10]='a' then inc(x)
004017F6 0FBE8DE7FEFFFF
movsx ecx, byte ptr [ebp+$FFFFFEE7]
004017FD 83F961
cmp ecx, +$61
00401800 7C0C
jl 0040180E
00401802 0FBE85E7FEFFFF
movsx eax, byte ptr [ebp+$FFFFFEE7]
00401809 83F861
cmp eax, +$61
0040180C 7E06
jle 00401814
0040180E FF0DA8D34B00
dec dword ptr [$004BD3A8]
;if s[8]<>'a' then dec(x)
00401814
0FBE95EEFEFFFF movsx edx, byte ptr [ebp+$FFFFFEEE]
0040181B 83FA34
cmp edx, +$34
0040181E 7506
jnz 00401826
00401820
FF05A8D34B00 inc dword ptr [$004BD3A8]
;if s[15]='4' then inc(x)
00401826 0FBE8DEFFEFFFF movsx ecx,
byte ptr [ebp+$FFFFFEEF]
0040182D 83F932
cmp ecx, +$32
00401830 7506
jnz 00401838
00401832 FF05A8D34B00 inc
dword ptr [$004BD3A8]
;if s[16]='2' then inc(x)
00401838 A1A8D34B00
mov eax, dword ptr [$004BD3A8]
;EAX = x
0040183D 83F836
cmp eax, +$36
;x<>$36就失败了
00401840 0F8532010000
jnz 00401978
那么这里如何让x=$36呢,上面一共有8个条件,实际上就是8个等式,全部满足就对了,所以这里是常数的检查。
第二步是变量的检查,也就是和注册名相关了,和上面一样的,就不多说了。
最后的结论,计算注册码的时候首先根据注册名得到RSA的密文,然后解密即可,RSA的参数如下:
n = $A70F8F62AA6E97D1
e = $10001
d = $A7CAD9177AE95A9
- 标 题:EasyBoot(7千字)
- 作 者:upfeed1
- 时 间:2002-12-16
10:37:56
- 链 接:http://bbs.pediy.com