本人是一个破解菜鸟,从上周开始看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 之前的修改后无法保存,故未能完成爆破。如果后面有时间,再写个注册机出来。希望这点经验能够对大家学习破解有所帮助,同时申请邀请码。
另:本人完全出于学习的兴趣进行的研究,不承担任何关于软件版权的责任,请大家学习的时候遵守版权规定。
附:软件下载地址
http://www.nilsoft.net/download.html
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课