PEDIY_CrackMe_2007专辑中逍遥风专题下的的一个CrackM 21, 编写工具为Delphi
今天俺也发一贴,看帖子好久了,尽管该CrackMe已经写过破文,鉴于自己第一次使用RadAsm写汇编注册机借此文记录一下学习过程,因为逍遥风的帖子破解过程已经很详细了,我这里就不再分析详情可参见原帖地址: http://bbs.pediy.com/showthread.php?threadid=29678,我这里知识介绍下RadAsm的使用方法以及写的注册机(代码里有注释,请结合破文一起阅读)
首先,介绍下情况,自己编程能力很差最初写程序使用的VB因为简单且容易实现,但是鉴于仰慕汇编的魅力还是尽量使用汇编写程序的好,(为什么说汇编魅力大这个优点太多了,首先你可以看下RadAsm这个程序编辑器安装包才3M,其他的VB精简版也得十几M,更不要提Visual C了,总之一句话短小的都是精品!不废话了。总之好处多多……)之前安装RadAsm已经很久了,可是就是不会使用,即便是复制一个程序编译运行始终不能成功。郁闷至极~终于有一天静下来学习下如何使用,也不枉了安装这个软件了。其实使用汇编写注册机挺方便的,并不需要创建窗体,而只需要调用一个对话框就可以了,因为对话框是API的预编译类,只需要调用就可以了。所以不需要你像普通应用程序样创建窗体前注册窗体类,显示窗台,更新用户区等等繁琐的代码。
介绍下使用方法
你可以在masm32目录下新建一个文件
然后粘贴如下程序,另存为x.asm 这时先不要急否则即使编译后生成了x.obj文件再连接生成x.exe,双击运行没有任何反应,因为还缺少一个重要的文件就是资源文件他负责指定你所用到的对话框资源,按钮以及文本框等内容,要另外粘贴到一个文件中 保存为rsrc.rc,资源文件名字固定为rsrc
只有当这两个文件都有了后,你才可以进行操作如下:
1.先选择构建菜单中的“编译资源脚本”将rsrc.rc编译成 rsrc.res格式(这样再连接时就添加到.exe文件中了)。
2.选择构建菜单中的构建(或者选则编译然后连接)生成.EXE文件
3.运行,就弹出了对话框
注册机有个需要注意的地方当Name长度大于4时计算SN前四个字节一次取Name第4个字节开始计算直到第一个。然后计算SN后四个字节时,取Name的倒数第2个字节开始直到取够4个字节计算结束。
如果输入NAME长度等于四时,在计算SN后四个字节时从Name倒数第2个开始取(即第3个字节)取不到4个字节,源程序中NAME前空间存储的是NAME长度因此第四个字节是NAME长度,这就是定义iLen在szName之前的原因。
代码部分:
资源内容如下:
#include "include\resource.h"
#define CrackMev1 101
#define IDC_EDT1 1001
#define IDC_EDT2 1002
#define ID_OK 1003
#define IDC_STATIC1 1004
#define IDC_STATIC2 1005
CrackMev1 DIALOGEX 6,6,185,97
CAPTION "CrackMe v1.0"
FONT 8,"MS Sans Serif",0,0
STYLE 0x10CE0800
EXSTYLE 0x00000000
BEGIN
CONTROL "Name:",IDC_STATIC1,"Static",0x50010000,10,11,22,15,0x00000200
CONTROL "Sn:",IDC_STATIC2,"Static",0x50010000,10,38,22,15,0x00000200
CONTROL "",IDC_EDT1,"Edit",0x50010000,34,11,116,13,0x00000200
CONTROL "",IDC_EDT2,"Edit",0x50010000,34,38,118,13,0x00000200
CONTROL "ok",ID_OK,"Button",0x50010000,58,62,68,15,0x00000000
END
程序文件x.asm内容如下:
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM
.const
IDD_DIALOG1 equ 101
IDC_EDT1 equ 1001
IDC_EDT2 equ 1002
ID_OK equ 1003
;#########################################################################
.data
szFormat db "%s",0
SzError db '输入名称太短,不能少于4个!',0
SzCaption db '错误提示',0
szText db '请输入名称',0
.data?
hInstance dd ? ;句柄
szSN db 9 dup (?),0 ;存放SN
iLen db ? ;存放Name长度(定义时注意一定要放到szName的前面当LEN=4时,会用到这个长度1个字节参与计算)
szName db 20 dup (?) ;存放Name
iLenName dd ? ;存放Name长度(定义成4个字节为了便于程序使用)
iNumName dd ? ;存放计算Name累加和
iNumTemp dd ? ;存放中间过程和
;#########################################################################
.code
start:
invoke GetModuleHandle,NULL ;获取模块句柄
mov hInstance,eax ;显示对话框时使用
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL;显示对话框
;invoke ExitProcess,0
;########################################################################
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_COMMAND
mov eax,wParam
.if ax==ID_OK ;点击按钮时,取Name文本框内容
invoke GetDlgItemText,hWin,IDC_EDT1,addr szName,80
.if !eax ;为空时,提示输入
invoke SetDlgItemText,hWin,IDC_EDT2,addr szText
.else ;不为空,则调用注册函数
call Reg
invoke wsprintf,addr szSN,addr szFormat,addr szSN ;转换存储的数据为字符串来显示
invoke SetDlgItemText,hWin,IDC_EDT2,addr szSN ;显示变量到SN文本框
.endif
.endif
.elseif eax==WM_CLOSE ;点击右上角差号时,退出程序
;invoke EndDialog,hWin,0
invoke ExitProcess,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
Reg Proc hWin:dword
pushad ;保存寄存器
MOV iLenName,0h ;变量初始化
MOV iNumName,0h
MOV iNumTemp,0h
LEA ESI,szName ;去变量地址偏移
XOR EDX,EDX ;清EDX,ECX
XOR ECX,ECX
CalLenName:
MOVZX EAX,BYTE PTR [ESI];取一个字节
TEST AL,AL ;判断是否为0
JE GetLenName ;为零则结束
ADD EDX,EAX ;不为零则累加
INC ECX ;Name字节数计数
INC ESI ;移动指针指向下一个字节
JMP CalLenName ;循环
GetLenName:
MOV iNumName,EDX ;保存Name累加和
MOV iLenName,ECX ;保存Name长度
MOV iLen,CL ;取一个字节的长度赋给变量
CMP ECX,4 ;长度是否小于4
JB LenTooSmall ;是则退出
LEA EDI,szSN ;取偏移存储变量地址
LEA ESI,szName
MOV ECX,1 ;循环四次计算SN前四个字节
CalSN1:
CMP ECX,4
JA CalSN1Over ;是否已循环四次
MOV BL,BYTE PTR [iNumTemp];取低位字节
;取Name第5-CL个字节
SUB ESI,ECX
OR BL,[ESI+4]
ADD ESI,ECX ;恢复ESI指针
PUSH CX ;保存CX内容
AND CL,01h
SHL BL,CL ;左移CL位
POP CX ;恢复CX
MOV DL,BYTE PTR [iNumName];
SHL DL,CL
ADD BL,DL
MOV AX,BX
MOV CH, 1Ah
DIV CH
ADD AH,41h
MOV [EDI],AH ;保存计算出的SN第CL个字节
INC EDI
XOR EAX,EAX
XOR CH,CH
ADD ESI,ECX
MOV AL,BYTE PTR [ESI-1]
SUB ESI,ECX
MUL CL
ADD DWORD PTR [iNumTemp],EAX
INC ECX
JMP CalSN1
CalSN1Over:
MOV BYTE PTR [EDI],2Dh;存“-”到第5个字节
INC EDI
XOR EAX,EAX
XOR EBP,EBP
MOV DWORD PTR [iNumTemp],0ABCDh
MOV ECX,1
CalSN2: ;计算SN后四个字节
CMP ECX,4
JA CalSNOver
MOV BL,BYTE PTR [iNumTemp]
MOV EBP,iLenName ;取Name第Len-CL个字节
SUB EBP,ECX
ADD ESI,EBP
MOV AL,[ESI-1]
SUB ESI,EBP
OR BL,AL
PUSH CX
AND CL,01h
SHL BL,CL
POP CX
MOV EDX,DWORD PTR [iNumName];取累加和
SHR EDX,CL ;右移CL位
ADD BL,DL
MOV AL,BL
MOV CH,1Ah
DIV CH
ADD AH,41h
MOV [EDI],AH ;保存计算出的SN第CL个字节
INC EDI
XOR CH,CH
MOV EBP,iLenName
ADD EBP,ECX
ADD ESI,EBP
MOV AL,[ESI-5]
SUB ESI,EBP
MUL CL
ADD DWORD PTR [iNumTemp],EAX
INC ECX
JMP CalSN2
CalSNOver:
POPAD
RET
LenTooSmall:
INVOKE MessageBox,0,ADDR SzError,ADDR SzCaption,MB_OK
POPAD
RET
Reg Endp
end start
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)