本人是一个破解菜鸟,从上周开始看CCDebuger的OLLYDBG教程和其他入门基础,自己动手craker了字符参考和函数参考里面的两个例子,正式开始动手做自己的第一个破解示例。
一、查壳和脱壳
1.PEID查壳,UPX 0.89.6 - 1.02 / 1.05 - 2.90 (Delphi) stub -> Markus & Laszlo.
图1:

2.开OD,手动脱壳,根据UPX特性跨段找到OEP如下:

 006C1B04 > $  55            PUSH EBP



3.利用OD插件DUMP出来,一看,文件大了3倍左右,再用PEID看看,搞定,
显示:Borland Delphi 6.0 - 7.0

图2:


二、开始破解
1.OD打开脱壳后文件,运行,先用字符参考,找到注册方法函数入口,:
00695960  /.  55            PUSH EBP                                 ;  注册按钮入口
00695961  |.  8BEC          MOV EBP,ESP
00695963  |.  33C9          XOR ECX,ECX
00695965  |.  51            PUSH ECX
00695966  |.  51            PUSH ECX
00695967  |.  51            PUSH ECX
00695968  |.  51            PUSH ECX
00695969  |.  51            PUSH ECX
0069596A  |.  53            PUSH EBX
0069596B  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
0069596E  |.  33C0          XOR EAX,EAX
00695970  |.  55            PUSH EBP
00695971  |.  68 F45A6900   PUSH Q99.00695AF4
00695976  |.  64:FF30       PUSH DWORD PTR FS:[EAX]
00695979  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
0069597C  |.  8D55 F8       LEA EDX,DWORD PTR SS:[EBP-8]
0069597F  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00695982  |.  8B80 0C030000 MOV EAX,DWORD PTR DS:[EAX+30C]
00695988  |.  E8 7370DEFF   CALL Q99.0047CA00
0069598D  |.  A1 3CF36C00   MOV EAX,DWORD PTR DS:[6CF33C]
00695992  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
00695994  |.  66:BA F5FF    MOV DX,0FFF5
00695998  |.  E8 9B5EE0FF   CALL Q99.0049B838                        ;  将注册码写入EDX
0069599D  |.  33D2          XOR EDX,EDX
0069599F  |.  55            PUSH EBP
006959A0  |.  68 B25A6900   PUSH Q99.00695AB2
006959A5  |.  64:FF32       PUSH DWORD PTR FS:[EDX]
006959A8  |.  64:8922       MOV DWORD PTR FS:[EDX],ESP
006959AB  |.  68 20030000   PUSH 320                                 ; /Timeout = 800. ms
006959B0  |.  E8 43A4D7FF   CALL <JMP.&kernel32.Sleep>               ; \Sleep
006959B5  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
006959B8  |.  E8 07F5D6FF   CALL Q99.00404EC4
006959BD  |.  83F8 13       CMP EAX,13                               ;  判断注册码是否19位
006959C0  |.  0F85 D0000000 JNZ Q99.00695A96
006959C6  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  将EAX值从注册码长度改为注册码值
006959C9  |.  8A40 04       MOV AL,BYTE PTR DS:[EAX+4]               ;  注册码第5位送AL
006959CC  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]             ;  将EDX改为注册码值
006959CF  |.  3A42 09       CMP AL,BYTE PTR DS:[EDX+9]               ;  判断注册码第5位与第10位是否相等
006959D2  |.  0F85 BE000000 JNZ Q99.00695A96
006959D8  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  将EAX值从注册码长度改为注册码值
006959DB  |.  8A40 09       MOV AL,BYTE PTR DS:[EAX+9]               ;  注册码第10位送AL
006959DE  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]             ;  将EDX改为注册码值
006959E1  |.  3A42 0E       CMP AL,BYTE PTR DS:[EDX+E]               ;  判断注册码第10位与第15位是否相等
006959E4  |.  0F85 AC000000 JNZ Q99.00695A96
006959EA  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  将EAX值从注册码长度改为注册码值
006959ED  |.  8078 0E 2D    CMP BYTE PTR DS:[EAX+E],2D               ;  判断注册码第E位(即第15位)的值是否为'-'
006959F1      0F85 9F000000 JNZ Q99.00695A96
006959F7  |.  8D55 F4       LEA EDX,DWORD PTR SS:[EBP-C]
006959FA  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  将EAX改为注册码值
006959FD  |.  E8 9294E0FF   CALL Q99.0049EE94                        ;  将注册码用BASE64编码存入堆栈,原注册码存入EDX
00695A02  |.  68 C8000000   PUSH 0C8                                 ; /Timeout = 200. ms
00695A07  |.  E8 ECA3D7FF   CALL <JMP.&kernel32.Sleep>               ; \Sleep
00695A0C  |.  8B15 FCEF6C00 MOV EDX,DWORD PTR DS:[6CEFFC]            ;  Q99.006D1FFC
00695A12  |.  8B12          MOV EDX,DWORD PTR DS:[EDX]
00695A14  |.  8B52 60       MOV EDX,DWORD PTR DS:[EDX+60]
00695A17  |.  A1 FCEF6C00   MOV EAX,DWORD PTR DS:[6CEFFC]
00695A1C  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
00695A1E  |.  8B40 5C       MOV EAX,DWORD PTR DS:[EAX+5C]
00695A21  |.  8990 B8010000 MOV DWORD PTR DS:[EAX+1B8],EDX
00695A27  |.  8B15 FCEF6C00 MOV EDX,DWORD PTR DS:[6CEFFC]            ;  Q99.006D1FFC
00695A2D  |.  8BD8          MOV EBX,EAX
00695A2F  |.  68 085B6900   PUSH Q99.00695B08                        ;  ASCII "update t_para set ivalue2=3253,svalue2="
00695A34  |.  8D55 EC       LEA EDX,DWORD PTR SS:[EBP-14]
00695A37  |.  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]             ;  编码后注册码存入EAX
00695A3A  |.  E8 5543D7FF   CALL Q99.00409D94
00695A3F  |.  FF75 EC       PUSH DWORD PTR SS:[EBP-14]
00695A42  |.  68 385B6900   PUSH Q99.00695B38                        ;   where itype=0 and name='mc'
00695A47  |.  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
00695A4A  |.  BA 03000000   MOV EDX,3
00695A4F  |.  E8 30F5D6FF   CALL Q99.00404F84                        ;  连接字符串并放入堆栈
00695A54  |.  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-10]            ;  将连接好的SQL语句放入EAX
00695A57  |.  50            PUSH EAX
00695A58  |.  8BC3          MOV EAX,EBX
00695A5A  |.  E8 650DEAFF   CALL Q99.005367C4
00695A5F  |.  5A            POP EDX                                  ;  将SQL语句出栈并存入EDX
00695A60  |.  8B08          MOV ECX,DWORD PTR DS:[EAX]
00695A62  |.  FF51 2C       CALL DWORD PTR DS:[ECX+2C]
00695A65  |.  8BC3          MOV EAX,EBX
00695A67  |.  E8 C421EAFF   CALL Q99.00537C30                        ;  执行SQL语句
00695A6C  |.  A1 FCEF6C00   MOV EAX,DWORD PTR DS:[6CEFFC]
00695A71  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
00695A73  |.  8B40 58       MOV EAX,DWORD PTR DS:[EAX+58]
00695A76  |.  8983 B8010000 MOV DWORD PTR DS:[EBX+1B8],EAX
00695A7C  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00695A7F  |.  8B80 F8020000 MOV EAX,DWORD PTR DS:[EAX+2F8]
00695A85  |.  33D2          XOR EDX,EDX
00695A87  |.  8B08          MOV ECX,DWORD PTR DS:[EAX]
00695A89  |.  FF51 64       CALL DWORD PTR DS:[ECX+64]
00695A8C  |.  68 F4010000   PUSH 1F4                                 ; /Timeout = 500. ms
00695A91  |.  E8 62A3D7FF   CALL <JMP.&kernel32.Sleep>               ; \Sleep
00695A96  |>  33C0          XOR EAX,EAX
00695A98  |.  5A            POP EDX
00695A99  |.  59            POP ECX
00695A9A  |.  59            POP ECX
00695A9B  |.  64:8910       MOV DWORD PTR FS:[EAX],EDX
00695A9E  |.  68 B95A6900   PUSH Q99.00695AB9
00695AA3  |>  A1 3CF36C00   MOV EAX,DWORD PTR DS:[6CF33C]
00695AA8  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
00695AAA  |.  33D2          XOR EDX,EDX
00695AAC  |.  E8 875DE0FF   CALL Q99.0049B838
00695AB1  \.  C3            RETN
00695AB2   .- E9 CDE9D6FF   JMP Q99.00404484
00695AB7   .^ EB EA         JMP SHORT Q99.00695AA3
00695AB9   .  6A 40         PUSH 40
00695ABB   .  B9 585B6900   MOV ECX,Q99.00695B58                     ;  提示
00695AC0   .  BA 605B6900   MOV EDX,Q99.00695B60                     ;  请关闭本软件,重启后注册码将生效!感谢您对中国共享软件的支持!
00695AC5   .  A1 48EF6C00   MOV EAX,DWORD PTR DS:[6CEF48]
00695ACA   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
00695ACC   .  E8 1F80E0FF   CALL Q99.0049DAF0                        ;  弹出提示框


3.运行软件,点注册方法,由上面注释可以看到一步步跟入发现注册码是输入后判断是否19位,每四位用'-'分隔,存入数据库(数据库用的是SQLITE3,已加密),如不正确会存不到数据库,此时不会判断是否与机器码匹配。

4.安装注册码规则随便输入任意19位,点注册存入数据库,提示重启软件生效。




5.利用消息断点和函数参考找到启动时判断是否注册的函数:
00550294    55              PUSH EBP                                 ; 程序启动时判断注册
00550295    8BEC            MOV EBP,ESP
00550297    B9 0D000000     MOV ECX,0D
0055029C    6A 00           PUSH 0
0055029E    6A 00           PUSH 0
005502A0    49              DEC ECX                                  ; 将ECX值减1
005502A1  ^ 75 F9           JNZ SHORT Q99.0055029C
005502A3    51              PUSH ECX
005502A4    53              PUSH EBX
005502A5    56              PUSH ESI
005502A6    57              PUSH EDI
005502A7    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX
005502AA    33C0            XOR EAX,EAX
005502AC    55              PUSH EBP
005502AD    68 75065500     PUSH Q99.00550675
005502B2    64:FF30         PUSH DWORD PTR FS:[EAX]
005502B5    64:8920         MOV DWORD PTR FS:[EAX],ESP
005502B8    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
005502BB    8B40 60         MOV EAX,DWORD PTR DS:[EAX+60]
005502BE    8B55 FC         MOV EDX,DWORD PTR SS:[EBP-4]
005502C1    8B5A 5C         MOV EBX,DWORD PTR DS:[EDX+5C]
005502C4    8983 B8010000   MOV DWORD PTR DS:[EBX+1B8],EAX
005502CA    33C0            XOR EAX,EAX
005502CC    55              PUSH EBP
005502CD    68 8F055500     PUSH Q99.0055058F
005502D2    64:FF30         PUSH DWORD PTR FS:[EAX]
005502D5    64:8920         MOV DWORD PTR FS:[EAX],ESP
005502D8    8BC3            MOV EAX,EBX
005502DA    E8 E564FEFF     CALL Q99.005367C4
005502DF    BA 90065500     MOV EDX,Q99.00550690                     ; select * from t_para where itype=0 and ivalue2=3253 and name='mc'
005502E4    8B08            MOV ECX,DWORD PTR DS:[EAX]
005502E6    FF51 2C         CALL DWORD PTR DS:[ECX+2C]               ; 可能是执行SQL语句
005502E9    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
005502EC    8B40 5C         MOV EAX,DWORD PTR DS:[EAX+5C]
005502EF    E8 A434FDFF     CALL Q99.00523798
005502F4    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
005502F7    8B58 5C         MOV EBX,DWORD PTR DS:[EAX+5C]
005502FA    80BB A1000000 0>CMP BYTE PTR DS:[EBX+A1],0
00550301    74 12           JE SHORT Q99.00550315                    ; 可能必跳
00550303    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
00550306    05 BC000000     ADD EAX,0BC
0055030B    E8 F448EBFF     CALL Q99.00404C04
00550310    E9 6C020000     JMP Q99.00550581
00550315    33C0            XOR EAX,EAX
00550317    55              PUSH EBP
00550318    68 4C035500     PUSH Q99.0055034C
0055031D    64:FF30         PUSH DWORD PTR FS:[EAX]
00550320    64:8920         MOV DWORD PTR FS:[EAX],ESP
00550323    8BC3            MOV EAX,EBX
00550325    BA DC065500     MOV EDX,Q99.005506DC                     ; ASCII "sValue2"
0055032A    E8 ED44FDFF     CALL Q99.0052481C                        ; 取到一个字符串'HEQ'放入EAX
0055032F    8D55 F4         LEA EDX,DWORD PTR SS:[EBP-C]
00550332    8B08            MOV ECX,DWORD PTR DS:[EAX]
00550334    FF51 60         CALL DWORD PTR DS:[ECX+60]               ; 取sValue2的值并放入堆栈
00550337    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]             ; 将取到的sValue2的值放入EAX
0055033A    8D55 F8         LEA EDX,DWORD PTR SS:[EBP-8]             ; 将堆栈中位置为EBP的值减8的地址中的数压入EDX
0055033D    E8 46EEF4FF     CALL Q99.0049F188                        ; 将EAX中的注册码根据BASE64解码并压入堆栈
00550342    33C0            XOR EAX,EAX
00550344    5A              POP EDX
00550345    59              POP ECX
00550346    59              POP ECX
00550347    64:8910         MOV DWORD PTR FS:[EAX],EDX
0055034A    EB 0F           JMP SHORT Q99.0055035B
0055034C  ^ E9 7F3EEBFF     JMP Q99.004041D0
00550351    E8 FAE3EBFF     CALL Q99.0040E750
00550356    E8 A142EBFF     CALL Q99.004045FC
0055035B    BB 61090000     MOV EBX,961
00550360    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]             ; 将解码后注册码sValue2的值放入EAX
00550363    E8 5C4BEBFF     CALL Q99.00404EC4
00550368    83F8 13         CMP EAX,13                               ; 判断长度是否为19位,以下同注册方法中判断
0055036B    0F85 10020000   JNZ Q99.00550581
00550371    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
00550374    8A40 04         MOV AL,BYTE PTR DS:[EAX+4]
00550377    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
0055037A    3A42 09         CMP AL,BYTE PTR DS:[EDX+9]
0055037D    0F85 FE010000   JNZ Q99.00550581
00550383    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
00550386    8A40 09         MOV AL,BYTE PTR DS:[EAX+9]
00550389    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
0055038C    3A42 0E         CMP AL,BYTE PTR DS:[EDX+E]
0055038F    0F85 EC010000   JNZ Q99.00550581
00550395    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
00550398    8078 0E 2D      CMP BYTE PTR DS:[EAX+E],2D               ; 判断第15位是否为-
0055039C    0F85 DF010000   JNZ Q99.00550581                         ; 至此判断注册码位数和连接符结束
005503A2    8D4D F0         LEA ECX,DWORD PTR SS:[EBP-10]
005503A5    BA EC065500     MOV EDX,Q99.005506EC                     ; -将数据段中保存的'-'号放入EDX中,覆盖原来的解码后的注册码
005503AA    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]             ; 将堆栈中解码后的注册码放入EAX
005503AD    E8 AE52FBFF     CALL Q99.00505660                        ; 取注册码后四位放入EDX,并压入堆栈
005503B2    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]
005503B5    8B00            MOV EAX,DWORD PTR DS:[EAX]               ; 将堆栈中注册码后4位放入EAX
005503B7    50              PUSH EAX
005503B8    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]
005503BB    50              PUSH EAX
005503BC    8D45 D0         LEA EAX,DWORD PTR SS:[EBP-30]
005503BF    E8 C0AFFAFF     CALL Q99.004FB384                        ; 根据机器生成机器码并放入堆栈
005503C4    8B45 D0         MOV EAX,DWORD PTR SS:[EBP-30]            ; 机器码放EAX
005503C7    8D4D D4         LEA ECX,DWORD PTR SS:[EBP-2C]
005503CA    BA EC065500     MOV EDX,Q99.005506EC                     ; --将数据段中保存的'-'号放入EDX中
005503CF    E8 8C52FBFF     CALL Q99.00505660                        ; 截机器码后四位放入EDX,并压入堆栈
005503D4    8B45 D4         MOV EAX,DWORD PTR SS:[EBP-2C]
005503D7    8B00            MOV EAX,DWORD PTR DS:[EAX]               ; 机器码前四位放入EAX
005503D9    8D55 D8         LEA EDX,DWORD PTR SS:[EBP-28]
005503DC    E8 5F70FAFF     CALL Q99.004F7440                        ; 可能的关键函数1
005503E1    8D45 D8         LEA EAX,DWORD PTR SS:[EBP-28]
005503E4    8D55 E8         LEA EDX,DWORD PTR SS:[EBP-18]
005503E7    E8 B871FAFF     CALL Q99.004F75A4                        ; 可能的关键函数2
005503EC    8B45 E8         MOV EAX,DWORD PTR SS:[EBP-18]            ; 可能根据机器码生产一个验证字符串并放入了堆栈,此时从堆栈中放入EAX
005503EF    B9 04000000     MOV ECX,4                                ; ECX放4
005503F4    BA 01000000     MOV EDX,1                                ; EDX放1
005503F9    E8 264DEBFF     CALL Q99.00405124                        ; 调用此函数后ECX和EDX都被清零
005503FE    8B55 EC         MOV EDX,DWORD PTR SS:[EBP-14]            ; 将产生的验证字符串前四位放入EDX中,验证字符串放于堆栈中
00550401    58              POP EAX                                  ; 将栈顶的注册码前4位出栈压入EAX中
00550402    E8 094CEBFF     CALL Q99.00405010                        ; 可能是比较EAX和EDX的值,即比较注册码和生成字符串的值
00550407    75 0C           JNZ SHORT Q99.00550415                   ; 此处可能坚决不能跳
00550409    8BC3            MOV EAX,EBX
0055040B    B9 07000000     MOV ECX,7
00550410    99              CDQ
00550411    F7F9            IDIV ECX
00550413    8BD8            MOV EBX,EAX
00550415    8D4D CC         LEA ECX,DWORD PTR SS:[EBP-34]
00550418    BA EC065500     MOV EDX,Q99.005506EC                     ; -从数据段取分隔符'-'放入EDX
0055041D    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]             ; 将堆栈中注册码放入EAX
00550420    E8 3B52FBFF     CALL Q99.00505660                        ; 可能是根据EDX中的分隔符和EAX中的注册码将注册码按4位(后四位)分割并放入EDX
00550425    8B45 CC         MOV EAX,DWORD PTR SS:[EBP-34]
00550428    8B40 04         MOV EAX,DWORD PTR DS:[EAX+4]             ; 取到的四位注册码放EAX
0055042B    50              PUSH EAX
0055042C    8D45 C8         LEA EAX,DWORD PTR SS:[EBP-38]
0055042F    50              PUSH EAX
00550430    8D45 BC         LEA EAX,DWORD PTR SS:[EBP-44]
00550433    E8 4CAFFAFF     CALL Q99.004FB384                        ; 不知调用什么函数,程序中断,在菜单中点暂停后才能继续运行
00550438    8B45 BC         MOV EAX,DWORD PTR SS:[EBP-44]            ; 取机器码放EAX
0055043B    8D4D C0         LEA ECX,DWORD PTR SS:[EBP-40]            ; 从堆栈中取机器码放入EAX
0055043E    BA EC065500     MOV EDX,Q99.005506EC                     ; -从数据段取分隔符'-'放入EDX
00550443    E8 1852FBFF     CALL Q99.00505660                        ; 可能是根据EDX中的分隔符和EAX中的机器码,将机器码按4位(后四位)分割并放入EDX
00550448    8B45 C0         MOV EAX,DWORD PTR SS:[EBP-40]            ; 生产一个字符串放入EAX,可能是准备与后四位机器码比较
0055044B    8B40 04         MOV EAX,DWORD PTR DS:[EAX+4]
0055044E    8D55 D8         LEA EDX,DWORD PTR SS:[EBP-28]
00550451    E8 EA6FFAFF     CALL Q99.004F7440                        ; 调用此函数后ECX和EDX都被清零
00550456    8D45 D8         LEA EAX,DWORD PTR SS:[EBP-28]
00550459    8D55 C4         LEA EDX,DWORD PTR SS:[EBP-3C]
0055045C    E8 4371FAFF     CALL Q99.004F75A4
00550461    8B45 C4         MOV EAX,DWORD PTR SS:[EBP-3C]            ; 可能根据机器码生产一个验证字符串并放入了堆栈,此时从堆栈中放入EAX
00550464    B9 04000000     MOV ECX,4
00550469    BA 05000000     MOV EDX,5
0055046E    E8 B14CEBFF     CALL Q99.00405124                        ; 调用后EAX中产生的字符串被压入了堆栈
00550473    8B55 C8         MOV EDX,DWORD PTR SS:[EBP-38]            ; 取生产验证码的第二个四位放入EDX
00550476    58              POP EAX                                  ; 将堆栈中的注册码第二个四位出栈至EAX
00550477    E8 944BEBFF     CALL Q99.00405010                        ; 可能是比较EAX和EDX的值,即比较注册码和生成字符串的值
0055047C    75 0C           JNZ SHORT Q99.0055048A                   ; 根据上面逻辑,此处也可能坚决不能跳
0055047E    8BC3            MOV EAX,EBX
00550480    B9 07000000     MOV ECX,7
00550485    99              CDQ
00550486    F7F9            IDIV ECX
00550488    8BD8            MOV EBX,EAX
0055048A    8D4D B8         LEA ECX,DWORD PTR SS:[EBP-48]
0055048D    BA EC065500     MOV EDX,Q99.005506EC                     ; -
00550492    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
00550495    E8 C651FBFF     CALL Q99.00505660                        ; 可能是根据EDX中的分隔符和EAX中的机器码,将机器码按4位分割并放入EDX
0055049A    8B45 B8         MOV EAX,DWORD PTR SS:[EBP-48]
0055049D    8B40 08         MOV EAX,DWORD PTR DS:[EAX+8]
005504A0    50              PUSH EAX
005504A1    8D45 B4         LEA EAX,DWORD PTR SS:[EBP-4C]
005504A4    50              PUSH EAX
005504A5    8D45 A8         LEA EAX,DWORD PTR SS:[EBP-58]
005504A8    E8 D7AEFAFF     CALL Q99.004FB384
005504AD    8B45 A8         MOV EAX,DWORD PTR SS:[EBP-58]
005504B0    8D4D AC         LEA ECX,DWORD PTR SS:[EBP-54]
005504B3    BA EC065500     MOV EDX,Q99.005506EC                     ; -
005504B8    E8 A351FBFF     CALL Q99.00505660
005504BD    8B45 AC         MOV EAX,DWORD PTR SS:[EBP-54]
005504C0    8B40 08         MOV EAX,DWORD PTR DS:[EAX+8]
005504C3    8D55 D8         LEA EDX,DWORD PTR SS:[EBP-28]            ; 运行至此EAX值为机器码第三个四位数,EDX为第四个四位数
005504C6    E8 756FFAFF     CALL Q99.004F7440
005504CB    8D45 D8         LEA EAX,DWORD PTR SS:[EBP-28]
005504CE    8D55 B0         LEA EDX,DWORD PTR SS:[EBP-50]
005504D1    E8 CE70FAFF     CALL Q99.004F75A4                        ; 可能是生成验证字符串并放入EAX中
005504D6    8B45 B0         MOV EAX,DWORD PTR SS:[EBP-50]
005504D9    B9 04000000     MOV ECX,4
005504DE    BA 09000000     MOV EDX,9
005504E3    E8 3C4CEBFF     CALL Q99.00405124
005504E8    8B55 B4         MOV EDX,DWORD PTR SS:[EBP-4C]            ; 生成验证码第三个四位数从堆栈至EDX
005504EB    58              POP EAX                                  ; 栈顶注册码第三个四位数送EAX
005504EC    E8 1F4BEBFF     CALL Q99.00405010
005504F1    75 0C           JNZ SHORT Q99.005504FF                   ; 根据上面逻辑,此处也可能坚决不能跳
005504F3    8BC3            MOV EAX,EBX
005504F5    B9 07000000     MOV ECX,7
005504FA    99              CDQ
005504FB    F7F9            IDIV ECX
005504FD    8BD8            MOV EBX,EAX
005504FF    8D4D A4         LEA ECX,DWORD PTR SS:[EBP-5C]
00550502    BA EC065500     MOV EDX,Q99.005506EC                     ; -
00550507    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
0055050A    E8 5151FBFF     CALL Q99.00505660
0055050F    8B45 A4         MOV EAX,DWORD PTR SS:[EBP-5C]
00550512    8B40 0C         MOV EAX,DWORD PTR DS:[EAX+C]
00550515    50              PUSH EAX
00550516    8D45 A0         LEA EAX,DWORD PTR SS:[EBP-60]
00550519    50              PUSH EAX
0055051A    8D45 94         LEA EAX,DWORD PTR SS:[EBP-6C]
0055051D    E8 62AEFAFF     CALL Q99.004FB384
00550522    8B45 94         MOV EAX,DWORD PTR SS:[EBP-6C]
00550525    8D4D 98         LEA ECX,DWORD PTR SS:[EBP-68]
00550528    BA EC065500     MOV EDX,Q99.005506EC                     ; -
0055052D    E8 2E51FBFF     CALL Q99.00505660
00550532    8B45 98         MOV EAX,DWORD PTR SS:[EBP-68]
00550535    8B40 0C         MOV EAX,DWORD PTR DS:[EAX+C]
00550538    8D55 D8         LEA EDX,DWORD PTR SS:[EBP-28]
0055053B    E8 006FFAFF     CALL Q99.004F7440
00550540    8D45 D8         LEA EAX,DWORD PTR SS:[EBP-28]
00550543    8D55 9C         LEA EDX,DWORD PTR SS:[EBP-64]
00550546    E8 5970FAFF     CALL Q99.004F75A4
0055054B    8B45 9C         MOV EAX,DWORD PTR SS:[EBP-64]
0055054E    B9 04000000     MOV ECX,4
00550553    BA 0D000000     MOV EDX,0D
00550558    E8 C74BEBFF     CALL Q99.00405124
0055055D    8B55 A0         MOV EDX,DWORD PTR SS:[EBP-60]
00550560    58              POP EAX
00550561    E8 AA4AEBFF     CALL Q99.00405010
00550566    75 0C           JNZ SHORT Q99.00550574                   ; 根据上面逻辑,此处也可能坚决不能跳
00550568    8BC3            MOV EAX,EBX
0055056A    B9 07000000     MOV ECX,7
0055056F    99              CDQ
00550570    F7F9            IDIV ECX
00550572    8BD8            MOV EBX,EAX
00550574    83FB 32         CMP EBX,32                               ; 可能是关键的比较点
00550577    7D 08           JGE SHORT Q99.00550581                   ; 是否注册极为关键点,必须不跳
00550579    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
0055057C    E8 6F010000     CALL Q99.005506F0
00550581    33C0            XOR EAX,EAX
00550583    5A              POP EDX
00550584    59              POP ECX
00550585    59              POP ECX
00550586    64:8910         MOV DWORD PTR FS:[EAX],EDX
00550589    68 96055500     PUSH Q99.00550596
0055058E    C3              RETN

三、总结:
      由以上代码和注释大家可以看到注册码和机器码之间的联系,程序每次启动从数据库(如数据库不存在则自动重建)取出注册码,根据机器硬件编号生成机器码(碍于笔者的水平未能找出生成规则),根据机器码生成验证的注册码,再与数据库存放的注册码比较,因水平及时间,未能理清关系,不然可以写个注册机。笔者只是简单找出联系后找出自己的对应验证注册码后重新注册,因程序每次启动自解压部分DLL,放于WINDOWS临时文件夹TEMP中,其中地址00694000  之前的修改后无法保存,故未能完成爆破。如果后面有时间,再写个注册机出来。希望这点经验能够对大家学习破解有所帮助,同时申请邀请码。
另:本人完全出于学习的兴趣进行的研究,不承担任何关于软件版权的责任,请大家学习的时候遵守版权规定。
附:软件下载地址
h**p://www.nilsoft.net/download.html