【破文标题】 天天个人助理(DailyPim)注册算法分析
【破文作者】 xu_wh
【软件名称】 天天个人助理(DailyPim) V3.53
【下载地址】 http://www.haoz.cn/Software/Catalog59/4746.html
http://www.997.cn/SoftView/SoftView_4599.html
【软件简介】 DailyPim是一款个人日常信息管理的软件,具有的功能有日记本、资料管理、文件管理、日程管理、地址簿、网页快抓、收发消息、收发文件、邮箱监视器、查询天气、火车、航班、电话区号、邮政编码、定时关机等。DailyPim是国内功能最强大的个人信息管理软件。
【调试环境】 Win xp 、Ollydbg 1.10、PEID V0.93、LordPE 1.4、Import RE 1.6
【作者声明】 有人曾经写出了注册机,但是发现注册机程序有问题。后来再网上找到了相关的注册算法,但是发现注册算法不完整,至少不能适用于3.53这个版本。为了弥补这个缺漏,对这个程序重新分析。 其中参考了snake大侠的破解说明,节省了我许多时间。在此表示感谢!
----------------------------------------------------------------------------------------------
【破解过程】
一、脱壳:
先用PEID对程序DailyPim.exe进行检测,检测的结果是“Nothing found *”。只好手工脱壳。用OD载入:
00C52082 d> 60 pushad ;一路F8,好好走。
00C52083 E8 00000000 call dailypim.00C52088
00C52088 5D pop ebp
00C52089 81ED 22A54500 sub ebp,dailypim.0045A522
00C5208F 8DBD 1CA54500 lea edi,dword ptr ss:[ebp+45A51C]
00C52095 81EF 82000000 sub edi,82
00C5209B 89BD 84A84500 mov dword ptr ss:[ebp+45A884],edi
00C520A1 8B4F 18 mov ecx,dword ptr ds:[edi+18]
00C520A4 89FE mov esi,edi
00C520A6 0377 14 add esi,dword ptr ds:[edi+14]
00C520A9 8B47 10 mov eax,dword ptr ds:[edi+10]
00C520AC E8 2A060000 call dailypim.00C526DB
00C520B1 8B4F 24 mov ecx,dword ptr ds:[edi+24]
00C520B4 89FE mov esi,edi
00C520B6 0377 20 add esi,dword ptr ds:[edi+20]
00C520B9 8B47 1C mov eax,dword ptr ds:[edi+1C]
00C520BC E8 1A060000 call dailypim.00C526DB
00C520C1 6A 00 push 0
......
00C522E8 39FE cmp esi,edi
00C522EA 7D 12 jge short dailypim.00C522FE
00C522EC 8B06 mov eax,dword ptr ds:[esi]
00C522EE 83C6 04 add esi,4
00C522F1 09C0 or eax,eax
00C522F3 ^ 74 F3 je short dailypim.00C522E8
00C522F5 50 push eax
00C522F6 FF95 08A94500 call near dword ptr ss:[ebp+45A908]
00C522FC ^ EB EA jmp short dailypim.00C522E8 ;不要回跳
00C522FE 8DB5 58A84500 lea esi,dword ptr ss:[ebp+45A858] ;F4 到这里
......
00C4B0C7 8B46 04 mov eax,dword ptr ds:[esi+4]
00C4B0CA 05 0E010000 add eax,10E
00C4B0CF 6A 04 push 4
00C4B0D1 68 00100000 push 1000
00C4B0D6 50 push eax
00C4B0D7 6A 00 push 0
00C4B0D9 FF95 4D050000 call near dword ptr ss:[ebp+54D]
00C4B0DF 8985 52010000 mov dword ptr ss:[ebp+152],eax
00C4B0E5 56 push esi
00C4B0E6 8B1E mov ebx,dword ptr ds:[esi]
00C4B0E8 039D 22040000 add ebx,dword ptr ss:[ebp+422]
00C4B0EE FFB5 56010000 push dword ptr ss:[ebp+156]
00C4B0F4 FF76 04 push dword ptr ds:[esi+4]
00C4B0F7 50 push eax
00C4B0F8 53 push ebx
00C4B0F9 E8 6E050000 call dailypim.00C4B66C
00C4B0FE B3 01 mov bl,1
00C4B100 80FB 00 cmp bl,0
00C4B103 75 5E jnz short dailypim.00C4B163
00C4B105 FE85 EC000000 inc byte ptr ss:[ebp+EC]
00C4B10B 8B3E mov edi,dword ptr ds:[esi]
00C4B10D 03BD 22040000 add edi,dword ptr ss:[ebp+422]
00C4B113 FF37 push dword ptr ds:[edi]
00C4B115 C607 C3 mov byte ptr ds:[edi],0C3
00C4B118 FFD7 call near edi
00C4B11A 8F07 pop dword ptr ds:[edi]
00C4B11C 50 push eax
00C4B11D 51 push ecx
00C4B11E 56 push esi
00C4B11F 53 push ebx
00C4B120 8BC8 mov ecx,eax
00C4B122 83E9 06 sub ecx,6
00C4B125 8BB5 52010000 mov esi,dword ptr ss:[ebp+152]
00C4B12B 33DB xor ebx,ebx
00C4B12D 0BC9 or ecx,ecx
00C4B12F 74 2E je short dailypim.00C4B15F
00C4B131 78 2C js short dailypim.00C4B15F
00C4B133 AC lods byte ptr ds:[esi]
00C4B134 3C E8 cmp al,0E8
00C4B136 74 0A je short dailypim.00C4B142
00C4B138 EB 00 jmp short dailypim.00C4B13A
00C4B13A 3C E9 cmp al,0E9
00C4B13C 74 04 je short dailypim.00C4B142
00C4B13E 43 inc ebx
00C4B13F 49 dec ecx
00C4B140 ^ EB EB jmp short dailypim.00C4B12D
00C4B142 8B06 mov eax,dword ptr ds:[esi]
00C4B144 EB 0A jmp short dailypim.00C4B150
00C4B146 803E 00 cmp byte ptr ds:[esi],0
00C4B149 ^ 75 F3 jnz short dailypim.00C4B13E
00C4B14B 24 00 and al,0
00C4B14D C1C0 18 rol eax,18
00C4B150 2BC3 sub eax,ebx
00C4B152 8906 mov dword ptr ds:[esi],eax
00C4B154 83C3 05 add ebx,5
00C4B157 83C6 04 add esi,4
00C4B15A 83E9 05 sub ecx,5
00C4B15D ^ EB CE jmp short dailypim.00C4B12D
00C4B15F 5B pop ebx
00C4B160 5E pop esi
00C4B161 59 pop ecx
00C4B162 58 pop eax
00C4B163 EB 08 jmp short dailypim.00C4B16D
00C4B165 0000 add byte ptr ds:[eax],al
00C4B167 DE01 fiadd word ptr ds:[ecx]
00C4B169 0000 add byte ptr ds:[eax],al
00C4B16B D001 rol byte ptr ds:[ecx],1
00C4B16D 8BC8 mov ecx,eax
00C4B16F 8B3E mov edi,dword ptr ds:[esi]
00C4B171 03BD 22040000 add edi,dword ptr ss:[ebp+422]
00C4B177 8BB5 52010000 mov esi,dword ptr ss:[ebp+152]
00C4B17D C1F9 02 sar ecx,2
00C4B180 F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
00C4B182 8BC8 mov ecx,eax
00C4B184 83E1 03 and ecx,3
00C4B187 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[>
00C4B189 5E pop esi
00C4B18A 68 00800000 push 8000
00C4B18F 6A 00 push 0
00C4B191 FFB5 52010000 push dword ptr ss:[ebp+152]
00C4B197 FF95 51050000 call near dword ptr ss:[ebp+551]
00C4B19D 83C6 08 add esi,8
00C4B1A0 833E 00 cmp dword ptr ds:[esi],0
00C4B1A3 ^ 0F85 1EFFFFFF jnz dailypim.00C4B0C7 ;不要往回跳
00C4B1A9 68 00800000 push 8000 ;F4到这里
00C4B1AE 6A 00 push 0
00C4B1B0 FFB5 56010000 push dword ptr ss:[ebp+156]
00C4B1B6 FF95 51050000 call near dword ptr ss:[ebp+551] ; kernel32.VirtualFree
.....................................
中间略。坚持一路F8,不要往回跳的原则,否则就要多走些路了 :)
==============================================================>来到这里:
00C4B389 8946 10 mov dword ptr ds:[esi+10],eax
00C4B38C 83C6 14 add esi,14
00C4B38F 8B95 22040000 mov edx,dword ptr ss:[ebp+422]
00C4B395 ^ E9 EBFEFFFF jmp dailypim.00C4B285
00C4B39A B8 F8384200 mov eax,dailypim.004238F8
00C4B39F 50 push eax
00C4B3A0 0385 22040000 add eax,dword ptr ss:[ebp+422]
00C4B3A6 59 pop ecx
00C4B3A7 0BC9 or ecx,ecx
00C4B3A9 8985 A8030000 mov dword ptr ss:[ebp+3A8],eax
00C4B3AF 61 popad ;终于找到了 :)
00C4B3B0 75 08 jnz short dailypim.00C4B3BA ;慢慢走
00C4B3B2 B8 01000000 mov eax,1
00C4B3B7 C2 0C00 retn 0C
00C4B3BA 68 F8388200 push dailypim.008238F8 ;应该就是你了吧
00C4B3BF C3 retn
============================================================>找到EOP
008238F8 55 push ebp ;EOP here
008238F9 8BEC mov ebp,esp
008238FB 83C4 F0 add esp,-10
008238FE 53 push ebx
008238FF B8 682A8200 mov eax,dailypim.00822A68
00823904 E8 8B3DBEFF call dailypim.00407694
00823909 8B1D 941F8300 mov ebx,dword ptr ds:[831F94] ; dailypim.00833C3C
0082390F 8B03 mov eax,dword ptr ds:[ebx]
00823911 E8 DA7BC5FF call dailypim.0047B4F0
00823916 8B03 mov eax,dword ptr ds:[ebx]
00823918 BA 88398200 mov edx,dailypim.00823988 ; ASCII "DailyPim"
我们用LordPE Dump下来,生成一个Dump.exe的文件。然后启用Import RE,输入OEP为4238F8,获取输入表,没问题。
脱壳成功,脱壳后的软件能直接运行。我的天,这个脱了壳的软件有8M多。 用PE检测到Borland Delphi 6.0 - 7.0。
二、破解一:
在这部分,我们通过跟踪程序生成真注册码的过程,完成对部分注册码的破解。
首先运行脱壳后的软件,对软件有一个基本的了解。在帮助菜单下选择“注册”,有一个弹出框,点击“输入注册码”。
我的机器码:U2686167070
我的用户名:xu_wh
我的注册码:111222333444555666777888999000(随便输的)
输入完成后,会看到一个提示信息,指出软件在下次启动的时候会对注册码进行校验。在软件的安装目录看到有一个名为PIM.INI的文件。在这个文件里,有我们输入的用户名和机器码:
REGUSER=xu_wh
REGSN=111222333444555666777888999000
U2686167070=111222333444555666777888999000
注意到“REGSN”和“REGUSER”这样的字符串,就是将来我们破解的一个突破口。
用OD载入脱壳后的软件,然后搜索字符串:REGSN和REGUSER。在找到的地方下断。F9,运行至此:
007CBEAD |. B9 B0C97C00 mov ecx,dumped(?007CC9B0 ; ASCII "REGUSER"
007CBEB2 |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CBEB7 |. 8BC3 mov eax,ebx
007CBEB9 |. 8B38 mov edi,dword ptr ds:[eax]
007CBEBB |. FF17 call near dword ptr ds:[edi]
007CBEBD |. 8B55 D0 mov edx,dword ptr ss:[ebp-30] ; edx = 02545478; value here is 'xu_wh'
007CBEC0 |. A1 741B8300 mov eax,dword ptr ds:[831B74]
007CBEC5 |. E8 E28EC3FF call dumped(?00404DAC ; user name saved into 02545478 , 008386898 -> 02545478
007CBECA |. 6A 00 push 0
007CBECC |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
007CBECF |. 50 push eax
007CBED0 |. 8B0D 30238300 mov ecx,dword ptr ds:[832330] ; dumped(?00836934
007CBED6 |. 8B09 mov ecx,dword ptr ds:[ecx]
007CBED8 |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CBEDD |. 8BC3 mov eax,ebx ; edx is machine code 'U2686167070'
007CBEDF |. 8B38 mov edi,dword ptr ds:[eax]
007CBEE1 |. FF17 call near dword ptr ds:[edi] ; get user password from PIM.ini by U2686167070
007CBEE3 |. 837D FC 00 cmp dword ptr ss:[ebp-4],0 ; if password = 0, mean's input password once
007CBEE7 |. 75 16 jnz short dumped(?007CBEFF ; then jump
007CBEE9 |. 6A 00 push 0
007CBEEB |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
007CBEEE |. 50 push eax
007CBEEF |. B9 C0C97C00 mov ecx,dumped(?007CC9C0 ; ASCII "REGSN"
007CBEF4 |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CBEF9 |. 8BC3 mov eax,ebx
如果输过了密码,则跳过我们在007CBEEF设置的断点,到达这里:
007CBEFD |. FF17 call near dword ptr ds:[edi]
007CBEFF |> A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007CBF04 |. 8B55 FC mov edx,dword ptr ss:[ebp-4] ; edx is 0254F9AC, save input password
007CBF07 |. E8 A08EC3FF call dumped(?00404DAC
007CBF0C |. 6A 01 push 1
007CBF0E |. B9 D0C97C00 mov ecx,dumped(?007CC9D0 ; ASCII "SKIN"
007CBF13 |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CBF18 |. 8BC3 mov eax,ebx
007CBF1A |. 8B38 mov edi,dword ptr ds:[eax]
007CBF1C |. FF57 08 call near dword ptr ds:[edi+8]
007CBF1F |. 8945 F8 mov dword ptr ss:[ebp-8],eax
007CBF22 |. 6A 04 push 4
007CBF24 |. B9 E0C97C00 mov ecx,dumped(?007CC9E0 ; ASCII "STS"
007CBF29 |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CBF2E |. 8BC3 mov eax,ebx
007CBF30 |. 8B38 mov edi,dword ptr ds:[eax]
007CBF32 |. FF57 08 call near dword ptr ds:[edi+8]
007CBF35 |. 8945 F4 mov dword ptr ss:[ebp-C],eax
007CBF38 |. 6A 00 push 0
007CBF3A |. B9 ECC97C00 mov ecx,dumped(?007CC9EC ; ASCII "LEFT"
007CBF3F |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
...(略掉部分都是对pim.ini进行读操作) 我们一路F8,直到下面:
007CC905 |. B9 F8CD7C00 mov ecx,dumped(?007CCDF8 ; ASCII "IEMENU"
007CC90A |. BA 84C97C00 mov edx,dumped(?007CC984 ; ASCII "PIM"
007CC90F |. 8BC3 mov eax,ebx
007CC911 |. 8B38 mov edi,dword ptr ds:[eax]
007CC913 |. FF57 08 call near dword ptr ds:[edi+8]
007CC916 |. 48 dec eax
007CC917 |. 75 07 jnz short dumped(?007CC920
007CC919 |. 8BC6 mov eax,esi
007CC91B |. E8 C8F0FFFF call dumped(?007CB9E8
007CC920 |> 8BC3 mov eax,ebx
007CC922 |. E8 4175C3FF call dumped(?00403E68
007CC927 |. 33C0 xor eax,eax
007CC929 |. 5A pop edx
007CC92A |. 59 pop ecx
007CC92B |. 59 pop ecx
007CC92C |. 64:8910 mov dword ptr fs:[eax],edx
007CC92F |. 68 51C97C00 push dumped(?007CC951
007CC934 |> 8D45 BC lea eax,dword ptr ss:[ebp-44]
007CC937 |. BA 0A000000 mov edx,0A
007CC93C |. E8 3B84C3FF call dumped(?00404D7C
007CC941 |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
007CC944 |. E8 0F84C3FF call dumped(?00404D58
007CC949 \. C3 retn
可以知道这部分程序的功能是从配置文件中读出所需的配置信息。程序返回到:
007AC2EC . E8 17FB0100 call dumped(?007CBE08
007AC2F1 . 8B03 mov eax,dword ptr ds:[ebx]
007AC2F3 . E8 6C1A0200 call dumped(?007CDD64 ; 在处007AC2F3,F7跟进。此时EDX = 02584330 -> password
007AC2F8 . A1 941F8300 mov eax,dword ptr ds:[831F94]
007AC2FD . 8B00 mov eax,dword ptr ds:[eax]
007AC2FF . C640 5B 01 mov byte ptr ds:[eax+5B],1
007AC303 . 8B45 FC mov eax,dword ptr ss:[ebp-4]
007AC306 . E8 99B9CCFF call dumped(?00477CA4
我们来到007CDD64:
007CDD64 $ 55 push ebp
007CDD65 . 8BEC mov ebp,esp
007CDD67 . B9 18000000 mov ecx,18
007CDD6C > 6A 00 push 0
007CDD6E . 6A 00 push 0
007CDD70 . 49 dec ecx
007CDD71 .^ 75 F9 jnz short dumped(?007CDD6C
007CDD73 . 51 push ecx
007CDD74 . 53 push ebx
007CDD75 . 56 push esi
007CDD76 . 57 push edi
007CDD77 . 8945 FC mov dword ptr ss:[ebp-4],eax
007CDD7A . 8B1D 2C1F8300 mov ebx,dword ptr ds:[831F2C] ; dumped(?0083687C
007CDD80 . 8D75 E0 lea esi,dword ptr ss:[ebp-20]
007CDD83 . 33C0 xor eax,eax
007CDD85 . 55 push ebp
007CDD86 . 68 ECF57C00 push dumped(?007CF5EC
007CDD8B . 64:FF30 push dword ptr fs:[eax]
在007CDD64中,很大一部分的功能是对临时EXCEL表进行操作,与我们破解无关。我们在这里一路F8,直到
007CEFEC . 8B45 FC mov eax,dword ptr ss:[ebp-4]
007CEFEF . 8B80 940F0000 mov eax,dword ptr ds:[eax+F94] ; eax=A01BA81E(它的生成在下面有说明)
007CEFF5 . E8 7616FCFF call dumped(?00790670 ; 在这里生成伪注册码。不用管它的详细算法
007CEFFA . 8B85 6CFFFFFF mov eax,dword ptr ss:[ebp-94] ; edx=c3d8e946a83746
007CF000 . 8D95 70FFFFFF lea edx,dword ptr ss:[ebp-90]
007CF006 . E8 C117FCFF call dumped(?007907CC ; 生成真正的注册码,F7跟进,下面就是算法
007CF00B . 8B95 70FFFFFF mov edx,dword ptr ss:[ebp-90]
007CF011 . A1 18188300 mov eax,dword ptr ds:[831818]
007CF016 . E8 915DC3FF call dumped(?00404DAC
007CF01B . 8B15 A81D8300 mov edx,dword ptr ds:[831DA8] ; dumped(?0083689C
007CF021 . 8B12 mov edx,dword ptr ds:[edx] ; EDX中存放我们输入的注册码111222333444555666777888999000
007CF023 . A1 18188300 mov eax,dword ptr ds:[831818]
007CF028 . 8B00 mov eax,dword ptr ds:[eax] ; EAX中存放在007907CC处生成的注册码b417d593d4834
007CF02A . E8 2D63C3FF call dumped(?0040535C ; 对真假注册码进行对比,我们在这里F7跟进,看看是怎么比较的。
007CF02F . 85C0 test eax,eax
007CF031 /74 0D je short dumped(?007CF040 ; 通常,在这里是一个爆破点但是程序还在别的地方对注册码进行判断,所以,仅仅在这里实施爆破是不行的。还要在后面进行爆破。
下面是真正的算法,该算法根据机器码算出序列号,是我们关注的重点之一。
007907CC /$ 55 push ebp
007907CD |. 8BEC mov ebp,esp
007907CF |. 83C4 C0 add esp,-40
007907D2 |. 53 push ebx
007907D3 |. 56 push esi
007907D4 |. 33C9 xor ecx,ecx
007907D6 |. 894D C0 mov dword ptr ss:[ebp-40],ecx
007907D9 |. 894D C4 mov dword ptr ss:[ebp-3C],ecx
007907DC |. 894D C8 mov dword ptr ss:[ebp-38],ecx
007907DF |. 894D F4 mov dword ptr ss:[ebp-C],ecx
007907E2 |. 894D F0 mov dword ptr ss:[ebp-10],ecx
007907E5 |. 8955 F8 mov dword ptr ss:[ebp-8],edx
007907E8 |. 8945 FC mov dword ptr ss:[ebp-4],eax
007907EB |. 8B45 FC mov eax,dword ptr ss:[ebp-4]
007907EE |. E8 154AC7FF call dumped(?00405208
007907F3 |. 8D75 DC lea esi,dword ptr ss:[ebp-24]
007907F6 |. 33C0 xor eax,eax
007907F8 |. 55 push ebp
007907F9 |. 68 F70A7900 push dumped(?00790AF7
007907FE |. 64:FF30 push dword ptr fs:[eax]
00790801 |. 64:8920 mov dword ptr fs:[eax],esp
00790804 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00790807 |. 8B55 FC mov edx,dword ptr ss:[ebp-4]
0079080A |. E8 E145C7FF call dumped(?00404DF0
0079080F |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00790812 |. B9 01000000 mov ecx,1
00790817 |. BA 01000000 mov edx,1
0079081C |. E8 974AC7FF call dumped(?004052B8
00790821 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00790824 |. B9 01000000 mov ecx,1
00790829 |. BA 02000000 mov edx,2
0079082E |. E8 854AC7FF call dumped(?004052B8
00790833 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00790836 |. B9 01000000 mov ecx,1
0079083B |. BA 03000000 mov edx,3
00790840 |. E8 734AC7FF call dumped(?004052B8
00790845 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00790848 |. B9 01000000 mov ecx,1
0079084D |. BA 06000000 mov edx,6
00790852 |. E8 614AC7FF call dumped(?004052B8
00790857 |. 8B45 F4 mov eax,dword ptr ss:[ebp-C]
0079085A |. E8 619CC7FF call dumped(?0040A4C0
0079085F |. 8BD8 mov ebx,eax ; eax=e8242862,eax是由硬盘的序列号得来的
00790861 |. F7D3 not ebx ; ebx=17DBD79D,ebx是对eax取反
00790863 |. 81F3 22211276 xor ebx,76122122 ; ebx=61C9F6BF,ebx与76122122进行异或
以下部分是分别取出ebx中的4个byte
00790869 |. 8BC3 mov eax,ebx
0079086B |. 25 000000FF and eax,FF000000
00790870 |. C1E8 18 shr eax,18 ; eax=61
00790873 |. 8906 mov dword ptr ds:[esi],eax
00790875 |. 8BC3 mov eax,ebx
00790877 |. 25 0000FF00 and eax,0FF0000
0079087C |. C1E8 10 shr eax,10
0079087F |. 8946 04 mov dword ptr ds:[esi+4],eax ; eax = C9
00790882 |. 8BC3 mov eax,ebx
00790884 |. 25 00FF0000 and eax,0FF00
00790889 |. C1E8 08 shr eax,8 ; eax=F6
0079088C |. 8946 08 mov dword ptr ds:[esi+8],eax
0079088F |. 8BC3 mov eax,ebx
00790891 |. 25 FF000000 and eax,0FF
00790896 |. 8946 0C mov dword ptr ds:[esi+C],eax ; eax=BF
提取后的值放分别放在 ds:[esi],ds:[esi+4],ds:[esi+8],ds:[esi+C],下面分别对这四个值进行计算:
00790899 |. 8B16 mov edx,dword ptr ds:[esi] ; edx = 61
0079089B |. 81E2 C0000000 and edx,0C0 ; edx = 40
007908A1 |. 8B4E 04 mov ecx,dword ptr ds:[esi+4] ; ecx=C9
007908A4 |. 81E1 C0000000 and ecx,0C0 ; ecx=C0
007908AA |. C1E9 02 shr ecx,2 ; ecx=30
007908AD |. 03D1 add edx,ecx ; edx=70
007908AF |. 8B4E 08 mov ecx,dword ptr ds:[esi+8] ; ecx=f6
007908B2 |. 81E1 C0000000 and ecx,0C0 ; ecx=C0
007908B8 |. C1E9 04 shr ecx,4 ; ecx=0C
007908BB |. 03D1 add edx,ecx ; edx=7C
007908BD |. 25 C0000000 and eax,0C0 ; eax=80
007908C2 |. C1E8 06 shr eax,6 ; eax=02
007908C5 |. 03D0 add edx,eax ; edx=7E
007908C7 |. 8955 CC mov dword ptr ss:[ebp-34],edx
007908CA |. 8B06 mov eax,dword ptr ds:[esi] ; eax=61
007908CC |. 83E0 30 and eax,30 ; eax=20
007908CF |. C1E0 02 shl eax,2 ; eax=80
007908D2 |. 8B56 04 mov edx,dword ptr ds:[esi+4] ; edx=C9
007908D5 |. 83E2 30 and edx,30 ; edx=00
007908D8 |. 03C2 add eax,edx ; eax=80
007908DA |. 8B56 08 mov edx,dword ptr ds:[esi+8] ; edx=F6
007908DD |. 83E2 30 and edx,30 ; edx=30
007908E0 |. C1EA 02 shr edx,2 ; edx=0C
007908E3 |. 03C2 add eax,edx ; eax=8C
007908E5 |. 8B56 0C mov edx,dword ptr ds:[esi+C] ; edx=BF
007908E8 |. 83E2 30 and edx,30 ; edx=30
007908EB |. C1EA 04 shr edx,4 ; edx=03
007908EE |. 03C2 add eax,edx ; eax=8F
007908F0 |. 8945 D0 mov dword ptr ss:[ebp-30],eax
007908F3 |. 8B06 mov eax,dword ptr ds:[esi] ; eax=61
007908F5 |. 83E0 0C and eax,0C ; eax=00
007908F8 |. C1E0 04 shl eax,4 ; eax=00
007908FB |. 8B56 04 mov edx,dword ptr ds:[esi+4] ; edx=C9
007908FE |. 83E2 0C and edx,0C ; edx=08
00790901 |. C1E2 02 shl edx,2 ; edx=20
00790904 |. 03C2 add eax,edx ; eax=20
00790906 |. 8B56 08 mov edx,dword ptr ds:[esi+8]
00790909 |. 83E2 0C and edx,0C
0079090C |. 03C2 add eax,edx
0079090E |. 8B56 0C mov edx,dword ptr ds:[esi+C]
00790911 |. 83E2 0C and edx,0C
00790914 |. C1EA 02 shr edx,2
00790917 |. 03C2 add eax,edx
00790919 |. 8945 D4 mov dword ptr ss:[ebp-2C],eax ; eax=27
0079091C |. 8B06 mov eax,dword ptr ds:[esi]
0079091E |. 83E0 03 and eax,3
00790921 |. C1E0 06 shl eax,6
00790924 |. 8B56 04 mov edx,dword ptr ds:[esi+4]
00790927 |. 83E2 03 and edx,3
0079092A |. C1E2 04 shl edx,4
0079092D |. 03C2 add eax,edx
0079092F |. 8B56 08 mov edx,dword ptr ds:[esi+8]
00790932 |. 83E2 03 and edx,3
00790935 |. C1E2 02 shl edx,2
00790938 |. 03C2 add eax,edx
0079093A |. 8B56 0C mov edx,dword ptr ds:[esi+C]
0079093D |. 83E2 03 and edx,3
00790940 |. 03C2 add eax,edx
00790942 |. 8945 D8 mov dword ptr ss:[ebp-28],eax ; eax=5B
00790945 |. 8B5D CC mov ebx,dword ptr ss:[ebp-34]
00790948 |. C1E3 18 shl ebx,18
0079094B |. 8B45 D0 mov eax,dword ptr ss:[ebp-30]
0079094E |. C1E0 10 shl eax,10
00790951 |. 03D8 add ebx,eax
00790953 |. 8B45 D4 mov eax,dword ptr ss:[ebp-2C]
00790956 |. C1E0 08 shl eax,8
00790959 |. 03D8 add ebx,eax
0079095B |. 035D D8 add ebx,dword ptr ss:[ebp-28]
0079095E |. 8BC3 mov eax,ebx
00790960 |. 25 000000FF and eax,FF000000
00790965 |. C1E8 18 shr eax,18
00790968 |. 8906 mov dword ptr ds:[esi],eax ; eax=7E
0079096A |. 8BC3 mov eax,ebx
0079096C |. 25 0000FF00 and eax,0FF0000
00790971 |. C1E8 10 shr eax,10
00790974 |. 8946 04 mov dword ptr ds:[esi+4],eax
00790977 |. 8BC3 mov eax,ebx
00790979 |. 25 00FF0000 and eax,0FF00
0079097E |. C1E8 08 shr eax,8
00790981 |. 8946 08 mov dword ptr ds:[esi+8],eax
00790984 |. 81E3 FF000000 and ebx,0FF
0079098A |. 895E 0C mov dword ptr ds:[esi+C],ebx
0079098D |. 8B06 mov eax,dword ptr ds:[esi]
0079098F |. 8BD0 mov edx,eax
00790991 |. 81E2 F0000000 and edx,0F0
00790997 |. C1EA 04 shr edx,4
0079099A |. 83E0 0F and eax,0F
0079099D |. C1E0 04 shl eax,4
007909A0 |. 03D0 add edx,eax
007909A2 |. 8916 mov dword ptr ds:[esi],edx
007909A4 |. 8B46 04 mov eax,dword ptr ds:[esi+4]
007909A7 |. 8BD0 mov edx,eax
007909A9 |. 81E2 F0000000 and edx,0F0
007909AF |. C1EA 04 shr edx,4
007909B2 |. 83E0 0F and eax,0F
007909B5 |. C1E0 04 shl eax,4
007909B8 |. 03D0 add edx,eax
007909BA |. 8956 04 mov dword ptr ds:[esi+4],edx
007909BD |. 8B46 08 mov eax,dword ptr ds:[esi+8]
007909C0 |. 8BD0 mov edx,eax
007909C2 |. 81E2 F0000000 and edx,0F0
007909C8 |. C1EA 04 shr edx,4
007909CB |. 83E0 0F and eax,0F
007909CE |. C1E0 04 shl eax,4
007909D1 |. 03D0 add edx,eax
007909D3 |. 8956 08 mov dword ptr ds:[esi+8],edx
007909D6 |. 8B46 0C mov eax,dword ptr ds:[esi+C]
007909D9 |. 8BD0 mov edx,eax
007909DB |. 81E2 F0000000 and edx,0F0
007909E1 |. C1EA 04 shr edx,4
007909E4 |. 83E0 0F and eax,0F
007909E7 |. C1E0 04 shl eax,4
007909EA |. 03D0 add edx,eax
007909EC |. 8956 0C mov dword ptr ds:[esi+C],edx
007909EF |. 8B5E 04 mov ebx,dword ptr ds:[esi+4]
007909F2 |. C1E3 18 shl ebx,18
007909F5 |. 8B06 mov eax,dword ptr ds:[esi]
007909F7 |. C1E0 10 shl eax,10
007909FA |. 03D8 add ebx,eax
007909FC |. C1E2 08 shl edx,8
007909FF |. 03DA add ebx,edx
00790A01 |. 035E 08 add ebx,dword ptr ds:[esi+8]
00790A04 |. 8BC3 mov eax,ebx ; EAX=F8E7B572,它是运算的最终结果。
00790A06 |. 33D2 xor edx,edx
00790A08 |. 52 push edx ; /Arg2 => 00000000
00790A09 |. 50 push eax ; |Arg1
00790A0A |. 8D45 F0 lea eax,dword ptr ss:[ebp-10] ; |
00790A0D |. E8 CA99C7FF call dumped(?0040A3DC ; 将 F8E7B572 转换成10进制数
00790A12 |. 8B45 F0 mov eax,dword ptr ss:[ebp-10] ; eax=4175934834
下面对EAX中的10进制数进行运算,生成3个单独的字符,这里生成的是b,d,d:
00790A15 |. 0FB600 movzx eax,byte ptr ds:[eax] ; eax='0034'
00790A18 |. 8B55 F0 mov edx,dword ptr ss:[ebp-10]
00790A1B |. 0FB652 01 movzx edx,byte ptr ds:[edx+1] ; edx='0031'
00790A1F |. 03C2 add eax,edx ; eax='0065'
00790A21 |. B9 05000000 mov ecx,5
00790A26 |. 99 cdq
00790A27 |. F7F9 idiv ecx ; edx=1;eax=14
00790A29 |. 80C2 61 add dl,61 ; edx=62
00790A2C |. 8855 ED mov byte ptr ss:[ebp-13],dl ; dl is 'b'
00790A2F |. 8B45 F0 mov eax,dword ptr ss:[ebp-10]
00790A32 |. 0FB640 02 movzx eax,byte ptr ds:[eax+2]
00790A36 |. 8B55 F0 mov edx,dword ptr ss:[ebp-10] ; eax=37
00790A39 |. 0FB652 03 movzx edx,byte ptr ds:[edx+3] ; edx=35
00790A3D |. 03C2 add eax,edx ; eax=6C
00790A3F |. B9 05000000 mov ecx,5
00790A44 |. 99 cdq
00790A45 |. F7F9 idiv ecx ; eax=15,edx=3
00790A47 |. 80C2 61 add dl,61 ; edx=64
00790A4A |. 8855 EE mov byte ptr ss:[ebp-12],dl ; dl is 'd'
00790A4D |. 8B45 F0 mov eax,dword ptr ss:[ebp-10]
00790A50 |. 0FB640 04 movzx eax,byte ptr ds:[eax+4]
00790A54 |. 8B55 F0 mov edx,dword ptr ss:[ebp-10] ; eax=39
00790A57 |. 0FB652 05 movzx edx,byte ptr ds:[edx+5] ; edx=33
00790A5B |. 03C2 add eax,edx ; eax=6C
00790A5D |. B9 05000000 mov ecx,5
00790A62 |. 99 cdq
00790A63 |. F7F9 idiv ecx ; eax=15;edx=3
00790A65 |. 80C2 61 add dl,61 ; dl=64
00790A68 |. 8855 EF mov byte ptr ss:[ebp-11],dl ; dl is 'd'
00790A6B |. 8D45 C8 lea eax,dword ptr ss:[ebp-38]
00790A6E |. 8A55 ED mov dl,byte ptr ss:[ebp-13]
在生成了b,d,d后,将这三个字符插入到相应的位置,b放到第一个数字前,d放到第4个数字前,d放到第7个数字前。
00790A71 |. E8 C244C7FF call dumped(?00404F38
00790A76 |. 8B45 C8 mov eax,dword ptr ss:[ebp-38]
00790A79 |. 8D55 F0 lea edx,dword ptr ss:[ebp-10]
00790A7C |. B9 01000000 mov ecx,1
00790A81 |. E8 7A48C7FF call dumped(?00405300 ; insert b
00790A86 |. 8D45 C4 lea eax,dword ptr ss:[ebp-3C]
00790A89 |. 8A55 EE mov dl,byte ptr ss:[ebp-12]
00790A8C |. E8 A744C7FF call dumped(?00404F38
00790A91 |. 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
00790A94 |. 8D55 F0 lea edx,dword ptr ss:[ebp-10]
00790A97 |. B9 05000000 mov ecx,5
00790A9C |. E8 5F48C7FF call dumped(?00405300 ; insert d
00790AA1 |. 8D45 C0 lea eax,dword ptr ss:[ebp-40]
00790AA4 |. 8A55 EF mov dl,byte ptr ss:[ebp-11]
00790AA7 |. E8 8C44C7FF call dumped(?00404F38
00790AAC |. 8B45 C0 mov eax,dword ptr ss:[ebp-40]
00790AAF |. 8D55 F0 lea edx,dword ptr ss:[ebp-10]
00790AB2 |. B9 09000000 mov ecx,9
00790AB7 |. E8 4448C7FF call dumped(?00405300 ; insert d
00790ABC |. 8B45 F8 mov eax,dword ptr ss:[ebp-8]
00790ABF |. 8B55 F0 mov edx,dword ptr ss:[ebp-10]
00790AC2 |. E8 E542C7FF call dumped(?00404DAC
00790AC7 |. 33C0 xor eax,eax
00790AC9 |. 5A pop edx
00790ACA |. 59 pop ecx
00790ACB |. 59 pop ecx
00790ACC |. 64:8910 mov dword ptr fs:[eax],edx
00790ACF |. 68 FE0A7900 push dumped(?00790AFE
00790AD4 |> 8D45 C0 lea eax,dword ptr ss:[ebp-40]
00790AD7 |. BA 03000000 mov edx,3
00790ADC |. E8 9B42C7FF call dumped(?00404D7C
00790AE1 |. 8D45 F0 lea eax,dword ptr ss:[ebp-10]
00790AE4 |. BA 02000000 mov edx,2
00790AE9 |. E8 8E42C7FF call dumped(?00404D7C
00790AEE |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
00790AF1 |. E8 6242C7FF call dumped(?00404D58
00790AF6 \. C3 retn ; 生成真正的注册码后,返回到上面007CF00B执行。
下面是对真假注册码进行比较的部分:
0040535C /$ 85C0 test eax,eax
0040535E |. 74 40 je short dumped(?004053A0
00405360 |. 85D2 test edx,edx
00405362 |. 74 31 je short dumped(?00405395
00405364 |. 53 push ebx
00405365 |. 56 push esi
00405366 |. 57 push edi
00405367 |. 89C6 mov esi,eax ; esi中存放真正的注册码
00405369 |. 89D7 mov edi,edx ; edi中存放我们输入的注册码
0040536B |. 8B4F FC mov ecx,dword ptr ds:[edi-4] ; ecx中存放我们输入的注册码的长度
0040536E |. 57 push edi
0040536F |. 8B56 FC mov edx,dword ptr ds:[esi-4] ; edx中存放真注册码的长度
00405372 |. 4A dec edx
00405373 |. 78 1B js short dumped(?00405390
00405375 |. 8A06 mov al,byte ptr ds:[esi] ; al中放真注册码的第一个字符
00405377 |. 46 inc esi
00405378 |. 29D1 sub ecx,edx
0040537A |. 7E 14 jle short dumped(?00405390
0040537C |> F2:AE /repne scas byte ptr es:[edi] ; 在我们输入的注册码中找到程序生成的注册码的子串
0040537E |. 75 10 |jnz short dumped(?00405390
00405380 |. 89CB |mov ebx,ecx
00405382 |. 56 |push esi
00405383 |. 57 |push edi
00405384 |. 89D1 |mov ecx,edx
00405386 |. F3:A6 |repe cmps byte ptr es:[edi],byte>
00405388 |. 5F |pop edi
00405389 |. 5E |pop esi
0040538A |. 74 0C |je short dumped(?00405398
0040538C |. 89D9 |mov ecx,ebx
0040538E |.^ EB EC \jmp short dumped(?0040537C
00405390 |> 5A pop edx
00405391 |. 31C0 xor eax,eax
00405393 |. EB 08 jmp short dumped(?0040539D
00405395 |> 31C0 xor eax,eax
00405397 |. C3 retn
00405398 |> 5A pop edx
00405399 |. 89F8 mov eax,edi
0040539B |. 29D0 sub eax,edx ; eax = 3, 41-3E = 3
0040539D |> 5F pop edi
0040539E |. 5E pop esi
0040539F |. 5B pop ebx
004053A0 \> C3 retn
通过对上面代码的分析,我们知道,只要程序生成注册码是我们输入的注册码的一个子串即可。因为程序还有另外一部分对注册码的其它部分进行校验。
我们在这里还应该注意到,真正注册码的生成和一个数有关:A01BA81E,这个数的产生和硬盘序列号有关,下面就是有关的算法:
00790624 /$ 83C4 F4 add esp,-0C
00790627 |. 6A 00 push 0 ; /pFileSystemNameSize = NULL
00790629 |. 6A 00 push 0 ; |pFileSystemNameBuffer = NULL
0079062B |. 8D4424 10 lea eax,dword ptr ss:[esp+10] ; |
0079062F |. 50 push eax ; |pFileSystemFlags
00790630 |. 8D4424 10 lea eax,dword ptr ss:[esp+10] ; |
00790634 |. 50 push eax ; |pMaxFilenameLength
00790635 |. 8D4424 10 lea eax,dword ptr ss:[esp+10] ; |
00790639 |. 50 push eax ; |pVolumeSerialNumber
0079063A |. 6A 00 push 0 ; |MaxVolumeNameSize = 0
0079063C |. 6A 00 push 0 ; |VolumeNameBuffer = NULL
0079063E |. 68 68067900 push dumped(?00790668 ; |RootPathName = "c:\\"
00790643 |. E8 DC74C7FF call <jmp.&kernel32.GetVolumeInfo>; \GetVolumeInformationA
00790648 |. 8B0424 mov eax,dword ptr ss:[esp]
0079064B |. 05 85000000 add eax,85
00790650 |. B9 22000000 mov ecx,22
00790655 |. 33D2 xor edx,edx
00790657 |. F7F1 div ecx
00790659 |. 6BC0 29 imul eax,eax,29 ; EAX = A01BA81E,下面的计算中要用到这个值
0079065C |. 890424 mov dword ptr ss:[esp],eax
0079065F |. 8B0424 mov eax,dword ptr ss:[esp]
00790662 |. 83C4 0C add esp,0C
00790665 \. C3 retn
三、破解二
通过对上面程序的分析,我们能得到部分注册码:b417d593d4834。输入这个注册码。然后重新运行该软件。在经过一段时间后,又会跳出注册的对话框。
在对软件进行反复跟踪分析后,发现程序会对在地址00836948和0083694C处的值进行检查,如果是00000003,程序认为是经过注册的,然后再次对注册码进行检查,如果检查正确,保持00000003不变,否则给这个变量赋00000002。
最后程序又对这个值进行检查,如果是00000002表示没有完全注册;如果是00000003表示程序是正确注册的。(复杂呀!)
另外,在对程序的分析中,注册码的长度不能小于14。程序对注册码的检查分为两种:
1)注册码的长度为14,程序使用密钥"YiISIvp * kb2W A9iIpC5 M#IbI kxIScYoWI='v2S2b'"进行验密;
2)注册码的长度>14,程序使用密钥“YqhNrd8K1JOsbfZVUatRgB3McDiExTSu5GjvPekL2w7AXWzlIyHmQn94Co6Fp0#S_”
和”_$#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789“作为密码字典。算法如下,
拿出待校验的注册码的第一字符,在第一个字符串中,查找出它的位置X,然后在第二个字符串中,
取出第X个字符作为新串的第一个字符。然后再取出待校验注册码的第二个字符 ,在第一个字符串中找到它的位置Y,
然后再从第二个字符串找到第Y个字符,作为新串的第二个字符。生成新的字符串后。用这个长为2的新串和待校验注册码的倒数第3位开始,
长度为2进行比较(如果是正确的注册码,应该相等)。然后再用待校验注册码的倒数第四位和0比,倒数第一位和1比。如果都相等了,我们的注册码校验就顺利通过了 :)
我们索性输入注册码为:b417d593d4834Yj1。
在00836948和0083694C处下硬件读断点,重新运行,在等到一段时间后。终于拦下来了 :)
007DE1F2 . 8338 03 cmp dword ptr ds:[eax],3 ; eax=00836948
007DE1F5 . 0F85 57020000 jnz dumped(?007DE452 ; 因为在程序启动的时候,从.ini文件中读取了注册码,已经完成了部分检查,所以ds:[eax]=3,在这里不跳转
007DE1FB . A1 A81D8300 mov eax,dword ptr ds:[831DA8] ; ds:[eax]中存放我们输入的注册码
007DE200 . 8338 00 cmp dword ptr ds:[eax],0 ; 当然这里不是0了 :)
007DE203 . 0F84 49020000 je dumped(?007DE452
007DE209 . A1 A81D8300 mov eax,dword ptr ds:[831DA8] ;
007DE20E . 8B00 mov eax,dword ptr ds:[eax] ; ds:[eax]再次拿到我们输入的注册码
007DE210 . E8 0B6EC2FF call dumped(?00405020 ; 取得注册码的长度
007DE215 8BF0 mov esi,eax ; 存入到esi中
007DE217 . A1 18188300 mov eax,dword ptr ds:[831818] ; eax=00836858
007DE21C . 8B00 mov eax,dword ptr ds:[eax] ; ds:[eax]中存放由程序自动生成的注册码
007DE21E . E8 FD6DC2FF call dumped(?00405020 ; 取得这个注册码的长度
007DE223 . 2BF0 sub esi,eax ; 两个注册码的长度相减,减的值放在esi中
007DE225 4E dec esi ; esi减1
007DE226 . 0F85 2E010000 jnz dumped(?007DE35A ; 如果不等于0,则跳转
007DE22C . 8D45 F8 lea eax,dword ptr ss:[ebp-8] ; 下面是对长度为14的密码进行校验的算法。这次我们先不对它进行分析
......
; 下面是对长度>14的密码进行校验的算法
007DE35A > 8D45 E4 lea eax,dword ptr ss:[ebp-1C] ; eax=0012FDD4
007DE35D . 50 push eax
007DE35E . 8D45 DC lea eax,dword ptr ss:[ebp-24] ; eax=0012FDCC
007DE361 . 50 push eax
007DE362 . A1 A81D8300 mov eax,dword ptr ds:[831DA8] ; eax=0083689C
007DE367 . 8B00 mov eax,dword ptr ds:[eax] ; eax=025764AC->'b417d593d4834Yj0'
007DE369 . B9 02000000 mov ecx,2 ; ecx=2
007DE36E . BA 01000000 mov edx,1 ; edx=1
007DE373 . E8 006FC2FF call dumped(?00405278 ; 00405278的作用是从ds:[eax]中得到起始位置为edx,长为ecx的子串
007DE378 . 8B45 DC mov eax,dword ptr ss:[ebp-24] ; 子串是'b4'
007DE37B . 8D55 E0 lea edx,dword ptr ss:[ebp-20] ; edx=12FDD0
007DE37E . E8 FD1DFBFF call dumped(?00790180 ; 在这里,我们F7跟进,见下面的分析。
007DE383 . 8B45 E0 mov eax,dword ptr ss:[ebp-20] ; eax=0258694C --> Yj0
007DE386 . B9 02000000 mov ecx,2
007DE38B . BA 01000000 mov edx,1
007DE390 . E8 E36EC2FF call dumped(?00405278 ; after this, eax=0012FDD4,save the first 2 chars of Yj0
007DE395 . 8B45 E4 mov eax,dword ptr ss:[ebp-1C] ; EAX=0254831C -> Yj
007DE398 . 50 push eax
007DE399 . 8D45 D8 lea eax,dword ptr ss:[ebp-28]
007DE39C . 50 push eax
007DE39D . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE3A2 . 8B00 mov eax,dword ptr ds:[eax]
007DE3A4 . E8 776CC2FF call dumped(?00405020 ; get the length of password input,it's 16
007DE3A9 . 8BD0 mov edx,eax
007DE3AB . 83EA 02 sub edx,2
007DE3AE . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE3B3 . 8B00 mov eax,dword ptr ds:[eax] ; eax=password input with length 16
007DE3B5 . B9 02000000 mov ecx,2
007DE3BA . E8 B96EC2FF call dumped(?00405278 ; get the substring with begin at edx,length ecx
007DE3BF . 8B55 D8 mov edx,dword ptr ss:[ebp-28] ; dex='Yj'
007DE3C2 . 58 pop eax
007DE3C3 . E8 9C6DC2FF call dumped(?00405164 ; 对用注册的前两位生成的'Yj'和注册码的倒数第3、2位进行比较
007DE3C8 . 74 0B je short dumped(?007DE3D5 ; 如果是正确的注册码,必须跳。
007DE3CA . A1 981F8300 mov eax,dword ptr ds:[831F98]
007DE3CF . C700 02000000 mov dword ptr ds:[eax],2 ; 不能执行到这里,否则,就会给00836948赋2
007DE3D5 > 8D45 D4 lea eax,dword ptr ss:[ebp-2C]
007DE3D8 . 50 push eax
007DE3D9 . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE3DE . 8B00 mov eax,dword ptr ds:[eax] ; ds:[eax]是待校验的注册码
007DE3E0 . E8 3B6CC2FF call dumped(?00405020 ; 取得注册码的长度
007DE3E5 . 8BD0 mov edx,eax
007DE3E7 . 83EA 03 sub edx,3
007DE3EA . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE3EF . 8B00 mov eax,dword ptr ds:[eax]
007DE3F1 . B9 01000000 mov ecx,1
007DE3F6 . E8 7D6EC2FF call dumped(?00405278 ; 从待校验注册码的倒数第四位取出1位‘4’
007DE3FB . 8B45 D4 mov eax,dword ptr ss:[ebp-2C]
007DE3FE . BA B4E47D00 mov edx,dumped(?007DE4B4 ; 在007DE4B4处是‘0’
007DE403 . E8 5C6DC2FF call dumped(?00405164 ; 在这里,这两个数也应该相等
007DE408 . 74 0B je short dumped(?007DE415 ; 否则就会给00836948处的赋2
007DE40A . A1 981F8300 mov eax,dword ptr ds:[831F98] ;
007DE40F . C700 02000000 mov dword ptr ds:[eax],2
007DE415 > 8D45 D0 lea eax,dword ptr ss:[ebp-30]
007DE418 . 50 push eax
007DE419 . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE41E . 8B00 mov eax,dword ptr ds:[eax]
007DE420 . E8 FB6BC2FF call dumped(?00405020 ; 取得注册码的长度
007DE425 . 8BD0 mov edx,eax ; 这个长度给edx,说明要取最后一位了 :)
007DE427 . A1 A81D8300 mov eax,dword ptr ds:[831DA8]
007DE42C . 8B00 mov eax,dword ptr ds:[eax]
007DE42E . B9 01000000 mov ecx,1 ; ecx=1
007DE433 . E8 406EC2FF call dumped(?00405278 ; 取出待校验注册码的最后一位 ‘1’
007DE438 . 8B45 D0 mov eax,dword ptr ss:[ebp-30]
007DE43B . BA CCE47D00 mov edx,dumped(?007DE4CC ; 与007DE4CC处的‘1’ 比较
007DE440 . E8 1F6DC2FF call dumped(?00405164 ; 这里也必须相等
007DE445 . 74 0B je short dumped(?007DE452
007DE447 . A1 981F8300 mov eax,dword ptr ds:[831F98] ; 否则就会给00836948处的赋2
007DE44C . C700 02000000 mov dword ptr ds:[eax],2
007DE452 > 33C0 xor eax,eax
007DE454 . 5A pop edx
007DE455 . 59 pop ecx
007DE456 . 59 pop ecx
007DE457 . 64:8910 mov dword ptr fs:[eax],edx
007DE45A . EB 15 jmp short dumped(?007DE471
007DE45C .^ E9 E75EC2FF jmp dumped(?00404348
007DE461 . A1 981F8300 mov eax,dword ptr ds:[831F98]
007DE466 . C700 02000000 mov dword ptr ds:[eax],2
007DE46C . E8 0363C2FF call dumped(?00404774
007DE471 > A1 981F8300 mov eax,dword ptr ds:[831F98]
007DE476 . 8B00 mov eax,dword ptr ds:[eax]
如果要爆破,最简单的方法,就是在007DE1F5进行跳转,这样就不会对我们输入的注册码做后期校验了。
下面的算法,是取出注册码的第一个字符b,它在‘Y..’ string的位置是第13,而在‘_$’中第13个字符是‘j’。取出注册码的第二个字符4,它在‘Y..’ string的位置是第56,而在‘_$’中第56个字符是‘0’。所以,新的字符串是‘j0’,然后在‘j0’前加上‘Y...’ string的第一个字符‘Y’,得到‘Yj0’.
00790180 /$ 55 push ebp
00790181 |. 8BEC mov ebp,esp
00790183 |. 33C9 xor ecx,ecx
00790185 |. 51 push ecx
00790186 |. 51 push ecx
00790187 |. 51 push ecx
00790188 |. 51 push ecx
00790189 |. 51 push ecx
0079018A |. 53 push ebx
0079018B |. 56 push esi ; esi=3
0079018C |. 8BF2 mov esi,edx
0079018E |. 8945 FC mov dword ptr ss:[ebp-4],eax ; ss:0012FD8C 025901F0 -> 'b4'
00790191 |. 8B45 FC mov eax,dword ptr ss:[ebp-4]
00790194 |. E8 6F50C7FF call dumped(?00405208 ; get the length of 'b4' save EDX=2
00790199 |. 33C0 xor eax,eax
0079019B |. 55 push ebp
0079019C |. 68 39027900 push dumped(?00790239
007901A1 |. 64:FF30 push dword ptr fs:[eax]
007901A4 |. 64:8920 mov dword ptr fs:[eax],esp
007901A7 |. BB 01000000 mov ebx,1 ; ebx=1
007901AC |. 8D45 F8 lea eax,dword ptr ss:[ebp-8]
007901AF |. BA 50027900 mov edx,dumped(?00790250 ; ASCII "YqhNrd8K1JOsbfZVUatRgB3McDiExTSu5GjvPekL2w7AXWzlIyHmQn94Co6Fp0#S_"
007901B4 |. E8 374CC7FF call dumped(?00404DF0 ; after this; ss:12FD88 = string above
007901B9 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
007901BC |. BA 9C027900 mov edx,dumped(?0079029C ; ASCII "_$#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
007901C1 |. E8 2A4CC7FF call dumped(?00404DF0 ; after this, ss:12FD84 point to string above
007901C6 |. 8D45 F0 lea eax,dword ptr ss:[ebp-10] ; eax=0012FD80
007901C9 |. 50 push eax
007901CA |. B9 01000000 mov ecx,1
007901CF |. 8BD3 mov edx,ebx ; ecx=edx=dbx=1
007901D1 |. 8B45 F8 mov eax,dword ptr ss:[ebp-8] ; eax='Yq...' string
007901D4 |. E8 9F50C7FF call dumped(?00405278 ; got the first ECX chars from eax string. saved into [ss:ebp-10]
007901D9 |. 8D45 F8 lea eax,dword ptr ss:[ebp-8] ; EAX=0012FD88
007901DC |. 8B55 F8 mov edx,dword ptr ss:[ebp-8] ; EDX='Yq...' string
007901DF |. E8 444EC7FF call dumped(?00405028
007901E4 |. 8D45 F8 lea eax,dword ptr ss:[ebp-8] ; eax=0012FD88
007901E7 |. 50 push eax
007901E8 |. B9 41000000 mov ecx,41 ; ecx=41(the length of 'Yq...' string)
007901ED |. 8BD3 mov edx,ebx ; ebx=dex=1
007901EF |. 8B45 F8 mov eax,dword ptr ss:[ebp-8] ; eax='Y...' string
007901F2 |. E8 8150C7FF call dumped(?00405278 ; F7 to enter this one, check 008335C8
007901F7 |. 8D45 EC lea eax,dword ptr ss:[ebp-14]
007901FA |. 50 push eax
007901FB |. 8B4D F4 mov ecx,dword ptr ss:[ebp-C] ; string '_$...'
007901FE |. 8B55 F8 mov edx,dword ptr ss:[ebp-8] ; string 'Yq...'
00790201 |. 8B45 FC mov eax,dword ptr ss:[ebp-4] ; eax=first 2 chars in input password
00790204 |. E8 B3FEFFFF call dumped(?007900BC
00790209 |. 8B55 EC mov edx,dword ptr ss:[ebp-14] ; edx = 'j0', this was encrypted chars
0079020C |. 8D45 F0 lea eax,dword ptr ss:[ebp-10]
0079020F |. E8 144EC7FF call dumped(?00405028
00790214 |. 8BC6 mov eax,esi
00790216 |. 8B55 F0 mov edx,dword ptr ss:[ebp-10]
00790219 |. E8 8E4BC7FF call dumped(?00404DAC
0079021E |. 33C0 xor eax,eax
00790220 |. 5A pop edx
00790221 |. 59 pop ecx
00790222 |. 59 pop ecx
00790223 |. 64:8910 mov dword ptr fs:[eax],edx
00790226 |. 68 40027900 push dumped(?00790240
0079022B |> 8D45 EC lea eax,dword ptr ss:[ebp-14]
0079022E |. BA 05000000 mov edx,5
00790233 |. E8 444BC7FF call dumped(?00404D7C
00790238 \. C3 retn ; 返回到上面
============================================================================================================
上面我们完成了对注册码的所有分析,本来想写注册机的,可是我的汇编已经有8年没有用过了。我会努力的!! 感兴趣的大侠可以根据我的算法分析自己写吧 :(
另外提醒,如果是爆破,有两个地方要改的。不要只改一个地方 :)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)