【文章标题】: 菜鸟注册机编写基础教程(汇编版)
【文章作者】: qwgboy2000
【作者邮箱】: qwgboy2000@126.com
【作者主页】: 无
【作者QQ号】: 27141459
【软件名称】: DCG_2_2.exe
【软件大小】: 503K
【下载地址】: DCG
【加壳方式】: 无
【保护方式】: Name/Serial
【编写语言】: Delphi
【使用工具】: MASM32、VC60的资源编辑器、OD、WINDOWS计算器
【操作平台】: WINXP
【软件介绍】: DCG出品
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
laomms老大曾经写过《菜鸟注册机编写基础教程》,详细介绍了如何用VB、Dephi、MFC写注册机,相信一定使很多像我一样的菜鸟受益非浅,在此向laomms等无私奉献的牛人们表示感谢。
好了,下面我们一起来看一下如何用WIN32ASM来写注册机呢?
我分为两步走的,第一步:找一个CrackMe分析出算法;第二步:用MASM32写注册机
【第一步:】
首先当然要先找一个CrackMe,于是找了一个CrackMe――DCG_2_2.exe开始了菜鸟用汇编写注册机之路。
首先用PEID查一下DCG_2_2.exe发现DELPHI写的没有加壳,然后用OD载入跑一下发现可以用字符串参考就可以下到断点了,窃喜~~~~~~~~
【详细过程】
通过字符串参考下断:
004665DB |. E8 08BBFCFF call 004320E8
004665E0 |. 8B55 EC mov edx, dword ptr [ebp-14] ; EDX=name
004665E3 |. 66:B9 E14D mov cx, 4DE1
004665E7 |. 8B45 F8 mov eax, dword ptr [ebp-8]
004665EA |. E8 41FCFFFF call 00466230 ; 关键CALL
004665EF |. 8D55 E8 lea edx, dword ptr [ebp-18]
004665F2 |. 8B45 FC mov eax, dword ptr [ebp-4]
004665F5 |. 8B80 00030000 mov eax, dword ptr [eax+300]
004665FB |. E8 E8BAFCFF call 004320E8
00466600 |. 8B45 E8 mov eax, dword ptr [ebp-18] ; EAX=Serial
00466603 |. 8B55 F4 mov edx, dword ptr [ebp-C]
00466606 |. E8 A1DDF9FF call 004043AC ; 真假serial比较,真的EAX返回0
0046660B |. 75 13 jnz short 00466620
0046660D |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0046660F |. 68 6C664600 push 0046666C ; |valid key
00466614 |. 68 6C664600 push 0046666C ; |valid key
00466619 |. 6A 00 push 0 ; |hOwner = NULL
0046661B |. E8 D400FAFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
//////////////////////////////////////////////
关键CALL部分:
00466230 /$ 55 push ebp
00466231 |. 8BEC mov ebp, esp
00466233 |. 83C4 E4 add esp, -1C
00466236 |. 53 push ebx
00466237 |. 33DB xor ebx, ebx
00466239 |. 895D E4 mov dword ptr [ebp-1C], ebx
0046623C |. 66:894D F6 mov word ptr [ebp-A], cx
00466240 |. 8955 F8 mov dword ptr [ebp-8], edx
00466243 |. 8945 FC mov dword ptr [ebp-4], eax
00466246 |. 33C0 xor eax, eax
00466248 |. 55 push ebp
00466249 |. 68 E9624600 push 004662E9
0046624E |. 64:FF30 push dword ptr fs:[eax]
00466251 |. 64:8920 mov dword ptr fs:[eax], esp
00466254 |. 66:8B45 F6 mov ax, word ptr [ebp-A]
00466258 |. 66:8945 EE mov word ptr [ebp-12], ax ; 4DE1H存入[ebp-12]
0046625C |. 8B45 08 mov eax, dword ptr [ebp+8]
0046625F |. E8 3CDDF9FF call 00403FA0
00466264 |. 8B45 F8 mov eax, dword ptr [ebp-8]
00466267 |. E8 F4DFF9FF call 00404260
0046626C |. 85C0 test eax, eax
0046626E |. 7E 63 jle short 004662D3
00466270 |. 8945 E8 mov dword ptr [ebp-18], eax ; [ebp-18]为循环终值(即name长度)
00466273 |. C745 F0 01000>mov dword ptr [ebp-10], 1 ; [ebp-10]为循环变量
0046627A |> 8B45 F8 /mov eax, dword ptr [ebp-8]
0046627D |. 8B55 F0 |mov edx, dword ptr [ebp-10]
00466280 |. 8A4410 FF |mov al, byte ptr [eax+edx-1] ; 依次读name的每个字符到AL
00466284 |. 0FB755 EE |movzx edx, word ptr [ebp-12]
00466288 |. C1EA 08 |shr edx, 8 ; 右移8位
0046628B |. 32C2 |xor al, dl ; AL与DL异或
0046628D |. 8845 F5 |mov byte ptr [ebp-B], al ; 暂存一下,设此结果为A
00466290 |. 33C0 |xor eax, eax
00466292 |. 8A45 F5 |mov al, byte ptr [ebp-B] ; 读出暂存的A
00466295 |. 66:0345 EE |add ax, word ptr [ebp-12] ; AX+[ebp-12]
00466299 |. 8B55 FC |mov edx, dword ptr [ebp-4]
0046629C |. 66:F76A 04 |imul word ptr [edx+4] ; *CE6D(CE6D是固定值)
004662A0 |. 8B55 FC |mov edx, dword ptr [ebp-4]
004662A3 |. 66:0342 06 |add ax, word ptr [edx+6] ; +58BF(58BF是固定值)
004662A7 |. 66:8945 EE |mov word ptr [ebp-12], ax ; 保存
004662AB |. 8D4D E4 |lea ecx, dword ptr [ebp-1C]
004662AE |. 33C0 |xor eax, eax
004662B0 |. 8A45 F5 |mov al, byte ptr [ebp-B]
004662B3 |. BA 02000000 |mov edx, 2
004662B8 |. E8 831CFAFF |call 00407F40 ; 把A转成十六进制字符串,例如ASCII为36H,就转化为‘3’‘6’
004662BD |. 8B55 E4 |mov edx, dword ptr [ebp-1C]
004662C0 |. 8B45 08 |mov eax, dword ptr [ebp+8]
004662C3 |. E8 A0DFF9FF |call 00404268 ; 连接字符串所转换的字符串,循环结束即为正确的serial
004662C8 |. 8B45 08 |mov eax, dword ptr [ebp+8]
004662CB |. FF45 F0 |inc dword ptr [ebp-10]
004662CE |. FF4D E8 |dec dword ptr [ebp-18]
004662D1 |.^ 75 A7 \jnz short 0046627A
004662D3 |> 33C0 xor eax, eax
004662D5 |. 5A pop edx
004662D6 |. 59 pop ecx
004662D7 |. 59 pop ecx
004662D8 |. 64:8910 mov dword ptr fs:[eax], edx
004662DB |. 68 F0624600 push 004662F0
004662E0 |> 8D45 E4 lea eax, dword ptr [ebp-1C]
004662E3 |. E8 B8DCF9FF call 00403FA0
004662E8 \. C3 retn
以上是CrackMe的算法部分总结并转化为我们下面注册机的题目如下:
输入一个name,运算以后输出Serial
运算过程如下
初始数据有3个CE6D,58BF,X=4DE1
1、X>>8 ==> Y
2、依次取name的一个字符与上面的Y异或 ==> S
3、((S+X)*CE6D+58BF)&FFFF ==> X
4、S转化为ASCII码对应的两个字符(例如36H就变成'3''6')连接到Serial后面
4、循环到1、直到所有name的字符取完
直到这里为止第一步已经完成了,下面我们来实现第二步。
【第二步:】
用MASM32环境进行注册机的编写,因为本文面对没有使用过MASM32环境的朋友,所以说的详细(罗嗦)一些,高手可以跳过。
首先我们来准备一下运行环境(建议放弃MASM32简单的IDE环境,改为在命令行下用nmake工具进行代码维护):
为了建立这个环境,需要做下面的工作:
第1步:安装常用软件,包括编辑软件Editplus,MSDN,16进制编辑器hexedit,可视化资源编辑器Resource Workshop,调试工具OD和反汇编软件W32DASM等,如果空间允许的话,最好安装Visual C++,以便使用它集成的资源编辑器。
第2步:选择一个驱动器安装MASM32软件包,安装好的目录是x:\Masm32目录,对读者来说整个软件包中重要的只有3个目录:bin目录中有汇编编译器ml.exe,资源编译器rc.exe和链接器Link.exe等执行文件;include目录中有各种头文件;lib目录中有全部导入库。MASM32没有选择地把安装目录名定为masm32,如果不满意的话,完全可以把这3个关键目录拷贝到别的用户自己命名的目录中,对使用没有任何影响。
第3步:建立源文件目录,由于Win32汇编不再像DOS汇编一样一个项目只有一个asm文件,而是包括asm,rc,makefile和图标等多个文件,如果把多个项目的文件混在同一个目录中将无法分辨,所以必须为每个项目单独建立一个目录,建议把这些目录集中在一个专门放置源程序的目录中,如x:\Source目录。
第4步:由于MASM32软件包中没有nmake.exe文件,所以要单独寻找nmake.exe并拷贝到bin目录中。
第5步:为这个环境建立一个设置环境变量的批处理文件,假设文件名为Var.bat,那么这个文件内容如下:
@echo off
set include=x:\masm32\Include
set lib=x:\masm32\lib
set path=x:\masm32\bin;%path%
echo on
好了环境我们已经准备好了,下面开工开始写注册机
首先注册机要有对话框资源,我们可以用VC60的资源编辑器来完成这个工作,我们要做两个对话框一个是输入Name得出Serial的,一个是“关于注册机”的对话框。
建立好以后保存为Dialog.rc,然后用文本编辑器打开并去掉那些不重要甚至是阻碍我们用MASM32环境来编译的部分。我的Dialog.rc如下:
#include "resource.h"
#define ICO_MAIN 0x1000 //图标,这里值随便定义但是要和ASM里面相同
#define DLG_MAIN 1 //主对话框
#define IDD_ABOUTBOX 2 //关于对话框
#define IDC_STATIC1 11 //编辑框1,我们这里就是输入Name的那个编辑框
#define IDC_STATIC2 12 //编辑框2,我们这里就是得出Serial的那个编辑框
ICO_MAIN ICON "DCG_KeyGen.ico" //定义图标,我们这里用的是DCG标志的图标,你当然可以自己换一个好看的
IDD_ABOUTBOX DIALOG DISCARDABLE 193, 180, 234, 69
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU //定义了关于对话框的很多属性,具体意思不必要太了解,可以在resource.h里面查到
CAPTION "关于 DCG_2_2.exe_KeyGen" //对话框标题
FONT 9, "宋体" //对话框中字的字号、字体
BEGIN //可以换成 { (如果换了下面也要换)
ICON ICO_MAIN,-1,11,14,20,20 //图标放的位置
LTEXT "DCG_2_2.exe_KeyGen 2.0 版",IDC_STATIC,38,10,134,8, //标签文本
SS_NOPREFIX
DEFPUSHBUTTON "确定",IDOK,177,7,50,14,WS_GROUP //确定按纽
LTEXT "by qwgboy2000",IDC_STATIC,39,23,144,12 //标签文本
LTEXT "http://www.dcg.org.cn",IDC_STATIC,39,36,153,13 //标签文本
LTEXT "dAyCrAckingGroup@tom.com",IDC_STATIC,39,50,153,13 //标签文本
END //可以换成 }(如果换了上面也要换)
DLG_MAIN DIALOG 193, 180, 240, 60
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW //定义了主对话框的很多属性,具体意思不必要太了解,可以在resource.h里面查到
CAPTION "DCG_2_2.exe_KeyGen" //主对话框标题
FONT 9, "宋体" //字号、字体
BEGIN //可以换成 { (如果换了下面也要换)
DEFPUSHBUTTON "确定",IDOK,180,7,50,19 //确定按纽
PUSHBUTTON "关于",IDCANCEL,180,30,50,19 //关于按纽
LTEXT "Name:",IDC_STATIC,7,7,30,19 //标签Name
LTEXT "Serial:",IDC_STATIC,7,30,30,19 //标签Serial
EDITTEXT IDC_STATIC1,58,7,104,17,ES_AUTOHSCROLL //编辑框1
EDITTEXT IDC_STATIC2,57,29,104,17,ES_AUTOHSCROLL | ES_READONLY //编辑框2
END //可以换成 }(如果换了上面也要换)
对话框资源是做好了,其实用VC资源编辑器很容易做,但是作注释却化了我不少时间(拼音打字不容易呀)
下面终于到代码部分了,我们建立了一个Dialog.asm的文件,内容如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Dialog.asm
; 对话框资源使用的模板代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Dialog.asm
; rc Dialog.rc
; Link /subsystem:windows Dialog.obj Dialog.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000h ;图标,和资源文件里面的对应
DLG_MAIN equ 1 ;主对话框
IDD_ABOUTBOX equ 2 ;关于对话框
IDC_STATIC1 equ 11 ;输入Name的编辑框
IDC_STATIC2 equ 12 ;得出Serial的编辑框
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段 , 这里定义的都是全局变量
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
InforMation db "请输入name",0
.data?
hInstance dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;首先是关于对话框的部分,没有太多要特别解释的地方,
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcABOUT proc uses ebx edi esi hWnd,wMsg,wParam,lParam
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDOK ;点确定按纽就退出关于对话框
invoke EndDialog,hWnd,NULL
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcABOUT endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;这里是主对话框的部分,关键算法就在这里写了
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @szName[20]:byte ;定义局部变量字节型数组,这个看名字就知道是接收name用的了
local @szSerial[40]:byte ;定义局部变量字节型数组,这个看名字就知道是发Serial用的了
local @szLength:dword ;定义一个dword类型的变量
local @temp:word ;定义一个word类型的变量
invoke RtlZeroMemory,addr @szName,sizeof @szName ;对@szName变量清0
invoke RtlZeroMemory,addr @szSerial,sizeof @szSerial ;对@szSerial清0,(为什么要清0呢?因为不清0会出现一些不是我们想要的随机字符)
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDCANCEL
invoke DialogBoxParam,hInstance,IDD_ABOUTBOX,NULL,offset _ProcABOUT,NULL ;点"关于"按纽弹出关于对话框
.endif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;紧接着下面就是关键算法部分了
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.if ax == IDOK ;点"确定"按纽
invoke GetDlgItemText,hWnd,IDC_STATIC1,addr @szName,sizeof @szName ;得到编辑框1的内容
mov @szLength,eax ;得到编辑框1长度放入@szLength
mov @temp,4de1h ;3个固定值还记得吗?这里先用到一个了放入@temp
.if @szLength==0 ;如果编辑框1为空
invoke SetDlgItemText,hWnd,IDC_STATIC2,addr InforMation ;编辑框2的内容变为"请输入name"
.else ;否则到(核心部分了)
lea esi,@szSerial ;@szSerial字符串的首地址给esi(这里不能用mov esi,offset @szSerial,因为@szSerial是局部变量,地址是放在堆栈中的,用offset会提示出错)
xor ebx,ebx ;ebx=0
mov cx,@temp
mov ax,cx ;ax=4de1
suanfa:shr ax,8 ;循环部分了,ax>>8
lea esi,@szName ;取@szName首地址
mov dl,[esi+ebx] ;依次取Name的字符
xor al,dl ;^al
mov dl,al ;暂存
and al,0fh ;保留al的后四位
lea esi,@szSerial ;取Serial的首地址
.if al<0ah ;这个if是把值转化为16进制字符的
add al,30h
.else
add al,37h
.endif ;直到这里,就是如果小于10的话就加30H,大于10的话就加37H
mov [esi+2*ebx+1],al ;上面算出的字符放到Serial的相应位置
mov al,dl ;读取暂存
shr al,4 ;取al前四位
.if al<0ah ;同上的if把al内容转换位16进制字符
add al,30h
.else
add al,37h
.endif
mov [esi+2*ebx],al ;结果保存到Serial的相应位置
movzx ax,dl ;零扩展
add ax,cx ;+cx
mov dx,0ce6dh ;3个固定值的第二个了
imul dx ;*固定值ce6dh
add ax,058bfh ;+3个固定值的第三个了
and ax,0ffffh
mov cx,ax ;存入cx,以便循环继续使用
inc ebx
cmp ebx,@szLength ;判断Name的每个字符是不是算完了
jl suanfa ;没算完就继续循环算,算完了就好了
invoke SetDlgItemText,hWnd,IDC_STATIC2,addr @szSerial ;把最终得到的@szSerial送到编辑框2显示出来
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
好了Dialog.asm我们也写好了
下面就是编译了,我们来做一个makefile文件,为什么要做一个makefile文件呢?我们上面说了:建议放弃MASM32简单的IDE环境,改为在命令行下用nmake工具进行代码维护
makefile文件内容如下
NAME = Dialog
OBJS = $(NAME).obj
RES = $(NAME).res
LINK_FLAG = /subsystem:windows
ML_FLAG = /c /coff
$(NAME).exe: $(OBJS) $(RES)
Link $(LINK_FLAG) $(OBJS) $(RES)
.asm.obj:
ml $(ML_FLAG) $<
.rc.res:
rc $<
clean:
del *.obj
del *.res
好了下面编译一下就可以了,终于完成了,有的人会说怎么那么长呀?真麻烦。其实大多都是框架结构而已。你可以直接照抄就可以了,只要在关键算法那里改成你自己的就好了,这样一想是不是也不难呀,甚至比其他工具写要更简单呢。。。。
祝大家天天进步,最后感谢一下QQ群:老罗汇编中的雅枫大哥,他RP非常不错,请教问题都能耐心给予解答。
--------------------------------------------------------------------------------
【经验总结】
相信不少和我一样的菜鸟要感叹:天了!原来用WIN32ASM来写注册机那么容易!
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年01月10日 下午 09:39:45
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: