-
-
[旧帖] [原创]第一次脱壳破解分享(申请邀请码) 0.00雪花
-
发表于: 2009-11-23 14:51 1740
-
本人是一个破解菜鸟,从上周开始看CCDebuger的OLLYDBG教程和其他入门基础,自己动手craker了字符参考和函数参考里面的两个例子,正式开始动手做自己的第一个破解示例。
一、查壳和脱壳
1.PEID查壳,UPX 0.89.6 - 1.02 / 1.05 - 2.90 (Delphi) stub -> Markus & Laszlo.
图1
2.开OD,手动脱壳,根据UPX特性跨段找到OEP如下:
007B1A50 60 PUSHAD
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 之前的修改后无法保存,故未能完成爆破。如果后面有时间,再写个注册机出来。希望这点经验能够对大家有所帮助,同时申请邀请码。
一、查壳和脱壳
1.PEID查壳,UPX 0.89.6 - 1.02 / 1.05 - 2.90 (Delphi) stub -> Markus & Laszlo.
图1
2.开OD,手动脱壳,根据UPX特性跨段找到OEP如下:
007B1A50 60 PUSHAD
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 之前的修改后无法保存,故未能完成爆破。如果后面有时间,再写个注册机出来。希望这点经验能够对大家有所帮助,同时申请邀请码。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
- 悬赏贴] 求助,.net的dll破解,希望各位高手帮忙 2473
- [分享]中年危机,lost到loser是很近的 11395
- [求助]Armadillo 3.78 - 4.xx脱壳 1505
- [原创]第一次脱壳破解分享(申请邀请码) 1741
- [原创]我的第一个自己动手的破解实例 6476
谁下载
lfsx
xingbing
sky827
rooky2000
dreams
Flashcqxg
冰山客
yangkerjkl
神猪
ydsoft
gghpop
huanbaocn
wsldc
JohnsonGuo
dewwu
urbigfool
piratelzs
zysyyz
supernova
猫王wfb
ddbigboy
hjlrobert
红毛小子
cocoyin
moonife
fdsajhg
wxl王杏林
Killeth
raising
halycarp
戊辰寒
yayiba
ansuntt
米达麦亚
ironstone
zaobao
huangyuyun
agamennong
小飙
keroal
millen
dxasqw
此名已占
gadwgadw
sizsiz
pkhhhg
TopmenC
柳絮初飘
yaojiank
cjchome
ninekent
Claud
realright
luoshuhui
hxfood
hzyking
谦谦jhw
Phelibus
海案
yufengmuyu
谁下载
lfsx
xingbing
sky827
rooky2000
dreams
Flashcqxg
冰山客
yangkerjkl
神猪
ydsoft
gghpop
huanbaocn
wsldc
JohnsonGuo
dewwu
urbigfool
piratelzs
zysyyz
supernova
猫王wfb
ddbigboy
hjlrobert
红毛小子
cocoyin
moonife
fdsajhg
wxl王杏林
Killeth
raising
halycarp
戊辰寒
yayiba
ansuntt
米达麦亚
ironstone
zaobao
huangyuyun
agamennong
小飙
keroal
millen
dxasqw
此名已占
gadwgadw
sizsiz
pkhhhg
TopmenC
柳絮初飘
yaojiank
cjchome
ninekent
Claud
realright
luoshuhui
hxfood
hzyking
谦谦jhw
Phelibus
海案
yufengmuyu
看原图
赞赏
雪币:
留言: