• 标 题:EasyBoot(7千字)
  • 作 者:upfeed1
  • 时 间:2002-12-16 10:37:56
  • 链 接:http://bbs.pediy.com

写在前面的话:

  如果在读本文的时候不了解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