Tutorial 1 : How to crack 1st Contact 2.00.0.1
作者:dREAMtHEATER
写作日期: 14/15th July, 1999
版本:1.0 Beta 1
软件背景资料
运行平台: Win9X
文件名称: con92001.zip
程序类型: Contact Manager
下载地点:
a2eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3A6K6L8$3k6@1j5$3!0F1M7%4g2D9N6r3W2F1k6#2)9J5k6h3y4G2L8b7`.`.
文件大小: 1,281KB
使用的工具
SoftIce V3.25--Win9X Debugger
W32Dasm V8.93--Win9X Dissembler
Hex WorkShop v2.54--Hex Editor
难易程度
Easy(X)-Part1 Medium(X)-Part2 Hard( ) Pro( )
前言
网上的朋友,大家好!
这是我写的第一篇破解教程,如若有纰漏,请各位多指教!
这里我先声明,我写这篇教程的目的并不是教你如何去偷人家软件作者的劳动成果
,如果你想从我这里找注册码什么的,那我还是劝你到别的站点去找吧,我只是想教你
破解的思路,纯教学目的,若你真的很喜欢这个软件,那么请花钱注册!
Introduction
软件的作者这样说:
1st Contact comes with many features to make managing contacts an easy
and enjoyable task.
关于此软件的保护机制
运行程序Contacts.exe,首先跳出一个窗口(nag screen),显示你还可以试用多少
天。只要你不注册,那么它总是先跳出来,这是我们要crack的地方。
进入程序,看看帮助里面有没有可以注册的地方,果真有 “Enter Registration
Code...”,这也是我们的切入点之一。
我追踪了一下它在windoz的注册表(registry)中存放的键值(key value),发现第
一次安装时,会把安装日期保存在“HKEY_USERS\.DEFAULT\Software\JSoft Consultin
g\1st Contact\Main Form\InstallDate_Date”中,若没有注册,每次程序运行就会读
取此键值,从而计算出你还可以试用多少天。告诉你,当你试用期过后,你把此键值删
掉,即可重新获得三十天试用期。这算不算是cracking ? :-)
注册后,你会发现他把注册信息放在"HKEY_LOCAL_MACHINE\Software\JSoft Cons
ulting\1st Contact\2.00.0.1\"里面。
这篇文章里我用两种方法去破解这个软件,一个软件的破解,往往可以从多个角度
来入手,如若你只想单纯地破解,那么某些情况下,也许很简单,但你可能并不能完全
了解软件作者的程序保护系统,下次遇到同样的保护机制,你会挠头的!
不多说了,转回正题,让我们开始吧!
正文
PART 1 用SoftIce从内存中嗅出注册码
我写的不是基础教程,如果你不知道SoftIce怎么用,那么还是先去补补课吧!
好,在注册窗口中,任意填入你的名字、注册码(他的注册码形式为xxxxxxxx-x
xxxxxxx,后半部分数目不确定),我填入的是name:DREAMTHEATER(我本想填dREAMtHEATE
R,程序自动转为大写),registration code为12121212-12121212(这叫"12"大法 :-)
当你填好后,你会发现窗口上"finish"按扭还呈不可按(disable)状态,看来软
件作者真的在这方面下了一番工夫,这意味着它是进行实时注册码计算的,只有你输入正
确的注册码,才能按"finish"按扭。
怎么办呢?这也许对cracker新生(newbies)来说会放弃掉,如果真是这样,foll
ow me!
删掉你填入的注册码的最后一位,CTRL-D,进入SoftIce,设断点bpx hmemcpy,F5,
返回程序,重新填入注册码的最后一位,你发现你会立刻进入SoftIce,再CTRL-D两次,为
什么呢?这是因为注册窗口里有三个地方需要我们填写。第三次回到SoftIce后,首先取
消你所有下的断点,接下来,你需要按无数次的F12,回到计算注册码的部分,又有人问
了,怎么才能知道你回到了正确的地方,以及我到底需要按多少次F12?这是一个经验问
题,我看到很多教程里,精确地告诉你按了多少次F12,我觉得这没有任何意义,因为给
你换一个程序,你还是不会cracking。这方面我也是摸了无数次才算找到切入点,很简
单,如果你看到在SoftIce的code窗口中,offset变成004xxxxx,极少的情况下,还会是
005xxxxx,这代表你已进入程序代码本身,多数情况下,你还需要进一步按F12,到底还需
按多少次,我再教你一些经验,如果你发现每按一次F12,在每个call后面数行就紧跟一
个ret指令,那么你就还需按F12。慢慢按照我的指导再拿几个软件练一练,我想你会成
功的!
开始我们的trace吧!
如果你能找到下面这段代码,那么你已成功了一半:
:004ADB9D E8B242F8FF call 00431E54
:004ADBA2 8B45FC mov eax, dword ptr [ebp-04] <--最后一次按F
12,回到这里
敲入d eax ,在数据窗口,你会看到你输入的name
:004ADBA5 8D55F8 lea edx, dword ptr [ebp-08]
:004ADBA8 E8E38C0100 call 004C6890 <--计算注册码的部分
:004ADBAD 8B45F8 mov eax, dword ptr [ebp-08]
:004ADBB0 50 push eax <-- 敲入d eax, see what? yes,the
real code
:004ADBB1 8D55F4 lea edx, dword ptr [ebp-0C]
:004ADBB4 8B83D4020000 mov eax, dword ptr [ebx+000002D4]
CTRL-D退出SoftIce,在注册窗口填入正确的注册码,我的是114A19D5-456DA1A1,不
要用我的注册码去注册!自己去练习吧!
再补充一下,注册码的前部分是固定的,你可以试试。
PART2 通过PATCH,迫使程序注册。
我先讲一下破解思路,很多共享软件现在都使用全局变量,作为软件注册与否的
标志,在汇编中体现为在某个内存地址中,存入1或0,往往1代表已注册,0为共享状态
,计算机专业用语中,这个内存地址称之为FLAG,当程序运行时,初始化值为0,读取win
doz注册表或*.ini文件中的注册信息后,若已注册,那么flag值变为1,否则,继续保持
为0,程序的其他部分可以访问这个flag,维持软件的共享状态。
说起来很简单,实际破解过程中需要花大量的时间,我用第一种方法破解,两分
钟就搞定了,但是此法花费了我数个小时的时间,但这很值,他使你的cracking技术又
提高了几个百分点!
我们开始吧!
如果你用第一种方法已注册,那么,按照我前面说的,删掉他的注册信息,重新
进入共享状态。
运行你的程序,出现了nag screen,告诉你还剩多少天可试用,对cracker来说这
是一个很好的画面,点击窗口的任意部位,进入主窗口,看看还有什么可值得借鉴的(
这期间我试了很多方法,略掉)。点击菜单help\Administration\Status...,叫出一个
message box,他告诉你:“You are on day X of your 30 day evaluation period”,
又是一条好的线索。
在softice中下断点bpx messageboxa,看看有什么反应,很可惜,不工作,但我保
证这绝对是message box,后来我用其他方法确定程序是用Delphi编写的,向这种API函数
Delphi总是用自己封装的函数。
剩最后一招了,请出我们的老朋友---W32Dasm,我认为他是最cool的软件,它可以
将程序的源代码反汇编出来,如果你还没有,赶紧下载一个,kool!
我发现这个工具在国内提到的很少,但在国外的tutor里总是提到他,如果说sof
tice是你的左膀,那么它应是你的右臂。
运行W32Dasm,等待他为你反汇编1st Contact,利用这个时候你可以去喝杯茶 :-)
反正我的机器得等会儿。
OK,在W32Dasm中寻找字符串“You are on day”,又经过漫长等待,你会发现下
面的代码:
:004CDDB9 A0D65F4D00 mov al, byte ptr [004D5FD6] 〈--看出来了吗
,地址004D5FD6是一个注册flag
:004CDDBE 3401 xor al, 01 <--异或al 与 01,如果004D5FD6的
内容为1,那么异或结果为0,否则为1
:004CDDC0 2C01 sub al, 01 al=al-01
:004CDDC2 7207 jb 004CDDCB <--如果已注册,al=0,jump to 0
04CDDCB,显示"This copy of 1st Contact is registered to "
:004CDDC4 7456 je 004CDE1C <--否则,al=1,jump to 下一个f
lag,看你还剩多少天试用期,或已过期。
:004CDDC6 E984010000 jmp 004CDF4F
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004CDDC2(C)
|
:004CDDCB 6A00 push 00000000
:004CDDCD FF3518624D00 push dword ptr [004D6218]
* Possible StringData Ref from Code Obj ->"This copy of "
|
:004CDDD3 6880DF4C00 push 004CDF80
:004CDDD8 FF3528624D00 push dword ptr [004D6228]
* Possible StringData Ref from Code Obj ->" is registered to "
|
:004CDDDE 6898DF4C00 push 004CDF98
:004CDDE3 FF3544624D00 push dword ptr [004D6244]
* Possible StringData Ref from Code Obj ->" - Serial Number: "
|
:004CDDE9 68B4DF4C00 push 004CDFB4
:004CDDEE FF353C624D00 push dword ptr [004D623C]
:004CDDF4 68D0DF4C00 push 004CDFD0
:004CDDF9 8D45F4 lea eax, dword ptr [ebp-0C]
:004CDDFC BA08000000 mov edx, 00000008
:004CDE01 E8BA61F3FF call 00403FC0
:004CDE06 8B45F4 mov eax, dword ptr [ebp-0C]
:004CDE09 668B0DD4DF4C00 mov cx, word ptr [004CDFD4]
:004CDE10 B202 mov dl, 02
:004CDE12 E8F9A3F8FF call 00458210
:004CDE17 E933010000 jmp 004CDF4F
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004CDDC4(C)
|
:004CDE1C 833D68624D00FF cmp dword ptr [004D6268], FFFFFFFF <--地址
004D6268又是个全局变量,检查试用期是否已过的flag
:004CDE23 0F94C0 sete al 〈--如果此时004D6268的内容是FFFFF
FFF,那么al=1
:004CDE26 2C01 sub al, 01
:004CDE28 7207 jb 004CDE31 <--al=0,jump to 004cde31,即显
示“You are on day X of your 30 day evaluation period”
:004CDE2A 7450 je 004CDE7C 〈--al=1,jump to 004CDE7C,即显
示"Your evaluation period has expired. Please register NOW if you wish to co
ntinue using "
:004CDE2C E91E010000 jmp 004CDF4F
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004CDE28(C)
|
:004CDE31 6A00 push 00000000
:004CDE33 FF3518624D00 push dword ptr [004D6218]
* Possible StringData Ref from Code Obj ->"You are on day "
|
:004CDE39 68E0DF4C00 push 004CDFE0
:004CDE3E 8D55F0 lea edx, dword ptr [ebp-10]
:004CDE41 B81F000000 mov eax, 0000001F
:004CDE46 2B0568624D00 sub eax, dword ptr [004D6268]
:004CDE4C E8A7AFF3FF call 00408DF8
:004CDE51 FF75F0 push [ebp-10]
* Possible StringData Ref from Code Obj ->" of your 30 day evaluation period
."
|
:004CDE54 68F8DF4C00 push 004CDFF8
:004CDE59 8D45F4 lea eax, dword ptr [ebp-0C]
:004CDE5C BA04000000 mov edx, 00000004
:004CDE61 E85A61F3FF call 00403FC0
:004CDE66 8B45F4 mov eax, dword ptr [ebp-0C]
:004CDE69 668B0DD4DF4C00 mov cx, word ptr [004CDFD4]
:004CDE70 B202 mov dl, 02
:004CDE72 E899A3F8FF call 00458210
:004CDE77 E9D3000000 jmp 004CDF4F
从004CDE28跳转的代码:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004CDE2A(C)
|
:004CDE7C 6A00 push 00000000
:004CDE7E FF3518624D00 push dword ptr [004D6218]
* Possible StringData Ref from Code Obj ->"Your evaluation period has expire
d. "
->"Please register NOW if you wish "
->"to continue using "
|
:004CDE84 6824E04C00 push 004CE024
:004CDE89 FF3528624D00 push dword ptr [004D6228]
:004CDE8F 68D0DF4C00 push 004CDFD0
:004CDE94 8D45F4 lea eax, dword ptr [ebp-0C]
:004CDE97 BA04000000 mov edx, 00000004
:004CDE9C E81F61F3FF call 00403FC0
:004CDEA1 8B45F4 mov eax, dword ptr [ebp-0C]
上面的代码你看明白了吗?如果没有问题,那么继续,否则你需先去学习汇编
的基础知识。既然知道了地址004D5FD6是registration flag,那么我们需要找到什么地
方给他赋值,前面已说,赋1即mov byte ptr [004D5FD6], 01,代表已注册。还是在W3
2Dasm中search,你会发现下面的两段代码:
第一段:
* Referenced by a CALL at Address:
|:004C7332
|
:004C7C84 B83C624D00 mov eax, 004D623C
:004C7C89 8B1538624D00 mov edx, dword ptr [004D6238]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7C14(C)
|
:004C7C8F E844C0F3FF call 00403CD8
:004C7C94 C605D65F4D0001 mov byte ptr [004D5FD6], 01
第二段:
* Referenced by a CALL at Address:
|:004C733F
|
:004C7F90 55 push ebp
:004C7F91 8BEC mov ebp, esp
:004C7F93 83C4F8 add esp, FFFFFFF8
:004C7F96 53 push ebx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7F67(C)
|
:004C7F97 33C9 xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7F77(C)
|
:004C7F99 894DF8 mov dword ptr [ebp-08], ecx
:004C7F9C 8BD8 mov ebx, eax
:004C7F9E 33C0 xor eax, eax
:004C7FA0 55 push ebp
:004C7FA1 6832814C00 push 004C8132
:004C7FA6 64FF30 push dword ptr fs:[eax]
:004C7FA9 648920 mov dword ptr fs:[eax], esp
:004C7FAC C605D65F4D0001 mov byte ptr [004D5FD6], 01
:004C7FB3 8B83A4030000 mov eax, dword ptr [ebx+000003A4]
你发现了什么,这两段代码分别从004C7332,004C733F两个offset处call的
,而且这两个地址离得非常近,让我们再走进一些看看:
* Possible StringData Ref from Code Obj ->"Name"
|
:004C7232 BA94734C00 mov edx, 004C7394
:004C7237 8B45F4 mov eax, dword ptr [ebp-0C]
:004C723A E8F1D3F9FF call 00464630
:004C723F 8B55F0 mov edx, dword ptr [ebp-10]
:004C7242 B844624D00 mov eax, 004D6244
:004C7247 E88CCAF3FF call 00403CD8
:004C724C 8D4DF0 lea ecx, dword ptr [ebp-10]
* Possible StringData Ref from Code Obj ->"Company"
|
:004C724F BAA4734C00 mov edx, 004C73A4
:004C7254 8B45F4 mov eax, dword ptr [ebp-0C]
:004C7257 E8D4D3F9FF call 00464630
:004C725C 8B55F0 mov edx, dword ptr [ebp-10]
:004C725F B830624D00 mov eax, 004D6230
:004C7264 E86FCAF3FF call 00403CD8
:004C7269 8D4DF0 lea ecx, dword ptr [ebp-10]
* Possible StringData Ref from Code Obj ->"Registration"
|
:004C726C BAB4734C00 mov edx, 004C73B4
:004C7271 8B45F4 mov eax, dword ptr [ebp-0C]
:004C7274 E8B7D3F9FF call 00464630
:004C7279 8B55F0 mov edx, dword ptr [ebp-10]
:004C727C B83C624D00 mov eax, 004D623C
:004C7281 E852CAF3FF call 00403CD8
* Possible StringData Ref from Code Obj ->"Registration Date"
|
:004C7286 BACC734C00 mov edx, 004C73CC
:004C728B 8B45F4 mov eax, dword ptr [ebp-0C]
:004C728E E881D6F9FF call 00464914
:004C7293 2C01 sub al, 01
:004C7295 7204 jb 004C729B <--在W32Dasm debugger状态下,
此处设断点,看看程序在非注册情况下的流程
:004C7297 7433 je 004C72CC
:004C7299 EB5F jmp 004C72FA
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7295(C)
|
:004C729B 8B45FC mov eax, dword ptr [ebp-04] <--程序跳转到这
里
:004C729E 8B80BC050000 mov eax, dword ptr [eax+000005BC]
:004C72A4 E86FAEF9FF call 00462118
:004C72A9 83C4F8 add esp, FFFFFFF8
:004C72AC DD1C24 fstp qword ptr [esp]
:004C72AF 9B wait
:004C72B0 8D55F0 lea edx, dword ptr [ebp-10]
* Possible StringData Ref from Code Obj ->"ddddd"
|
:004C72B3 B8E8734C00 mov eax, 004C73E8
:004C72B8 E8973EF4FF call 0040B154
:004C72BD 8B55F0 mov edx, dword ptr [ebp-10]
:004C72C0 B834624D00 mov eax, 004D6234
:004C72C5 E80ECAF3FF call 00403CD8
:004C72CA EB2E jmp 004C72FA 〈--继续跳转到004C72FA
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7297(C)
|
* Possible StringData Ref from Code Obj ->"Registration Date"
|
:004C72CC BACC734C00 mov edx, 004C73CC
:004C72D1 8B45F4 mov eax, dword ptr [ebp-0C]
:004C72D4 E82BD4F9FF call 00464704
:004C72D9 83C4F8 add esp, FFFFFFF8
:004C72DC DD1C24 fstp qword ptr [esp]
:004C72DF 9B wait
:004C72E0 8D55F0 lea edx, dword ptr [ebp-10]
* Possible StringData Ref from Code Obj ->"ddddd"
|
:004C72E3 B8E8734C00 mov eax, 004C73E8
:004C72E8 E8673EF4FF call 0040B154
:004C72ED 8B55F0 mov edx, dword ptr [ebp-10]
:004C72F0 B834624D00 mov eax, 004D6234
:004C72F5 E8DEC9F3FF call 00403CD8
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004C7299(U), :004C72CA(U)
|
:004C72FA 33C0 xor eax, eax 〈--又跳转到这里
:004C72FC 5A pop edx
:004C72FD 59 pop ecx
:004C72FE 59 pop ecx
:004C72FF 648910 mov dword ptr fs:[eax], edx
:004C7302 6817734C00 push 004C7317
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7315(U)
|
:004C7307 8B45F4 mov eax, dword ptr [ebp-0C]
:004C730A E83DBDF3FF call 0040304C
:004C730F C3 ret 〈--执行到这里,jump to 004C7317
:004C7310 E9ABC3F3FF jmp 004036C0
:004C7315 EBF0 jmp 004C7307
:004C7317 A0D85F4D00 mov al, byte ptr [004D5FD8]<--又是一个flag
:004C731C 2C01 sub al, 01
:004C731E 720C jb 004C732C <--可跳转到第一个call,可将jb
-->jmp
:004C7320 7417 je 004C7339 <--可跳转到第二个call,可将je
-->jmp,但你需要将上一指令改为两个nop
:004C7322 FEC8 dec al
:004C7324 7420 je 004C7346 <--正常情况(未注册),从这里
跳转,正好跳过两个包含“mov byte ptr [004D5FD6], 01”的call
:004C7326 FEC8 dec al
:004C7328 7429 je 004C7353
:004C732A EB32 jmp 004C735E
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C731E(C)
|
:004C732C 8B55F8 mov edx, dword ptr [ebp-08]
:004C732F 8B45FC mov eax, dword ptr [ebp-04]
:004C7332 E84D090000 call 004C7C84 <--第一个call
:004C7337 EB25 jmp 004C735E
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C7320(C)
|
:004C7339 8B55F8 mov edx, dword ptr [ebp-08]
:004C733C 8B45FC mov eax, dword ptr [ebp-04]
:004C733F E84C0C0000 call 004C7F90 <--第二个call
:004C7344 EB18 jmp 004C735E
你又看到了什么,对了,有几个字符串参考"Name"、"Registration"、"Compa
ny"、"Registration Date",这是程序从windoz注册表里获取我们的注册信息,这本应
调用标准的API函数"RegQueryValuea 或“RegQueryValueExa”而获取的键值,但我前面
已说它是用Delphi编写的,请注意区分。
获得这些键值后,程序判断注册码是否存在,若存在,正确与否?正确,那么
reg flag值为1,表示已注册,程序的其他部分以此为参考。
让我们分别Patch 004C731E 和 004C7320两处的指令,在004C731E处,强迫程
序跳到004c732c,结果程序成功注册,再也没有什么nag screen,不过在“关于”中他告
诉你" status:packaged by VBox"。VBox是一个公司,我知道他是专门为共享软件做保
护程序的,如果你是共享软件作者,你可以直接购买他的保护程序,加入你的程序代码
中,无须再编写保护系统。我曾经试图破解用他包装的软件,但我能力有限,至今仍没
有结果,他的代码中有防Debugger的部分,并且某个关键的动态链接库已被加密,不过
我在网上已看到老外的破解程序。
让我们再看看第二种Patch,程序出现message box,tell you :"This program
is not properly installed. Please re-install 1st Conctact from the JSoft CD-
Rom Collection. The serial number from the CD MUST be entered in the Setup W
izard along with your Name and Company."没关系,让我们在W32Dasm中search一下上
面的字符串,啊,找到了,请看下面的代码:
:004C80CE E83DBFF3FF call 00404010
:004C80D3 0F95C0 setne al
:004C80D6 FEC8 dec al
:004C80D8 7542 jne 004C811C <--change jne to jmp
:004C80DA 6A00 push 00000000
:004C80DC FF3518624D00 push dword ptr [004D6218]
* Possible StringData Ref from Code Obj ->"This program is not properly inst
alled. "
->"Please re-install "
|
:004C80E2 6804824C00 push 004C8204
:004C80E7 FF3528624D00 push dword ptr [004D6228]
* Possible StringData Ref from Code Obj ->" from the JSoft CD-Rom Collection
. "
->"The serial number from the CD "
->"MUST be entered in the Setup Wiza
rd "
->"along with your Name and Company.
"
|
:004C80ED 6848824C00 push 004C8248
:004C80F2 8D45F8 lea eax, dword ptr [ebp-08]
:004C80F5 BA04000000 mov edx, 00000004
将jne改为jmp,程序成功注册,“关于”中他告诉你" status:registered"。
THE PATCH
在Hex WorkShop中装入CONTACTS.EXE,press F5,填入要修改的十六进制程序代码
的offset,获取方法是在W32Dasm中,用鼠标双击你要修改的指令一行,屏幕将高亮显示
这一行,并在状态栏中标出offset.
第一种:offset c671eh : 改720C为EB0C
第二种:offset c671eh : 改720C7417为9090EB17 offset c74d8h : 改7542为
EB42
If you any comments,suggestion,critic,please email me at dreamtheater@
263.net