扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
注册机和补丁制作
第一节 概念介绍
何为注册机?注册机就是针对某一软件,通过一定算法算出注册码的程序。我们写注册机时,一般都要了解注册码的算法(这当然是通过跟踪调试了解的),之后用汇编语言或其它高级语言来把算法还原。这样大家可根据自己的要求输入注册码,如根据自己的姓名,公司的名称注册。
目前共享软件有两种注册方式:
一 种是交费后,作者给寄有全部功能的 Register软件,原来的Shareware根本没有某些功能;
第二种交费后, 作者给你个注册码(Register Number),注册后功能就无限制了 。共享软件注册前后基本相同 , 只是功能受限制 ,或者使用时间受限制 ,或者经常出现要求注册的画面 , 等等 。
我们平时所接触的共享软件是第二种,通过算出注册码或打补丁使该软件有注册后的功能。
软件的破解也分两种:
一是、补丁(patches),这些小程序的功能是用来改变某种软件内某些特定的部位,因此它们的作用通常只限于某一个软件的版本。请勿使用针对不同版本所设计的patch,必须注意所使用软件版本的版本号与patch是否相同。倘若使用不当,将导至错误信息,会破坏程序,严重时也有可能死机!
二是、序列号(serial number)和注册码(key generator)就显的安全多了。有时候旧版的序号亦适用于新出的版本,就算不能用也毫无伤害。只有在极少数的情况下软件作者会设下某些陷阱,当使用者输入黑名单上的序号后,软件会自动销毁而无法使用。
通过补丁和注册机可以大大方便用户的注册,就是目前有不少的程序,它的注册码都与硬件有关,就是在每一台机上安装都有一个机器码,要把这个机器码E-MAIL给作者, 作者把收到的机器码用注册程序算出注册码后再寄回给用户,这样做使得软件的防复制方面加强了,但造成了不少用户的麻烦,因为只要用户一重装系统或升级主板 ,就要重新去注册了。对于这种程序,一般初学者只能在内存中找到自己机器的注册码,但这种注册码到了其它的机器上又不能用了。所以要求大家能自己写出注册机来。
而有的软件注册码计算很复杂,或只是试用版,到期就停止使用,根本无法输入注册码。对这类软件只能通过改动原程序代码指令,但如何让大家很方便地解除限制,当然你可把改动的字节告诉大家,用二进制编辑工具修改,但很不方便。所以大家有必要自己制作补丁程序,只要用户运行该补丁程序,让它帮你改动指定的代码,就可解除原软件限制,是不是很方便。
摘要:注册机和补丁制作何为注册机?注册机就是针对某一软件,通过一定算法算出注册码的程序。我们写注册机时,一般都要了解注册码的算法(这当然是通过跟踪调试了解的),之后用汇编语言……
标签:加密 解密 crack 破解
第二节 补丁制作
1、文件补丁制作
今天我们接触补丁制作工具是CodeFusion,界面制作也不错,它有以下功能:
1、可以自动比较补丁前后的差别
2、可以对字节逐个补丁,也可以使用普通和模板两种查找、替换;
3、补丁前后的文件尺寸可以不同;
4、可以对单个文件补丁,也可以处理多个不同盘、不同目录、甚至名字并不匹配的多个文件;
5、界面文字和链接等完全定制;
6、可以使用内置和外部的压缩器;也可以不压缩自行修改窗体;
为了使初学者能更快掌握这一工具使用,我就把一补丁最常用的制作过作写下来。
首先建立一个临时目录C:\TEMP(只是为了下面讲述的方便罢了).并在其下建立两个子目录,分别为C:\TEMP\1\以及 C:\TEMP\2\. 以网络吸血鬼NET VAMPIRE 3.2为例: 将没有CRACK的主程序VAMPIRE.EXE拷到C:\TEMP\1\目录下. 将已经CRACK的主程序VAMPIRE.EXE拷到C:\TEMP\2\目录下.
(图一)是用CodeFusion制成的补丁程序运行的界面。
(图一)
界面还是不错的,只要你用用CodeFusion,你就发现它很容易上手。
第一步、运行CodeFusion,界面如图二:
(图二)
图一和图二中的数字1、2、3、4、5是彼此对应的,要得到(图一)结果只需在(图二)中键入你自己的说明即可。你自己定制好界面可以存盘,存盘名是*.cfp,以后你只要打开该文件,就可出现所要的界面。很简单,自己摸索一下就能掌握。
第二步、定制好界面后,可以按预览按钮(就是上面的眼睛图标)看看界面自己是否满意,满意后按下一步。
(图三)
在图三中,按(1)处的绿色的十字,以添加原文件(在这里是吸血鬼的原主文件),按1后出现左边的一窗口,按2选择吸血鬼的原主文,选好按Ok即可。
第三步、这一步按图四的1处的绿色十字,出现如下结果:
(图四)
按上图中的2处是文件比较。第3处是Byte-path offset,在原文件中指定的地址处打字节补丁。第4处是Find &Replace,在原文件查找替换字节。第五处是Truncate offset,从指定地址处切断原文件。3,4,5的用处我在这里就不写了,大家可自己试试。
第四步、用鼠标按图四中的2处(File Compare)出现图五,选择己被crack的文件,进行比较,在这里是C:\TEMP\2\目录下, 已经CRACK的主程序VAMPIRE.EXE。
(图五)
在1 处选择C:\TEMP\2\目录下, 已经CRACK的主程序VAMPIRE.EXE。下一步按第2处的compare,进行两文件的比较,比较结束后按Ok,再按下一步。
第五步,这是最后一步,出现图六。
(图六)
在这界面上的各项选项就以默认值为主,它们都是些压缩选项,压缩补丁以保护你的版权。最后一步按1处(Make win32 Executable),选择路径、文件名,生成你的补丁。好了你可以把这补丁散发给大家,真可谓,辛苦你一人,方便千万人啊!
该软件的其它功能,大家自己再摸索一下,是不是很直观好用。
摘要:注册机和补丁制作何为注册机?注册机就是针对某一软件,通过一定算法算出注册码的程序。我们写注册机时,一般都要了解注册码的算法(这当然是通过跟踪调试了解的),之后用汇编语言……
标签:加密 解密 crack 破解
2、内存补丁制作
2.1 R!SC'sPatcher 工具使用
简介
RPP.EXE 是内存动态补丁制作软件。它通过脚本命令创建win32文件,以此文件装载程序,装载过程中等待软件解压或解除其自身保护后,然后按脚本要求修补内存中的指令,以使软件能够按我们要求运行。
如ACDSEE3.0是用ASPACK压缩软件,你crack时发现在内存地址433FEA处把6A00改成EB17就可成功,但你不可能直接修改压缩过的ACDSEE.EXE文件;这里就可用 RPP.EXE 按我们要求生成一LOAD.EXE文件,首先运行LOAD.EXE,它自动装载ACDSEE.EXE,等其自解压完成后,然后修改内存433FEA地址为EB17,这样ACDSEE.EXE就可按我们要求运行了,不过我不赞成用此法对付ACDSEE.EXE,因为ACDSEE.EXE运行有两种界面,其中VIEW界面用此法不太灵。
RPP.EXE 还可很方便对付NAG(一些提示、警告窗口的软件),如用 NEOLITE 2.0 Y压缩过的软件运行之前弹出来的那种窗口,当然也有专门除掉NAG的工具。
用法
在资源管理器中双击rpp.exe文件,它弹出一菜单,你选择事先编好的脚本文件,然后按OK 。
或在WINDOWS下的DOS窗口下用命令方式“rpp.exe <script.rpp>”,其中script.rpp为脚本命令文件。
如你的输出文件己存在,它将覆盖。在命令方式下,脚本文件可是任何文件名和扩展名;但在对话窗口操作方式下,文件名必须为 *.rpp
脚 本 命 令
-------------------
';' 注释符号, 跟着的只是些说明, 不会执行的, 直到下一行.
'T=' 表示对内存的检测次数,T=1000:意味着对内存检测1000次,在放弃之前,告诉你的应用程序是
不正确的版本。
注意:在脚本文件里,默认值T=8000。
'F=' 需要补丁的文件名
'O=' 生成的补丁文件名,如你没指定文件名,默认为LOAD.EXE
'P=' 如何在内存补丁, 格式:内存地址/原码/补码
具体看看脚本的例子
'R:' 把前面需要补的全部补好后, 再继续, 可以看看azpr243.rpp这个例子
':' 每一行都要以冒号结尾, 相当于回车
'$' 脚本结束标志
所有数字采用16进制
内存地址和原码都符合才会进行补丁, 字节间请用逗号分开。脚本文件不能大于40K,被补的字节有限为1f0h字节,被处理的原文件不小于30h字节。
脚本例子
script.rpp
T=1000: ;对内存尝试1000次补丁, 不行则放弃, 如果不设默认为8000
F=test.exe: ;要补丁的程序
P=40101D/74,60/74,00: ;将命令jz xx 改为jz next instruction
P=4024A6/46,52,45,45,20/52,21,53,43,00: ;将字符 'FREE ' 替换成 'R!SC'
$ ;结束
具体的脚本范例大家可参考其自带的Scripts.zip。
一些问题
下面是一有趣的试验,写一脚本文件,输入输出名一样,产生一执行文件,该文件将不断装载其自身
最后导致windows崩溃,你只好重新启动了。
'P=401000/68/B8:'
'F=fun.exe:'
'O=fun.exe:', 然后运行 fun.exe 不一会你只好重新启动微机了 :)
——————————————————————————————————
2.2 如何写Loader
作者:夜月
E-mail:luoyi.ly@yeah.net
写作日期:31th, August 2001
使用的工具
Trw2000 V1.23--Win9X Debugger
Masm32 V5.00--Loader Compiler
难易程度
Easy( ) Medium(X) Hard( ) Pro( )
----------=======Declare========----------
未经作者同意,不得修改、引用原文,一切权利保留。
本教程只供教学用,其他一切用途皆被禁止。
------------------=====Begin=====------------------
以Director 7.0为例,和大家谈谈如何写 Loader。当然,破解Director 7.0并不一定需要Loader,
它既没加壳,也没有CRC校验,完全可以用Patch的方法。但我这篇文章的目的不是教你如何破解Director,
而是教你如何写Loader。Clearly?
Ready?
Go!
Director 7.0也是一个狗保护的软件,和Authorware差不多。跟踪过程并不复杂,在此略去。
程序判断的关键点:
* Referenced by a CALL at Address:
|:00445A24
|
:0058CC24 53 push ebx
:0058CC25 32DB xor bl, bl
:0058CC27 E835000000 call 0058CC61
:0058CC2C 83F852 cmp eax, 00000052
:0058CC2F 741D je 0058CC4E
:0058CC31 83F856 cmp eax, 00000056
:0058CC34 7418 je 0058CC4E
:0058CC36 3D76030000 cmp eax, 00000376
:0058CC3B 7411 je 0058CC4E
:0058CC3D 3D54030000 cmp eax, 00000354
:0058CC42 740A je 0058CC4E
:0058CC44 83F841 cmp eax, 00000041
:0058CC47 7405 je 0058CC4E
:0058CC49 83F851 cmp eax, 00000051
:0058CC4C 7502 jne 0058CC50
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0058CC2F(C), :0058CC34(C), :0058CC3B(C), :0058CC42(C), :0058CC47(C)
|
:0058CC4E B301 mov bl, 01
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0058CC4C(C)
|
:0058CC50 E83E000000 call 0058CC93
:0058CC55 84C0 test al, al
:0058CC57 7402 je 0058CC5B
:0058CC59 B301 mov bl, 01
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0058CC57(C)
|
:0058CC5B 8AC3 mov al, bl <-----------改为 mov al,1
:0058CC5D 5B pop ebx
:0058CC5E C20400 ret 0004
Loader的写作思路很简单,主要是你要知道有这些个API存在。我买了一本32位汇编的书,上面
竟然说在Window98里面,不能对别的进程进行读写。幸亏有《论坛精华2》中,DDXia翻译的一篇文章上
面有介绍如何读写别的进程,不然,我到现在还被蒙在鼓里。哎!现在的书呀,真有误人子弟的嫌疑了。
写Loader要用到的几个API函数:
(1) BOOL GetOpenFileName(
LPOPENFILENAME lpofn // 指向一个OPENFILENAME的结构
);
该函数的作用是得到要被Load的程序的路径以及文件名
(2) (摘自罗云彬的Win32Asm教程)
BOOL CreateProcess(
LPCTSTR lpApplicationName, // 执行程序文件名
LPTSTR lpCommandLine, // 参数行
LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全参数
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全参数
BOOL bInheritHandles, // 继承标记
DWORD dwCreationFlags, // 创建标记
LPVOID lpEnvironment, // 环境变量
LPCTSTR lpCurrentDirectory, // 运行该子进程的初始目录
LPSTARTUPINFO lpStartupInfo, // 创建该子进程的相关参数
LPPROCESS_INFORMATION lpProcessInformation // 创建后用于被创建子进程的信息
);
改函数的作用是创建进程,使被Load的程序运行起来
(3) BOOL ReadProcessMemory(
HANDLE hProcess, // 被读的进程的句柄
LPCVOID lpBaseAddress, // 开始读的地址
LPVOID lpBuffer, // 读完后,数据存放的地址
DWORD nSize, // 要读的数量,以字节为单位
LPDWORD lpNumberOfBytesRead // 实际上读的数量,以字节为单位
);
改函数的作用是读去一片范围的内存,可以作校验用——看看运行的进程是不是我们要Load的那个。
(4) BOOL WriteProcessMemory(
HANDLE hProcess, // 被写的进程的句柄
LPVOID lpBaseAddress, // 开始写的地址
LPVOID lpBuffer, // 要写入的数据存放地址
DWORD nSize, // 要写的数量,以字节为单位
LPDWORD lpNumberOfBytesWritten // 实际上写的数量,以字节为单位
);
写一个Loader要用的主要就是这4个函数。
还有一个问题:如果程序被加壳了,我们如何知道它已经在内存里面节压缩完毕?
R!sc用的是WaitForInputIdle的方法。这个方法很不错,对付大多数的壳都可以行得通。
但是,对于这个程序而言,就没有WaitForInputIdle的必要了。因为它并没有加壳。
好了,下面看看我写的这个Loader的源代码:
Loader源代码(load.exe):
---------------------------------------Cut From Here------------------------------------------
**********************************************************
主程序 *
**********************************************************
.386p
.model flat,stdcall
option casemap :none
include windows.inc
include kernel32.inc
include user32.inc
include comdlg32.inc
include comctl32.inc
includelib kernel32.lib
includelib user32.lib
includelib comdlg32.lib
includelib comctl32.lib
**********************************************************
Normal Data *
**********************************************************
.data
CSiR_Tag db 'PE LOADER &CRACKER-----ROBOTOW 2001',0
CSiR_Error db 'Error!',0
CSiR_Error1 db 'Something fucked up...',0
OpenERR_txt db 'CreateProcess Error :( ',0
ReadERR_txt db 'ReadProcess Error :(',0
WriteERR_txt db 'WriteProcess Error :P',0
VersionERR_txt db 'Incorrect Version of application :(',0
CSiR_ProcessInfo dd 4 dup(0)
CSiR_StartupInfo db 48h dup(0)
CSiR_RPBuffer db 10h dup(0)
szFilter db 'Director.exe',0,'Director.exe',0
db 'Execute Files',0,'*.exe,;*.com',0
db 0
szTitleOpen db 'Find Director.exe,0
szExt db '*.exe',0
**********************************************************
Patch Data *
**********************************************************
CSiR_AppName OPENFILENAME <?>
CSiR_AppName_Buffer db 512 dup(?)
fuck dd 58cc5bh
mysizeof dd 6h
checkbytes db 08Ah,0C3h,05Bh,0C2h,04h,00h
patch_data_1 db 0B0h,0
patch_size_1 dd 2
patch_addr_1 dd 58cc5bh
.code
Start:
invoke InitCommonControls
invoke GetModuleHandle,NULL
mov CSiR_AppName.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
mov CSiR_AppName.lStructSize,SIZEOF CSiR_AppName
mov CSiR_AppName.hwndOwner,eax
mov CSiR_AppName.lpstrFilter,offset szFilter
mov CSiR_AppName.lpstrFile,offset CSiR_AppName_Buffer
mov CSiR_AppName.nMaxFile,512
mov CSiR_AppName.lpstrInitialDir,0
mov CSiR_AppName.lpstrTitle,offset szTitleOpen
mov CSiR_AppName.lpstrDefExt,offset szExt
invoke GetOpenFileName,offset CSiR_AppName
mov dword ptr [CSiR_StartupInfo],44h
invoke CreateProcessA,offset CSiR_AppName_Buffer,0,0,0,0,20h,0,0,\
offset CSiR_StartupInfo,offset CSiR_ProcessInfo
test eax,eax
jz OpenERR
invoke ReadProcessMemory,[CSiR_ProcessInfo],[fuck],offset CSiR_RPBuffer,\
[mysizeof],0
test eax,eax
jz ReadERR
cld
lea esi,CSiR_RPBuffer
lea edi,checkbytes
mov ecx,6
repe cmpsb
jnz VersionERR
Patch:
invoke WriteProcessMemory,[CSiR_ProcessInfo],[patch_addr_1],offset patch_data_1,\
[patch_size_1],0
test eax,eax
jz WriteERR
close_this_app:
invoke CloseHandle,[CSiR_ProcessInfo]
invoke CloseHandle,[CSiR_ProcessInfo+4]
invoke ExitProcess,NULL
VersionERR:
lea eax,VersionERR_txt
jmp abort
ReadERR:
lea eax,ReadERR_txt
jmp abort
WriteERR:
lea eax,WriteERR_txt
jmp abort
OpenERR:
lea eax,OpenERR_txt
abort:
invoke MessageBox,0,eax,offset CSiR_Error,0
jmp close_this_app
End Start
------------------------------------------Cut End---------------------------------------------
第三节 注册机制作工具
1、CrackCode2000使用介绍
以前我们写注册机时,一般都要了解程式的算法,之后用汇编语言或C语言来把算法还原,这样做一个注册机一般都有要花不少的时间,而且要对汇编语言和编程有比较高的要求,所以对于初学者来说,是一件很难的事情,对于不少的初学者,有时他们能在内存中找到注册码,但却没有能力写出注册机来,这大大削弱了他们的破解积极性,但还有更可恶的事,就是目前有不少的程式,它的注册码都与硬件有关,就是在每一台机上安装都有一个机身码,要把这个机身码E-MAIL给作者,作者把收到的机身码用注册程式算出注册码后再寄回给用户,这样做使得软件的防复制方面加强了,但造成了不少用户的麻烦,因为只要用户一重装系统或升级主板,就要重新去注册了。对于这种程式,一般初学者只能在内存中找到自己机器的注册码,但这种注册码到了其它的机器上又不能用了,而自己又没有办法写出注册机来,为了解决这方面的问题,我写了一个小软件,它可以从另一进程内存中取出注册码来,显示出来,而不需要你去了解注册程式的算法,但它的应用面是很有限的,只能对付符合以下条件的软件:
一、必须在内存中或在寄存器中可以找到正确的注册码;
二、被取注册码的软件不能反跟踪程式;
三、被取注册码的软件的比较部分程式是静态的存在的;
四、注册码比较程式只作比较注册码使用。
好了,讲了这么多,不如来个例子说明一下如何使用它吧!哦对了,大家还不知那个东西是什么呢?它叫CrackCode2000啊!
以下是一个软件的注册码比较程式,大家不要问我怎么样得到了,大家只要听下去就可以了。
015F:004149D2 8A06 MOV AL,[ESI] 这里放你的输入的注册码
015F:004149D4 84C0 TEST AL,AL
015F:004149D6 740D JZ 004149E5
015F:004149D8 8A11 MOV DL,[ECX] 这里放正确的注册码
015F:004149DA 41 INC ECX
015F:004149DB 46 INC ESI
015F:004149DC 3AC2 CMP AL,DL
015F:004149DE 751F JNZ 004149FF
015F:004149E0 803900 CMP BYTE PTR [ECX],00
015F:004149E3 75ED JNZ 004149D2
015F:004149E5 803900 CMP BYTE PTR [ECX],00
015F:004149E8 7515 JNZ 004149FF
015F:004149EA 803E00 CMP BYTE PTR [ESI],00
015F:004149ED 7510 JNZ 004149FF
015F:004149EF B801000000 MOV EAX,00000001 最后正确就把EAX=1
015F:004149F4 5F POP EDI
015F:004149F5 5E POP ESI
015F:004149F6 5D POP EBP
015F:004149F7 5B POP EBX
015F:004149F8 81C460030000 ADD ESP,00000360
015F:004149FE C3 RET
好了,大家在Winsoftice下以下的命令可以看到:
:d esi
0167:0041F1F8 34 38 34 38 34 38 34 38-34 38 34 38 00 00 00 00 484848484848....
0167:0041F208 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0167:0041F218 04 0D 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0167:0041F228 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0167:0041F238 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0167:0041F248 00 00 00 00 00 00 00 00-00 C0 00 00 0A 04 00 00 ................
0167:0041F258 04 00 00 00 0A 00 00 00-01 00 00 00 90 03 CA 00 ................
0167:0041F268 00 00 00 00 D0 03 CA 00-00 00 00 00 00 00 00 00 ................
:d ecx
0167:0066F3E4 58 51 4D 50 5A 43 57 58-54 45 52 53 00 01 08 00 XQMPZCWXTERS....
0167:0066F3F4 9A EE 8B 17 E3 A4 00 00-10 00 E0 2C 00 00 00 01 ...........,....
0167:0066F404 00 03 00 00 00 00 00 00-80 01 AB 01 8D 01 9C 01 ................
0167:0066F414 00 00 AB 01 8D 01 00 00-80 01 9C 01 8C 01 A4 01 ................
0167:0066F424 8D 01 9C 01 8C 01 A4 01-8D 01 04 00 00 00 B6 0C ................
0167:0066F434 00 A9 52 FB 83 2A D1 78-21 88 73 DA A2 0B F0 59 ..R..*.x!.s....Y
0167:0066F444 65 CC 37 9E E6 4F B4 1D-44 ED 16 BF C7 6E 95 3C e.7..O..D....n.<
0167:0066F454 ED 44 BF 16 6E C7 3C 95-CC 65 9E 37 4F E6 1D B4 .D..n.<..e.7O...
见到了吧!那个XQMPZCWXTERS就是正确的注册码了,但如果我们用以前的方法来写注册机,就要去分析前面的程式了,但我们今次不是用这种方法来制作,而是用CRACKCODE来做,这样大家可以见到用CRACKCODE来做注册机实在是太方便了,太简单了!好,我们为CRACKCODE来写一个INI文件吧!
第一种写法(这是一种不提倡的写法!):
内存直接寻址的方法:
[Options]
CommandLine=Axplorer.exe 这是被取注册码的EXE文件名
Mode=0 采用模式0读取注册码
First_Break_Address=4149D2 程式的中断地址,它和ICE中见到的是一样的
First_Break_Address_Code=8A 中断程式的1 Byte代码,这个8A就是015F:004149D2的8A
First_Break_Address_Code_Lenth=2 中断行代码的长度(单位:byte)
Save_Code_Address=66F3E4 存放注册码的内存地址
第二种写法(这种值得推荐!)
寄存器间接寻址的方法:
[Options]
CommandLine=test.exe 这是被取注册码的EXE文件名(化名)
Mode=0 取用模式0读取注册码
First_Break_Address=4149D2 程式的中断地址,它和ICE中见到的是一样的
First_Break_Address_Code=8A 中断程式的1 Byte代码,这个8A就是015F:004149D2的8A
First_Break_Address_Code_Lenth=2中断行代码的长度(单位:byte)
Save_Code_Address=ECX 存放注册码的内存地址,这个ECX是从015F:004149D8来
的,大家见到了吧!这和上前的方法相差就只是这句,
当你使用了这句,就不怕软件是否被压缩过了。
注意:
目前CRACKCODE2000对所中断地址的代码长度已经是无有要求的,只要把长度写进INI
就可以了!
015F:004149D2 8A06 MOV AL,[ESI] 本行代码为2 Bytes
015F:004149DA 41 INC ECX 本行代码为1 Byte
015F:004149E0 803900 CMP BYTE PTR [ECX],00 本行代码为3 Bytes
生成后保存为CRACKCODE.INI文件,把CRACKCODE.EXE和CRACKCODE.INI一起copy到被注册的软件的安装目录下,运行CRACKCODE.EXE。哦!被取注册码的软件也运行了,到注册的窗口去,输入一个名字,随便输入注册码,按确定,哦!跳出一个显示窗来,里面出现了你想要的正确注册码了。是不是觉得很神奇呢!来试一试你就知道了!
好了,下面我再为大家显示CrackCode2000的另一种工作模式吧!
下面是Decompile Winhelp的注册机的写法,这个软件是加了壳的软件,我们来看一看加了壳的软件对于CrackCode2000是否有影响,现在我把它注册码的部分那出来给大家看一看吧!而且它的注册码和硬件是有关系的,所以要想别人可以注册,就一定要写出注册机了!
下面就是它的比较程式了:
015f:0040e4a9 8d45c0 lea eax,[ebp-40]
015f:0040e4ac 8d55ac lea edx,[ebp-54]
015f:0040e4af 8a08 mov cl,[eax] ds:eax放的是你输入的注册码
015f:0040e4b1 3a0a cmp cl,[edx] ds:edx放的是正确的注册码
015f:0040e4b3 7516 jnz 0040e4cb
015f:0040e4b5 84c9 test cl,cl
015f:0040e4b7 746e jz 0040e527
015f:0040e4b9 8a4801 mov cl,[eax+01]
015f:0040e4bc 3a4a01 cmp cl,[edx+01]
015f:0040e4bf 750a jnz 0040e4cb
015f:0040e4c1 83c002 add eax,02
015f:0040e4c4 83c202 add edx,02
015f:0040e4c7 84c9 test cl,cl
015f:0040e4c9 75e4 jnz 0040e4af
015f:0040e4cb 745a jz 0040e527
在winsoftice里下以下命令可以见到:
:d ds:eax
0167:006DF33C 34 34 34 34 34 34 34 34-34 34 34 34 34 34 00 00 44444444444444..
0167:006DF34C 80 00 BC 58 C8 F3 6D 00-7E 51 46 00 8C 29 47 00 ...X..m.~QF..)G.
0167:006DF35C 1C F3 6D 00 14 00 00 00-00 00 78 83 F5 10 00 00 ..m.......x.....
0167:006DF36C 00 00 00 00 A0 0E 08 00-00 00 00 00 00 00 00 00 ................
:d ds:edx
0167:006DF328 32 39 34 46 41 41 38 36-33 30 44 30 35 39 00 58 294FAA8630D059.X
0167:006DF338 80 00 00 00 34 34 34 34-34 34 34 34 34 34 34 34 ....444444444444
0167:006DF348 34 34 00 00 80 00 BC 58-C8 F3 6D 00 7E 51 46 00 44.....X..m.~QF.
0167:006DF358 8C 29 47 00 1C F3 6D 00-14 00 00 00 00 00 78 83 .)G...m.......x.
好了,来段INI文件把帮它做一个注册机吧!
[Options]
CommandLine=Decompile Winhelp.exe 这是被取注册码的EXE文件名
Mode=0 采用模式0读取注册码
First_Break_Address=40E4AF 程式的中断地址,它和ICE中见到的是一样的
First_Break_Address_Code=8A 中断程式的1 Byte代码,这个8A就是015f:0040e4af的8A
First_Break_Address_Code_Lenth=2 中断行代码的长度(单位:byte)
Save_Code_Address=EDX 存放注册码的内存地址
生成后保存为CRACKCODE.INI文件,把CRACKCODE.EXE和CRACKCODE.INI一起copy到被注册的软件的安装目录下,运行CRACKCODE.EXE。哦!被取注册码的软件也运行了,到注册的窗口去,随便输入足够数量的注册码,按确定,哦!跳出一个显示窗来,里面出现了你想要的正确注册码了。是不是觉得很神奇呢!来试一试你就知道了!大家现在可以见到,用寄存器寻址是多么好的一件事啊!
下面我们再来看一看CrackCode2000的另一个工作模式吧!以下是关于美萍网管大师3.1的注册
机的写法:
大家看一看这个软件的比较程式吧!
015f:00460759 8bd8 mov ebx,eax
015f:0046075b b87c074600 mov eax,0046077c
015f:00460760 e81f000000 call 00460784
015f:00460765 3bd8 cmp ebx,eax 这里的ebx就是放你台机器
015f:00460767 7507 jnz 00460770 的正确的注册码了
015f:00460769 b801000000 mov eax,00000001
015f:0046076e 5b pop ebx
015f:0046076f c3 ret
好我们来写注册机了:
[Options]
CommandLine=scon.exe 这是被取注册码的EXE文件名
Mode=1 采用模式1读取注册码
First_Break_Address=460765 程式的中断地址,它和ICE中见到的是一样的
First_Break_Address_Code=3B 中断程式的1 Byte代码,这个3B就是015f:00460765的3B
First_Break_Address_Code_Lenth=2 中断行代码的长度(单位:byte)
Save_Code_Address=EBX 存放注册码的内存地址
大家看到了吗?今次CrackCode2000使用了模式1来读取了,因为今次的注册码不是直接用ASCII的形式放在内存中的,而是用数值的形式放在寄存器处的,所以这时就要用模式1了。生成后保存为CRACKCODE.INI文件,把CRACKCODE.EXE和CRACKCODE.INI一起copy到被注册的软件的安装目录下,运行CRACKCODE.EXE。哦!被取注册码的软件也运行了,哦!软件一运行注册码就出来了!哈哈。。。。。。
好了,我们再来进一步地研究CrackCode的加强模式吧!这是正式版本才具有的,二重断点读取注册码,这是CrackCode的增强模式,它可以使用二次重点的方法,来达到的目的,大家可能还不了解为什么要这样做吧!好,让我们看一看下面这个软件,你就明白这是多么的重要啊!
下面的实现例子是大家熟悉的Winzip7.0!好了开始吧!我们找到了它的比较程式了:
015f:00457920 8a06 mov al,[esi] 输入的注册码
015f:00457922 46 inc esi
015f:00457923 8a27 mov ah,[edi] 正确的注册码
015f:00457925 47 inc edi
015f:00457926 38c4 cmp ah,al
015f:00457928 74f2 jz 0045791c
015f:0045792a 2c41 sub al,41
015f:0045792c 3c1a cmp al,1a
015f:0045792e 1ac9 sbb cl,cl
015f:00457930 80e120 and cl,20
015f:00457933 02c1 add al,cl
015f:00457935 0441 add al,41
015f:00457937 86e0 xchg ah,al
015f:00457939 2c41 sub al,41
015f:0045793b 3c1a cmp al,1a
015f:0045793d 1ac9 sbb cl,cl
015f:0045793f 80e120 and cl,20
015f:00457942 02c1 add al,cl
015f:00457944 0441 add al,41
015f:00457946 38e0 cmp al,ah
015f:00457948 74d2 jz 0045791c
我们在winsoftice中下以下的命令:
:d ds:esi
0167:0047D958 34 38 34 38 34 38 34 38-34 38 00 00 00 00 00 00 4848484848......
0167:0047D968 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0167:0047D978 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
:d ds:edi
0167:0072F41C 43 39 36 32 30 35 45 42-00 00 01 00 00 00 0A 00 C96205EB........
0167:0072F42C D0 00 36 18 DA F4 0C 00-2C 20 0C 00 CE 1F 1A 84 ..6....., ......
0167:0072F43C 3F 19 5C 84 97 0F 47 04-00 00 0A 00 00 00 0A 00 ?.\...G.........
看到了吗?那ds:edi放的就是你要的东西啊!
好了,我们先试一试用普通模式0来写注册机吧!
[Options]
CommandLine=winzip32.exe 这是被取注册码的EXE文件名
Mode=0 采用模式1读取注册码
First_Break_Address=457923 程式的中断地址,它和ICE中见到的是一样的
First_Break_Address_Code=8A 中断程式的1 Byte代码,这个3B就是015f:00460765的3B
First_Break_Address_Code_Lenth=2 中断行代码的长度(单位:byte)
Save_Code_Address=EDI 存放注册码的内存地址
生成后保存为CRACKCODE.INI文件,把CRACKCODE.EXE和CRACKCODE.INI一起copy到被注册的软件的安装目录下,运行CRACKCODE.EXE。哦!winzip会说很多的dll找不到,不能正常运行。
哦!发生了什么事啊!好我们用winsoftice在那cs:457923下一个断点,重新运行winzip,哦!我们的winsoftice不断地中断,原来winzip的设计很特殊性,它会用比较注册码的程式来加载其它的dll,所以CrackCode的跟踪就不能正常地进行下去了。
好吧!我们再看一看程式吧!经过分析我们知道,上面的比较程式是由下面的程式调用去
做比较注册码的工作的。
015f:00407c14 50 push eax
015f:00407c15 57 push edi
015f:00407c16 e8ab000000 call 00407cc6 带过这个Call在上面的
015f:00407c1b 59 pop ecx 0167:0072F41C址中注册
015f:00407c1c be58d94700 mov esi,0047d958 码就出来了。
015f:00407c21 59 pop ecx
015f:00407c22 8d85c0feffff lea eax,[ebp-0140]
015f:00407c28 56 push esi
015f:00407c29 50 push eax
015f:00407c2a e8d1fc0400 call 00457900 这个Call就是调用比较
015f:00407c2f f7d8 neg eax 注册码的Call了。
015f:00407c31 1bc0 sbb eax,eax
015f:00407c33 59 pop ecx
015f:00407c34 40 inc eax
015f:00407c35 59 pop ecx
015f:00407c36 a37cb04700 mov [0047b07c],eax
本来我们可以在上面出现了注册之后就找一个中断地址中断用模式0去取注册啊!但有一点你们切记,那是到了万不得意时才使用的,我们要尽可能地用寄存器寻址。所以我们使用增强模式来解决这个问题。好了,我们在出现了注册码和调用比较注册码程式的Call之间找一个地址,但经过分析我选取015f:00407c1c这个地址,当然你也可以选择其它的。下面大家看一看INI文件是如何写的:
[Options]
CommandLine=winzip32.exe 这是被取注册码的EXE文件名
Mode=2 采用增强模式2读取注册码
First_Break_Address=407C1C 程式的中断地址1,它和ICE中见到的是一样的
First_Break_Address_Code=BE 中断程式的1 Byte代码,这个3B就是015f:00407c1c的BE
First_Break_Address_Code_Lenth=5 中断行代码的长度(单位:byte)
Second_Break_Address=457923 程式的中断地址2,它和ICE中见到的是一样的
Second_Break_Address_Code_Lenth=2 中断行代码的长度(单位:byte)
Save_Code_Address=EDI 存放注册码的内存地址
生成后保存为CRACKCODE.INI文件,把CRACKCODE.EXE和CRACKCODE.INI一起copy到被注册的软件的安装目录下,运行CRACKCODE.EXE。哦!被取注册码的软件也运行了,哦!软件一运行注册码就出来了!哈哈。。。。。。
摘要:注册机和补丁制作何为注册机?注册机就是针对某一软件,通过一定算法算出注册码的程序。我们写注册机时,一般都要了解注册码的算法(这当然是通过跟踪调试了解的),之后用汇编语言……
标签:加密 解密 crack 破解
2、Keymake使用(作者:刘健英 知软网)
这个注册机编写器以前一直是我自己为写注册机而编写的,通过它只要略有汇编基础很快就能写出一个注册机。而不需要再过多的了解程序的指令算法。 整个程序体实际上只是我用汇编写的一个模板。所以大家也可以在其中自定义自己的界面和提示信息。可以用VC++或BC++等资源编辑工具自行修改key1.res资源文件,但请不要修改它们对应的ID号。
例子程序,主要用来举例说明这个程序的使用(我先假设自己并不太懂Win32汇编)。
通过动态调试或反汇编例子程序可以得到以下注册码的计算过程:
xxxx:00401077 CALL GetCommandLineA
xxxx:0040107C CMP BYTE PTR [EAX],22
xxxx:0040107F JNZ 401082
xxxx:00401081 INC EAX
xxxx:00401082 MOV CX,WORD PTR [EAX]
xxxx:00401085 MOV WORD PTR [0040306C],CX
xxxx:0040108C MOV WORD PTR [0040306E],5C
xxxx:00401095 PUSH 0
xxxx:00401097 PUSH 0
xxxx:00401099 PUSH 0
xxxx:0040109B PUSH 0
xxxx:0040109D PUSH DWORD 00403058
xxxx:004010A2 PUSH 0
xxxx:004010A4 PUSH 0
xxxx:004010A6 PUSH DWORD 0040306C
xxxx:004010AB CALL GetVolumeInformationA
……………………
……………………
xxxx:0040111E MOV EAX,1
xxxx:00401123 CPUID
xxxx:00401125 MOV ECX,DWORD PTR [00403058]
xxxx:0040112B XOR EDX,EDX
xxxx:0040112D MUL ECX
xxxx:0040112F ADD EAX,EDX
xxxx:00401131 PUSH EAX
xxxx:00401132 PUSH DWORD 0040303E; 在这里下D 40303E可以看到数据窗口中显示为“%1X”
xxxx:00401137 PUSH DWORD 0040305C
xxxx:0040113C CALL wsprintfA
对于以上的指令并不需要过多的了解它在干什么,只要将其中的每个地址改成一个变量地址的声明,然后再原封不动的抄到注册机编写器的代码窗口中即可。
这是写好的声明:
a1 dd 0 | ; 这是一个双字的内存空间,对应于上面的403058。 ;(因为40109D处的指令是DWORD 403058,所以用dd,如果是WORD就用dw,如果是BYTE就用db) |
a2 dd 0 | ; 对应于上面的40306C |
a3 db "%1X",0 | ; 对应于上面的40303E指向的字符串 |
a4 db 20 dup (0) |
; 这是20个字节的内存空间,用来存放输出的注册码,对应于上面的40305C |
输入如图所示:
这是写好的程序代码:
CALL GetCommandLineA CMPBYTE PTR [EAX],22h | ; 后面加h表示是十六进制 |
JNZn1 | |
INCEAX | |
n1: | |
MOVCX,WORD PTR [EAX] | |
MOVWORD PTR a2,CX | |
MOVWORD PTR a2+2,5Ch | |
PUSH 0 | |
PUSH 0 | |
PUSH 0 | |
PUSH 0 | |
LEAEAX,a1 | ; 令EAX指向a1 |
PUSH EAX | |
PUSH 0 | |
PUSH 0 | |
LEAEAX,a2 | |
PUSH EAX | ; 令EAX指向a2 |
CALL GetVolumeInformationA | ; 当然这几条语句也可以直接写成 invoke GetVolumeInformationA,addr a2,0,0,addr a1,0,0,0,0 的形式 |
MOVEAX,1 | |
CPUID | |
MOVECX,a1 | |
XOREDX,EDX | |
MULECX | |
ADDEAX,EDX | |
PUSH EAX | |
LEAEAX,a3 | ; 令EAX指向a3,也就是指向字符“%1X”。 |
PUSH EAX | |
LEAEAX,a4 | |
PUSH EAX | |
CALL wsprintfA | |
LEA EAX,a4 |
; 令EAX指向a4。因为程序最后显示的就是EAX寄存器所指向的内存地址的数据。 |
输入如下图所示:
可以看到这与上面的反汇编代码基本相同。点击编译就可以很容易的得到一个注册机了。
生成的注册机如下图所示(这只是我写的外观,你也可以自行修改):
需要说明的是因为这只是我写的一个模板,所以我也在程序中使用了几个变量。
请不要再重复声明:hCursorHandle、hInstance、hIcon、hTempEbp、hInput、hMode以免出错。
还有就是你一定要在指令结束时令EAX指向正确的注册码地址。
这种算注册码的方法不是直接从用户所输入的序列号来计算注册码的,所以并不适用于所有情况。有时我们可能需要根据用户所填入的序列号来计算注册码。考虑到这种情况所以我在程序初使时令EAX指向第一个编辑框(也就是输入序列号的窗口)收到用户输入的数据,令EBX指向第二个编辑框收到用户输入的数据,令ECX指向第三个编辑框收到用户输入的数据。你如果要对用户输入的序列号或用户名等信息进行操作,那么可以就对EAX、EBX、ECX进行操作。
下面的代码是本例根据用户所填入的序列号来计算注册码的方法:
MOV ECX,EAX | ; EAX指向用户输入的八位序列号,现在暂将它移动到ECX寄存器 |
XOR EBX,EBX | ; 以下是一段典型的将内存中的ASCII码转换为十六进制代码。 |
n1: | |
MOVZX EAX,BYTE PTR [ECX] | |
OR AL,AL | |
JZ n3 | |
CMP AL,3Ah | |
JC n2 | |
SUB AL,7 | |
n2: | |
SUB AL,30h | |
SHL EBX,4 | |
ADD EBX,EAX | |
INC ECX | |
JMP n1 | |
n3: | ; 我想以上的一段代码应该懂汇编就能写的出(如果不是很明白,那么你对我编写好的注册机用TRW调试一次就知道了)。 |
PUSH EBX | ; 最后的十六进制结果都保存在寄存器EBX中 ; 将EBX入栈,这是为了将EBX寄存器的数据保存起来。因为经过CPUID这个指令后EBX的值将被修改。然后后面就和上面一样照抄程序中的指令。以下计算注册码的方法很简短。但在实际的破解过程中,程序的算法可能会相当复杂。这就需要你通过调试或反汇编将关键的运算指令都找出来,再写进来。 |
MOVEAX,1 | |
CPUID | |
POP ECX | ; 恢复EBX的值到ECX寄存器 |
XOREDX,EDX | |
MULECX | |
ADDEAX,EDX | |
PUSH EAX | |
LEAEAX,a3 | ; 令EAX指向a3,也就是指向字符“%1X”。 |
PUSH EAX | |
LEAEAX,a4 | |
PUSH EAX | |
CALL wsprintfA | |
LEA EAX,a4 |
; 令EAX指向a4。因为程序最后显示的就是EAX寄存器所指向的内存地址的数据。 |
下图分别是采用方案二和方案三编译后的窗口界面:
如果你不采用这种方法编写那么也可以使用程序中的另一个功能“另类注册机”。它和CrackCode2000一样,也是通过拦截程序指令并显示出注册码。 我之所以再写一个是因为以前的CrackCode2000提供的拦截选项非常有限,而且也不对Wide格式(出现在VB程序中用00将ASCII码分隔开)提供支持,还有一个毛病是在有些程序中会出现莫名的非法操作或无法获得注册码的情况(就好比这个例子程序)。 另外它的界面也太简陋了,只是一个消息框。所以我用汇编写了这个另类注册机非常小巧,它最多可以设置100个断点(其实可以更多,但好象没这个必要),以及在每个断点处中断多少次,如下图所示:
对于以上界面的说明:程序名称和中断地址的设置,这个我想用不着多说,会破解的人都懂。 而获取注册码的方式上需要说明一下,我是这样考虑的:寄存器方式-因为注册码可能是会放在寄存器中比较,并且可能经过十进制或十六进制的转换, 所以就提供了一个寄存器方式及十进制或十六进制的选项。 内存方式-是指:如设置为EDX,即指注册码保存在EDX所指向的内存地址中(而不是寄存器里)这样就为获取注册码提供了更多的选择。
可以自定义在弹出的对话框中将显示的主页、邮件和窗口标题,如下图所示:
生成的注册机有二个可选界面如下图所示:
需要说明的一点是这个对话框只在拦截成功的时候出现。
除此之外还有一个制作破解补丁的附加工具,制作界面如图所示。
这是完成界面。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。