• 标 题:飞捷计费器 V2.11 算法分析
  • 作 者: Nnewell
  • 时 间:2003/03/14 04:22pm
  • 链 接:http://bbs.pediy.com

今天总算可以休息一会儿了,差不多有半年没完破解了,真怕自己落伍了,找了个简单的软件来练手,高手莫笑话。

飞捷计费器 V2.11算法分析

软件大小:  593 KB
软件语言:  简体中文
软件类别:  国产软件 / 共享版 / 网吧管理
应用平台:  Win9x/NT/2000/XP

难度:简单
算法:简单
使用工具: W32dasm v8.93
  ollydbg v1.09b
  PEID v0.8
  AspackDie v1.4
首先用 PEID v0.8 看是 Aspack2.12 的壳,用 AspackDie v1.4 很快就脱掉壳了。
运行软件, 输入相关信息 Name:Nnewell ,Code:4545454545123456789


:004631C6 8BC3                    mov eax, ebx
:004631C8 E86F8DFEFF              call 0044BF3C
:004631CD 33C9                    xor ecx, ecx

* Possible StringData Ref from Code Obj ->"\software\**计费器"
                                 |
:004631CF BA143B4600              mov edx, 00463B14
:004631D4 8BC3                    mov eax, ebx
:004631D6 E8C58DFEFF              call 0044BFA0
:004631DB 84C0                    test al, al
:004631DD 740F                    je 004631EE
:004631DF 8D4DF8                  lea ecx, dword ptr [ebp-08]

* Possible StringData Ref from Code Obj ->"UserName"
                                 |
:004631E2 BA343B4600              mov edx, 00463B34
:004631E7 8BC3                    mov eax, ebx
:004631E9 E87A8FFEFF              call 0044C168

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004631DD(C)
|
:004631EE 33C9                    xor ecx, ecx

* Possible StringData Ref from Code Obj ->"\software\microsoft\Counter"
                                 |
:004631F0 BA483B4600              mov edx, 00463B48
:004631F5 8BC3                    mov eax, ebx
:004631F7 E8A48DFEFF              call 0044BFA0
:004631FC 84C0                    test al, al
:004631FE 741C                    je 0046321C
:00463200 8D4DF0                  lea ecx, dword ptr [ebp-10]

* Possible StringData Ref from Code Obj ->"flag"
                                 |
:00463203 BA6C3B4600              mov edx, 00463B6C
:00463208 8BC3                    mov eax, ebx
:0046320A E8598FFEFF              call 0044C168
:0046320F 8B55F0                  mov edx, dword ptr [ebp-10]
:00463212 B8987F4600              mov eax, 00467F98
:00463217 E8E006FAFF              call 004038FC

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004631FE(C)
|
:0046321C 8BC3                    mov eax, ebx
:0046321E E8E98CFEFF              call 0044BF0C
:00463223 8BC3                    mov eax, ebx
:00463225 E86AFBF9FF              call 00402D94
:0046322A 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax==Nnewell,取出用户名
:0046322D E8F208FAFF              call 00403B24
:00463232 83F804                  cmp eax, 00000004<<--用户名是否大于4位
:00463235 7D0D                    jge 00463244
:00463237 8D45F8                  lea eax, dword ptr [ebp-08]

* Possible StringData Ref from Code Obj ->"guest"
                                 |
:0046323A BAF83A4600              mov edx, 00463AF8
:0046323F E8FC06FAFF              call 00403940

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463235(C)
|
:00463244 B8947F4600              mov eax, 00467F94
:00463249 8B55F8                  mov edx, dword ptr [ebp-08]
:0046324C E8AB06FAFF              call 004038FC
:00463251 A1987F4600              mov eax, dword ptr [00467F98]<<--eax=="4545454545123456789"
:00463256 E8C908FAFF              call 00403B24
:0046325B 83F813                  cmp eax, 00000013<<--注册码是19位吗
:0046325E 754B                    jne 004632AB

从上面的分析看出用户名必须大于4位且注册码必须等于19位,否则,嘿嘿……

:00463260 BB01000000              mov ebx, 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004632A7(C)
|
:00463265 B8987F4600              mov eax, 00467F98
:0046326A E8850AFAFF              call 00403CF4
:0046326F 8B15987F4600            mov edx, dword ptr [00467F98]
:00463275 8A541AFF                mov dl, byte ptr [edx+ebx-01]
:00463279 4A                      dec edx
:0046327A 885418FF                mov byte ptr [eax+ebx-01], dl
:0046327E A1987F4600              mov eax, dword ptr [00467F98]
:00463283 807C18FF61              cmp byte ptr [eax+ebx-01], 61
:00463288 7619                    jbe 004632A3
:0046328A B8987F4600              mov eax, 00467F98
:0046328F E8600AFAFF              call 00403CF4
:00463294 8B15987F4600            mov edx, dword ptr [00467F98]
:0046329A 8A541AFF                mov dl, byte ptr [edx+ebx-01]
:0046329E 4A                      dec edx
:0046329F 885418FF                mov byte ptr [eax+ebx-01], dl

省略一大段无用代码,来到下面算法分析的地方:

:004634EE E8294FFAFF              call 0040841C
:004634F3 83C4F8                  add esp, FFFFFFF8
:004634F6 DD1C24                  fstp qword ptr [esp]
:004634F9 9B                      wait
:004634FA 8D55F0                  lea edx, dword ptr [ebp-10]

* Possible StringData Ref from Code Obj ->"yyyy"-"mm"-"dd"
                                 |
:004634FD B8A83B4600              mov eax, 00463BA8
:00463502 E81D5BFAFF              call 00409024
:00463507 8B55F0                  mov edx, dword ptr [ebp-10]
:0046350A 8B45FC                  mov eax, dword ptr [ebp-04]
:0046350D 8B801C020000            mov eax, dword ptr [eax+0000021C]
:00463513 E814DBFBFF              call 0042102C
:00463518 33FF                    xor edi, edi<<--edi==0x0 清零
:0046351A 8D45F4                  lea eax, dword ptr [ebp-0C]
:0046351D E88603FAFF              call 004038A8
:00463522 E87DF3F9FF              call 004028A4
:00463527 B80A000000              mov eax, 0000000A
:0046352C E8AFF5F9FF              call 00402AE0
:00463531 666BC01E                imul ax, 001E
:00463535 6605C800                add ax, 00C8
:00463539 66A3A07F4600            mov word ptr [00467FA0], ax
:0046353F A1987F4600              mov eax, dword ptr [00467F98]
:00463544 BA083B4600              mov edx, 00463B08
:00463549 E8E606FAFF              call 00403C34
:0046354E 0F8446020000            je 0046379A
:00463554 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:00463557 E8C805FAFF              call 00403B24<<--eax=0x7 计算用户名长度
:0046355C 81C7AA550000            add edi, 000055AA<<--edi==edi+0x55AA
:00463562 03C7                    add eax, edi<<--eax==eax+edi
:00463564 8BF8                    mov edi, eax<<--edi<==eax 结果保存在edi
:00463566 8B45F8                  mov eax, dword ptr [ebp-08]
:00463569 E8B605FAFF              call 00403B24
:0046356E 8BF0                    mov esi, eax
:00463570 85F6                    test esi, esi
:00463572 7E15                    jle 00463589
:00463574 BB01000000              mov ebx, 00000001<<--计数器ebx==0x1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463587(C)
|
:00463579 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:0046357C 0FB64418FF              movzx eax, byte ptr [eax+ebx-01]<<--eax==0x4E,逐个取字符
:00463581 F7EB                    imul ebx<<--eax==eax*ebx
:00463583 03F8                    add edi, eax<<--edi==edi+eax,累加到edi
:00463585 43                      inc ebx
:00463586 4E                      dec esi
:00463587 75F0                    jne 00463579

上面是将用户名循环累加到edi,循环完后,edi=0x615B

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463572(C)
|
:00463589 BB01000000              mov ebx, 00000001<<--计数器ebx==0x1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004635B8(C)
|
:0046358E 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:00463591 8A4418FF                mov al, byte ptr [eax+ebx-01]<<--al==0x4E,逐个取字符
:00463595 3455                    xor al, 55<<--al==al xor 0x55
:00463597 25FF000000              and eax, 000000FF<<--eax==eax and 0xFF=0x1B 屏蔽高字节
:0046359C 8D4DF0                  lea ecx, dword ptr [ebp-10]
:0046359F BA02000000              mov edx, 00000002
:004635A4 E8D73CFAFF              call 00407280<<--转换为字符 "1B"
:004635A9 8B55F0                  mov edx, dword ptr [ebp-10]<<--edx=="1B"
:004635AC 8D45F4                  lea eax, dword ptr [ebp-0C]
:004635AF E87805FAFF              call 00403B2C
:004635B4 43                      inc ebx<<--计数器 ebx+1
:004635B5 83FB05                  cmp ebx, 00000005<<--循环5次,得字符串"1B3B3022",记为S1
:004635B8 75D4                    jne 0046358E

以上是注册码计算的第一部分,通过计算得到字符串"1B3B3022",记为S1

:004635BA 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:004635BD E86205FAFF              call 00403B24<<--取用户名长度 eax==0x7
:004635C2 8BD8                    mov ebx, eax<<--ebx==eax==0x7
:004635C4 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:004635C7 E85805FAFF              call 00403B24<<--取用户名长度 eax==0x7
:004635CC 8BF0                    mov esi, eax<<--esi==eax==0x7
:004635CE 4E                      dec esi<<--esi==0x6
:004635CF 2BF3                    sub esi, ebx<<--esi==esi-ebx
:004635D1 7F26                    jg 004635F9
:004635D3 4E                      dec esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004635F7(C)
|
:004635D4 8B45F8                  mov eax, dword ptr [ebp-08]<<--eax=="Nnewell"
:004635D7 0FB64418FF              movzx eax, byte ptr [eax+ebx-01]<<--eax==0x6C,逐个倒取字符
:004635DC 40                      inc eax<<--eax==eax+1=0x6D
:004635DD 8D4DF0                  lea ecx, dword ptr [ebp-10]
:004635E0 BA02000000              mov edx, 00000002
:004635E5 E8963CFAFF              call 00407280<<--转换为字符 "6D"
:004635EA 8B55F0                  mov edx, dword ptr [ebp-10]
:004635ED 8D45F4                  lea eax, dword ptr [ebp-0C]
:004635F0 E83705FAFF              call 00403B2C<<--连接到S1后面"1B3B30226D6D"
:004635F5 4B                      dec ebx
:004635F6 46                      inc esi
:004635F7 75DB                    jne 004635D4

注册码算法的第二部分得到另一字符串"1B3B30226D6D",记为S2

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004635D1(C)
|
:004635F9 8BC7                    mov eax, edi<<--eax==edi==0x615B

* Possible Reference to String Resource ID=65535: "Range check error"
                                 |
:004635FB B9FFFF0000              mov ecx, 0000FFFF<<--ecx==0xFFFF
:00463600 99                      cdq
:00463601 F7F9                    idiv ecx<<--eax--eax/ecx
:00463603 8BC2                    mov eax, edx
:00463605 8D4DF0                  lea ecx, dword ptr [ebp-10]
:00463608 BA04000000              mov edx, 00000004
:0046360D E86E3CFAFF              call 00407280<<--转换为字符 "615B"
:00463612 8B55F0                  mov edx, dword ptr [ebp-10]
:00463615 8D45F4                  lea eax, dword ptr [ebp-0C]
:00463618 E80F05FAFF              call 00403B2C<<--连接到S2后面"1B3B30226D6D615B"
:0046361D 8B45F4                  mov eax, dword ptr [ebp-0C]<<--eax=="1B3B30226D6D615B"
:00463620 E8FF04FAFF              call 00403B24<<--取用户名长度 eax==0x10
:00463625 8BF0                    mov esi, eax
:00463627 85F6                    test esi, esi
:00463629 7E2B                    jle 00463656
:0046362B BB01000000              mov ebx, 00000001<<--计数器ebx==0x1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463654(C)
|
:00463630 8BCB                    mov ecx, ebx<<--ecx==ebx==0x1
:00463632 8BC7                    mov eax, edi<<--eax==edi==0x615B
:00463634 D3E8                    shr eax, cl<<--eax==eax shr cl
:00463636 83E001                  and eax, 00000001<<--eax==eax and 0x1
:00463639 48                      dec eax<<--eax==eax-1
:0046363A 7516                    jne 00463652<<--不等于0,则不进行下面的计算
:0046363C 8D45F4                  lea eax, dword ptr [ebp-0C]
:0046363F E8B006FAFF              call 00403CF4
:00463644 8B55F4                  mov edx, dword ptr [ebp-0C]<<--edx=="1B3B30226D6D615B"
:00463647 8A541AFF                mov dl, byte ptr [edx+ebx-01]<<--dl=0x31
:0046364B 80C213                  add dl, 13<<--dl==dl+0x13
:0046364E 885418FF                mov byte ptr [eax+ebx-01], dl<<--替换字符

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0046363A(C)
|
:00463652 43                      inc ebx
:00463653 4E                      dec esi
:00463654 75DA                    jne 00463630

经过上面的计算和替换字符,得到新字符串"DBFU3C2E6D6DID5B",记为S3

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463629(C)
|
:00463656 33FF                    xor edi, edi<<--edi==0x0 清零
:00463658 BB01000000              mov ebx, 00000001<<--计数器ebx==0x1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463679(C)
|
:0046365D 8BC3                    mov eax, ebx<<--eax==ebx==0x1
:0046365F 03C0                    add eax, eax<<--eax==eax+eax==0x2
:00463661 8B55F4                  mov edx, dword ptr [ebp-0C]<<--edx=="DBFU3C2E6D6DID5B"
:00463664 8A5402FE                mov dl, byte ptr [edx+eax-02]<<--eax==0x44,取字符
:00463668 8B0D987F4600            mov ecx, dword ptr [00467F98]<<--ecx=="4545454545123456789",我们输入的注册码
:0046366E 3A5401FE                cmp dl, byte ptr [ecx+eax-02]<<--注册码比较
:00463672 7501                    jne 00463675
:00463674 47                      inc edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00463672(C)
|
:00463675 43                      inc ebx
:00463676 83FB09                  cmp ebx, 00000009
:00463679 75E2                    jne 0046365D

上面是取注册码比较,它只取单数位进行比较,如串"DBFU3C2E6D6DID5B" 1,3,5,7,……15位的字符分别为"D","F","3","2",……,"5",只要以上字符和输入的注册码相等,则完成注册码的第一部分比较,注意,这是第一部分,第二部分的注册码看下面:

:0046367B 8BC7                    mov eax, edi
:0046367D A29E7F4600              mov byte ptr [00467F9E], al
:00463682 83FF07                  cmp edi, 00000007
:00463685 0F8E0F010000            jle 0046379A
:0046368B 33FF                    xor edi, edi
:0046368D BB01000000              mov ebx, 00000001<<--计数器ebx==0x1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004636A7(C)
|
:00463692 8BC3                    mov eax, ebx<<--eax==ebx==0x1
:00463694 03C0                    add eax, eax<<--eax==eax+eax==0x2
:00463696 8B15987F4600            mov edx, dword ptr [00467F98]<<--edx=="DBFU3C2E6D6DID5B"
:0046369C 0FB64402FF              movzx eax, byte ptr [edx+eax-01]<<--取双数位字符的ASCII码 eax==0X42
:004636A1 03F8                    add edi, eax<<--edi==edi+eax 累加
:004636A3 43                      inc ebx
:004636A4 83FB09                  cmp ebx, 00000009
:004636A7 75E9                    jne 00463692

哈哈,看明白了吧,这次是计算串S3的双数位字符的累加结果,得一数edi==0x22D,记为N

:004636A9 33C0                    xor eax, eax
:004636AB 55                      push ebp
:004636AC 6874374600              push 00463774
:004636B1 64FF30                  push dword ptr fs:[eax]
:004636B4 648920                  mov dword ptr fs:[eax], esp
:004636B7 8D45EC                  lea eax, dword ptr [ebp-14]
:004636BA 50                      push eax
:004636BB B903000000              mov ecx, 00000003
:004636C0 BA11000000              mov edx, 00000011
:004636C5 A1987F4600              mov eax, dword ptr [00467F98]
:004636CA E85906FAFF              call 00403D28
:004636CF 8B4DEC                  mov ecx, dword ptr [ebp-14]
:004636D2 8D45F0                  lea eax, dword ptr [ebp-10]
:004636D5 BAC03B4600              mov edx, 00463BC0
:004636DA E89104FAFF              call 00403B70
:004636DF 8B45F0                  mov eax, dword ptr [ebp-10]
:004636E2 E8D53BFAFF              call 004072BC<<--取注册码的最后3位
:004636E7 2BC7                    sub eax, edi<<--eax==eax-edi==eax-0x22D
:004636E9 83F863                  cmp eax, 00000063<<--结果是否小于0x63
:004636EC 7E7C                    jle 0046376A<<--是则注册失败
:004636EE 8D45EC                  lea eax, dword ptr [ebp-14]
:004636F1 50                      push eax
:004636F2 B903000000              mov ecx, 00000003
:004636F7 BA11000000              mov edx, 00000011
:004636FC A1987F4600              mov eax, dword ptr [00467F98]
:00463701 E82206FAFF              call 00403D28
:00463706 8B4DEC                  mov ecx, dword ptr [ebp-14]
:00463709 8D45F0                  lea eax, dword ptr [ebp-10]
:0046370C BAC03B4600              mov edx, 00463BC0
:00463711 E85A04FAFF              call 00403B70
:00463716 8B45F0                  mov eax, dword ptr [ebp-10]
:00463719 E89E3BFAFF              call 004072BC<<--取注册码的最后3位
:0046371E 2BC7                    sub eax, edi<<--eax==eax-edi==eax-0x22D
:00463720 83F865                  cmp eax, 00000065<<--结果是否大于0x63
:00463723 7D45                    jge 0046376A<<--是则注册失败
:00463725 8D45EC                  lea eax, dword ptr [ebp-14]
:00463728 50                      push eax
:00463729 B903000000              mov ecx, 00000003
:0046372E BA11000000              mov edx, 00000011
:00463733 A1987F4600              mov eax, dword ptr [00467F98]
:00463738 E8EB05FAFF              call 00403D28
:0046373D 8B4DEC                  mov ecx, dword ptr [ebp-14]
:00463740 8D45F0                  lea eax, dword ptr [ebp-10]
:00463743 BAC03B4600              mov edx, 00463BC0
:00463748 E82304FAFF              call 00403B70
:0046374D 8B45F0                  mov eax, dword ptr [ebp-10]

从以上分析,可以看出最后3位注册码减去N,所得结果必须大于0x63且小于0x65,既然如此,则最后3位注册码的计算公式为:N+0x64=0x22D+0x64=0x291,这不就符合注册条件了吗?

综合上面的分析,就得到完整的注册码"DBFU3C2E6D6DID5B291"

完整注册信息:

Name:Nnewell
Code:DBFU3C2E6D6DID5B291

注册机以后再写了,现在真的没空。有兴趣的可以自己动手写,不说了。再说下去有人要扔鸡蛋了。

--------------------------------------------------------------------------------------------
作者:Nnewell[iPB]

       *  inside Pandora's Box -- [iPB]  *
致力于注册算法研究的中国破解组织

              写于2003年3月14日

*/转贴请保持完整 并写明出处:"看雪论坛" 作者:"Nnewell[iPB]"/*