【文章标题】: Prophet 5.0 时间限制+NAG的破解
【文章作者】: 斜阳残雪
【作者邮箱】: zlm324@126.com
【下载地址】: 到我网盘下载吧:http://www.edisk.org/?zlm324 (内附破解的程序和注册表补丁,用哪个随便)
【编写语言】: VC++ 4.x
【使用工具】: Ollydbg
【软件介绍】: 据说是非常昂贵的精算软件^_^
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这个是同学让我帮他破的,据说是价值好几百万的软件。
我们先不管它的价值是多少,在我们眼前它就仅仅是一个程序而已。
先试用,发现有时间限制和NAG。
1、破解时间限制:
OD载入,查找字符串,发现"There are %d days remaining..."字样,双击跟入:
00401E24 /. 55 push ebp
00401E25 |. 8BEC mov ebp, esp
00401E27 |. 81EC 80000000 sub esp, 80
00401E2D |. 53 push ebx
00401E2E |. 56 push esi
00401E2F |. 57 push edi
00401E30 |. 8BF1 mov esi, ecx
00401E32 |. E8 E9590000 call <jmp.&MFC40.#4173>
00401E37 |. A1 8CB44000 mov eax, dword ptr [40B48C]
00401E3C |. 8BCE mov ecx, esi
00401E3E |. 50 push eax
00401E3F |. 8D5E 60 lea ebx, dword ptr [esi+60]
00401E42 |. 68 FE030000 push 3FE
00401E47 |. E8 C2590000 call <jmp.&MFC40.#2707>
00401E4C |. 8BC8 mov ecx, eax
00401E4E |. E8 B5590000 call <jmp.&MFC40.#5492>
00401E53 |. 8D4D 80 lea ecx, dword ptr [ebp-80]
00401E56 |. 8B3D 18CC4000 mov edi, dword ptr [<&MSVCRT40.sprin>; MSVCRT40.sprintf
00401E5C |. FF33 push dword ptr [ebx] ; /<%d>
00401E5E |. 68 ECB44000 push 0040B4EC ; |format = "There are %d days remaining in
your free evaluation period."
00401E63 |. 51 push ecx ; |s
00401E64 |. FFD7 call edi ; \sprintf
单步到00401E5C push dword ptr [ebx]时发现ebx中的数值指向的地址中存在"3C",即十进制的60。(因为我是第一天试用,所
以是60。)
但是这个数值是从哪里来的呢?我们对那个内存地址下写入断点。但是麻烦就来了:系统初始化的时候要频繁地改动这个地址的
数据,我们跟不起啊。
那我们换个方法,对注册表的读写下断点bp RegQueryValueExA。
发现程序读取键值"TrialPeriodStart",呵呵,我们就在它读取了这个键值之后再下内存断点。
读取了"TrialPeriodStart"之后,程序断在这里:
00405595 /$ 56 push esi
00405596 |. 8B41 6C mov eax, dword ptr [ecx+6C]
00405599 |. 8BF1 mov esi, ecx
0040559B |. 85C0 test eax, eax
0040559D |. 74 17 je short 004055B6
0040559F |. 68 E8B64000 push 0040B6E8 ; /s2 = "/regFirst"
004055A4 |. 50 push eax ; |s1
004055A5 |. E8 222A0000 call <jmp.&MSVCRT40.strcmp> ; \strcmp
004055AA |. 83C4 08 add esp, 8
004055AD |. 85C0 test eax, eax
004055AF |. B8 00000000 mov eax, 0
004055B4 |. 74 16 je short 004055CC
004055B6 |> 6A 00 push 0
004055B8 |. 8B06 mov eax, dword ptr [esi]
004055BA |. 68 D4B64000 push 0040B6D4 ; ASCII "TrialPeriodStart"
004055BF |. 8BCE mov ecx, esi
004055C1 |. 68 C0B54000 push 0040B5C0 ; ASCII "Main"
004055C6 |. FF90 C4000000 call dword ptr [eax+C4]
004055CC |> 85C0 test eax, eax
004055CE |. 75 17 jnz short 004055E7
004055D0 |. E8 EF200000 call <jmp.&P0BASE.#581>
004055D5 |. 50 push eax ; /Arg3
004055D6 |. 8BCE mov ecx, esi ; |
004055D8 |. 68 D4B64000 push 0040B6D4 ; |Arg2 = 0040B6D4 ASCII "TrialPeriodStart"
004055DD |. 68 C0B54000 push 0040B5C0 ; |Arg1 = 0040B5C0 ASCII "Main"
004055E2 |. E8 82000000 call 00405669 ; \prophet.00405669
004055E7 |> 5E pop esi
004055E8 \. C3 retn
我们跟着返回:
0040456C . E8 24100000 call 00405595
00404571 . FF33 push dword ptr [ebx]
00404573 . 8BCE mov ecx, esi
00404575 . E8 4C0F0000 call 004054C6
0040457A . 85C0 test eax, eax
0040457C . 75 39 jnz short 004045B7
0040457E . 8BCE mov ecx, esi
00404580 . E8 3E0F0000 call 004054C3
00404585 . 85C0 test eax, eax
00404587 . 74 11 je short 0040459A
00404589 . C745 FC FFFFF>mov dword ptr [ebp-4], -1
00404590 . E8 7A000000 call 0040460F
00404595 .^ E9 91FDFFFF jmp 0040432B
0040459A > 8BCE mov ecx, esi
0040459C . E8 270E0000 call 004053C8
当执行过最后一个Call时,下了内存断点的地址内的数据发生变化,变成"3C"。
重新运行,跟入那个Call:
004053C8 /$ B8 5E544000 mov eax, 0040545E
004053CD |. E8 5E290000 call <jmp.&MSVCRT40._EH_prolog>
004053D2 |. 83EC 70 sub esp, 70
004053D5 |. 56 push esi
004053D6 |. 57 push edi
004053D7 |. 8BF1 mov esi, ecx
004053D9 |. 33FF xor edi, edi
004053DB |. 57 push edi
004053DC |. 8D4D 84 lea ecx, dword ptr [ebp-7C]
004053DF |. E8 D0C7FFFF call 00401BB4
004053E4 |. 8BCE mov ecx, esi
004053E6 |. 897D FC mov dword ptr [ebp-4], edi
004053E9 |. E8 FB010000 call 004055E9
发现执行过最后一个Call时EAX中出现"3C"。
重新运行,再跟入:
004055E9 /$ 53 push ebx ; PROPHET.0040B83C
004055EA |. 56 push esi
004055EB |. 8B71 6C mov esi, dword ptr [ecx+6C]
004055EE |. 57 push edi
004055EF |. 8BD9 mov ebx, ecx
004055F1 |. 85F6 test esi, esi
004055F3 |. 74 36 je short 0040562B
004055F5 |. BF F4B64000 mov edi, 0040B6F4 ; ASCII "/freeExpired"
004055FA |. 57 push edi ; /s => "/freeExpired"
004055FB |. E8 D2290000 call <jmp.&MSVCRT40.strlen> ; \strlen
00405600 |. 83C4 04 add esp, 4
00405603 |. 50 push eax ; /maxlen
00405604 |. 57 push edi ; |s2
00405605 |. 56 push esi ; |s1
00405606 |. FF15 FCCB4000 call dword ptr [<&MSVCRT40.strncmp>] ; \strncmp
0040560C |. 83C4 0C add esp, 0C
0040560F |. 85C0 test eax, eax
00405611 |. 75 18 jnz short 0040562B
00405613 |. 57 push edi ; /s
00405614 |. E8 B9290000 call <jmp.&MSVCRT40.strlen> ; \strlen
00405619 |. 83C4 04 add esp, 4
0040561C |. 0343 6C add eax, dword ptr [ebx+6C]
0040561F |. 50 push eax ; /s
00405620 |. FF15 00CC4000 call dword ptr [<&MSVCRT40.atoi>] ; \atoi
00405626 |. 83C4 04 add esp, 4
00405629 |. EB 22 jmp short 0040564D
0040562B |> 6A 00 push 0
0040562D |. 8B03 mov eax, dword ptr [ebx]
0040562F |. 68 D4B64000 push 0040B6D4 ; ASCII "TrialPeriodStart"
00405634 |. 8BCB mov ecx, ebx
00405636 |. 68 C0B54000 push 0040B5C0 ; ASCII "Main"
0040563B |. FF90 C4000000 call dword ptr [eax+C4]
00405641 |. 8BF0 mov esi, eax
00405643 E8 7C200000 call <jmp.&P0BASE.#581>
00405648 |. 2BF0 sub esi, eax
0040564A |. 8D46 3C lea eax, dword ptr [esi+3C] ;执行过这里之后,eax中出现3c
0040564D |> 5F pop edi
0040564E |. 5E pop esi
0040564F |. 5B pop ebx
00405650 \. C3 retn
跟踪得知,在执行过0040564A lea eax, dword ptr [esi+3C]之后,eax中数值变成3C。
查看前面的几行代码:
00405641 mov esi, eax
00405643 call <jmp.&P0BASE.#581>
00405648 sub esi, eax
当执行到第一句的时候,eax中数据是357B(就是TrialPeriodStart的值)。
那么程序的意图很明显了:第二句Call一定是计算当前已经试用的天数,然后跟起始的天数相减,得到还可以试用的天数。
我们把那句Call <jmp.&P0BASE.#581>给nop掉,这样的话sub esi,eax过后esi永远都是0,就是说试用天数永远都不变了。
到此为止,时间限制破解完毕。
2、破解NAG:
下bp ShowWindow,F9几次后到达这里:
0013FC5C 5F803E5A /CALL 到 ShowWindow 来自 MFC40.5F803E54
0013FC60 00040248 |hWnd = 00040248 ('Prophet License Agreement',class='#32770',parent=00050144)
0013FC64 00000001 \ShowState = SW_SHOWNORMAL
顺着堆栈窗口往下翻,找到:
0013FCAC 004053FF 返回到 PROPHET.004053FF 来自 <jmp.&MFC40.#2199>
看来这个貌似是调用NAG的地方,我们在这一行上面按Enter键,返回到这里:
004053FA |. E8 EF220000 call <jmp.&MFC40.#2199>
004053FF |. 8945 EC mov dword ptr [ebp-14], eax
00405402 |. 83F8 01 cmp eax, 1
00405405 |. 75 30 jnz short 00405437
00405407 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
0040540A |. E8 E1230000 call <jmp.&MFC40.#486>
0040540F |. 8D45 F0 lea eax, dword ptr [ebp-10]
00405412 |. 8D4D 84 lea ecx, dword ptr [ebp-7C]
00405415 |. C645 FC 01 mov byte ptr [ebp-4], 1
00405419 |. 50 push eax
0040541A |. E8 25CBFFFF call 00401F44
0040541F |. 85C0 test eax, eax
00405421 |. 74 0B je short 0040542E
00405423 |. 8D45 F0 lea eax, dword ptr [ebp-10]
00405426 |. 8BCE mov ecx, esi
00405428 |. 50 push eax
00405429 |. E8 23020000 call 00405651
0040542E |> C645 FC 00 mov byte ptr [ebp-4], 0
00405432 |. E8 1F000000 call 00405456
00405437 |> C745 FC FFFFF>mov dword ptr [ebp-4], -1
0040543E |. E8 25000000 call 00405468
00405443 |. 8B45 EC mov eax, dword ptr [ebp-14]
00405446 |. 8B4D F4 mov ecx, dword ptr [ebp-C]
00405449 |. 64:890D 00000>mov dword ptr fs:[0], ecx
00405450 |. 5F pop edi
00405451 |. 5E pop esi
00405452 |. 8BE5 mov esp, ebp
00405454 |. 5D pop ebp
00405455 \. C3 retn
简单猜测一下:call是调用NAG窗口;cmp eax,1是判断按钮。
经验证"Accept"的按钮返回值是1。
那么我们的工作也很明了了:干掉那个Call即可。
按照一般的想法,我们是把call给nop掉,然后再对eax赋值1。
但是在这里还有一个mov dword ptr [ebp-14], eax呢?谁知道程序在以后还有没有对那个地址进行判断呢?
所以我们换个办法,把call改成mov eax,1,哈哈,完美解决:)
--------------------------------------------------------------------------------
【后记】
破解之后,我又到网上去搜索它的注册码,还真让我找到了。
经跟踪,程序在注册之后会在注册表里面添加一句:
"UserRegisKey=<注册码1:注册码2>",位于HLM\Software\BBN\Prophet 5\Main
然后我居然发现,把注册码改成任意值都可以!!!
看来这个软件的破解可以简化到添加一句注册表键值!Shit!
贴这篇破文的目的也就是仅仅在于给大家一个破解时间限制的例子罢了:)
--------------------------------------------------------------------------------
2007年06月27日 14:05:21
[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!