下载地址:http://bbs.pediy.com/showthread.php?threadid=29940
使用工具:
反编译工具:IDA,Resource Hacker
程序开发包:MASM32 这个程序用PEID查的结果是MASM/TASM编译的,而实际上更象是TASM:第一,代码区段的名字是CODE
而不是.text;第二,建立堆栈框架是用enter指令而不是push ebp; mov ebp, esp;第三,导入表中有
一大堆程序里并未用到的函数。
用IDA载入程序,并且用Resource Hacker分析资源,将控件ID等常数用符号表示出来。由于这次的
反汇编内容比较长,为了不影响阅读起见,把它放在正文后面了。
主界面是用DialogBoxParam建立的对话框,但在GetModuleHandle之后有一大段给某个WNDCLASSEX结
构体赋值的指令,让人还以为他要注册窗口类,但最后又不见调用RegisterClassEx之类的函数,这段代
码是垃圾,鉴定完毕,哈哈,不过怎么知道那是给一个WNDCLASSEX结构体赋值呢?一般来说,如果连续
出现几个mov语句,给地址是连续的几个内存单元依次赋值的话,那就很可能是在给某个结构体的各成员
赋初始值了,至于这个结构体是什么,那就看你对于一些常见的结构体是否熟悉了,比如现在给内存单
元[402138]赋的值是一个位于代码区段中的偏移量,把接着的两个双字填0以后,又接着把hInstance的
值赋给[402144],马上就应该联想到WNDCLASSEX结构体中,成员lpfnWndProc往后跳过两个成员的地方正
是成员hInstance,那就试试看这是不是个WNDCLASSEX结构体吧!lpfnWndProc成员在WNDCLASSEX中的偏
移是8,那么结构体的首地址应该在402138 - 8 = 402130的地方,让IDA把这个地址开始的一片区域分析
成一个WNDCLASSEX结构,再回到这段代码的地方一看,果然下面装载图标、装载光标所得的结果都被赋
给了正确的字段,从而证实我们的猜测。与之同样道理,下面的GetMessage中也可以把地址402118开始
的地方分析成一个MSG结构体,不过这样的话这个结构体的最后一个字段跟刚才的WNDCLASSEX结构体的第
一个字段cbsize发生重叠,不可能两方面都顾全,反正这也是段无用代码,随它去吧!
罗嗦了那么多,现在继续跟踪流程,DialogBoxParam函数结束以后是一个jmp指令,跳到的地方(即
loc_4010C7标号处)先是进行一些出栈操作然后ret返回,难道程序是用这种方式结束并返回到操作系统
的?但为什么返回之前又要pop呢,程序开始运行的地方并没有对应的push操作呀!这难道不会引起堆栈
不平衡而导致返回地址错误吗?跟进对话框过程里可以发现,当对话框决定结束的时候,不是象通常那
样调用EndDialog,而是直接调用ExitProcess来个一了百了,也就是说,不会等到DialogBoxParam返回
的时候,整个进程就结束了;并且ExitProcess调用的时候甚至连uExitCode参数都懒得给,直接用当前
的[esp]值做这个参数,如果用调试器跟踪就会发现这个uExitCode的值是些象12FB74之类的奇怪数值,
他的逻辑就是管你什么堆栈不平衡,我退出进程的时候反正把我用的堆栈都释放掉了,你能奈我何!虽
然还不至于引起系统崩溃,但这种编程风格实在太差,在源码里我将其改成了常规的流程。
在对话框过程的WM_INITDIALOG消息处理分支里也是直接返回TRUE,让Windows把输入焦点设置到第
一个定义了WS_VISIBLE | WS_TABSTOP的控件上,在资源脚本里这个控件是Close按钮,这似乎有点不同
于常识,若不喜欢,可以自行调整资源脚本中的控件顺序。
验证注册码的算法是:用户名不能超过8个字符,只能由字母组成,程序中将其转为大写字母,然后
依次读取用户名的每个字符并到一个串
szIndex = "A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9"
中找到这个字符所在的位置,然后把串
szTable = "SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF"
中对应位置的字符写入到szUnlockCode中(相当于换码),这样处理完整个用户名以后,szUnlockCode
中就是真正的序列号了;然后将输入的序列号与之进行比较。例如:
用户名:PEDIY
在szIndex中找到这五个字母,然后看szTable中对应位置的字符:
序列号:SFK0L
但是注意验证流程中的两点:
第一,程序只把小于'A'及大于'z'的字符判为非法输入,其他判为合法,这其中就包括小于'a'但大
于'Z'的字符,譬如我输入字符'\',它的ASCII码为5Ch,不会被判非法,按照验证的逻辑应该减去20h变
成字符'<',但是在szIndex中无法找到这个字符,也就是说,这种用户名虽然合法但不可能有对应的序
列号,这也算是个Bug。在源码里我把合法输入的范围严格限定为字母了;
第二,从szTable取字符到szUnlockCode中属于字节操作,那就应该直接用一个8位寄存器中转,而
没有必要先扩展到eax然后用eax来中转,容易引起误解。
另外,由于输入只能是字母,szIndex中的数字就显得多余了,去掉这些数字,最好顺便把szIndex
调整成顺序字母表,当然要同时调整szTable,如下:
szIndex = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
szTable = "S4SKF0CN0FS770SSO9CRDN98LV"
这样一来,甚至于szIndex都没有存在的意义了,因为当用到一个字母的索引时,只需要用这个字母减去
'A'就可以了。代码就可以进一步优化。
上传文件内容:1.asm 按上述讨论整理过的源码(含注册机条件汇编)
1.rc 资源脚本
2.rc 注册机资源脚本
Icon_1.ico 图标 ===========================以下是代码========================
;分析资源得出
; enum Control_IDs
DLG_MAIN = 1
ICO_MAIN = 1
ID_CHECK = 1
ID_CLOSE = 2
EDT_NAME = 3
EDT_SERIAL = 4 public start
start proc near
push NULL ; lpModuleName
call GetModuleHandleA
mov ds:hInstance, eax
mov ds:stMyclass.style, CS_VREDRAW or CS_HREDRAW or CS_GLOBALCLASS
mov ds:stMyclass.lpfnWndProc, offset sub_4010AB
mov ds:stMyclass.cbClsExtra, 0
mov ds:stMyclass.cbWndExtra, 0
mov eax, ds:hInstance
mov ds:stMyclass.hInstance, eax
push ICO_MAIN ; lpIconName
push eax ; hInstance
call LoadIconA
mov ds:stMyclass.hIcon, eax
push IDC_ARROW ; lpCursorName
push NULL ; hInstance
call LoadCursorA
mov ds:stMyclass.hCursor, eax
push 0 ; dwInitParam
push offset _ProcDlgMain ; lpDialogFunc
push NULL ; hWndParent
push DLG_MAIN ; lpTemplateName
push ds:hInstance ; hInstance
call DialogBoxParamA
jmp short loc_4010C7
start endp loc_401074: ; CODE XREF: CODE:0040109Ej
push 0
push 0
push 0
push offset stMyMsg
call GetMessageA
cmp ax, 0
jz short loc_4010A0
push offset stMyMsg
call TranslateMessage
push offset stMyMsg
call DispatchMessageA
jmp short loc_401074
loc_4010A0: ; CODE XREF: CODE:00401088j
push dword ptr ds:unk_402120
call ExitProcess ; int __stdcall sub_4010AB(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
sub_4010AB proc near ; DATA XREF: start+16o
hWnd = dword ptr 8
Msg = dword ptr 0Ch
wParam = dword ptr 10h
lParam = dword ptr 14h
enter 0, 0
push esi
push edi
push ebx
jmp short $+2
push [ebp+lParam] ; lParam
push [ebp+wParam] ; wParam
push [ebp+Msg] ; Msg
push [ebp+hWnd] ; hWnd
call DefWindowProcA
jmp short $+2
loc_4010C7: ; CODE XREF: start+72j
pop ebx
pop edi
pop esi
leave
retn 10h
sub_4010AB endp ;对话框过程
; BOOL __stdcall ProcDlgMain(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
_ProcDlgMain proc near ; DATA XREF: start+5Eo
hWnd = dword ptr 8
uMsg = dword ptr 0Ch
wParam = dword ptr 10h
lParam = dword ptr 14h
enter 0, 0
push ebx
push esi
push edi
jmp short loc_4010F4
loc_4010D7: ; CODE XREF: _ProcDlgMain+125j
push MB_TASKMODAL ; uType
push offset szCaption ; "Duelist's Crackme #4"
push offset szTxtRegSucc ; "Congratulations! Please send your keyge"...
push NULL ; hWnd
call MessageBoxA
mov eax, TRUE
jmp short loc_401119
loc_4010F4: ; CODE XREF: _ProcDlgMain+7j
cmp [ebp+uMsg], WM_COMMAND
jz loc_4011FB
cmp [ebp+uMsg], WM_INITDIALOG
jz short loc_401120
cmp [ebp+uMsg], WM_CLOSE
jz loc_40120B
mov eax, 0
loc_401119: ; CODE XREF: _ProcDlgMain+24j
; _ProcDlgMain+57j ...
pop edi
pop esi
pop ebx
leave
retn 10h ; uExitCode
loc_401120: ; CODE XREF: _ProcDlgMain+3Aj
mov eax, TRUE
jmp short loc_401119
loc_401127: ; CODE XREF: _ProcDlgMain+131j
push 0 ; lParam
push 0 ; wParam
push WM_GETTEXTLENGTH ; Msg
push EDT_NAME ; nIDDlgItem
push [ebp+hWnd] ; hDlg
call SendDlgItemMessageA
mov ds:uNameLen, eax
cmp eax, 0
jz badboy
cmp eax, 8
jg badboy
mov esi, eax
push 0 ; lParam
push 0 ; wParam
push WM_GETTEXTLENGTH ; Msg
push EDT_SERIAL ; nIDDlgItem
push [ebp+hWnd] ; hDlg
call SendDlgItemMessageA
cmp eax, 0
jz badboy
cmp esi, eax
jnz badboy
push offset szUserName ; lParam
push 8 ; wParam
push WM_GETTEXT ; Msg
push EDT_NAME ; nIDDlgItem
push [ebp+hWnd] ; hDlg
call SendDlgItemMessageA
push offset szSerial ; lParam
push 10h ; wParam
push WM_GETTEXT ; Msg
push EDT_SERIAL ; nIDDlgItem
push [ebp+hWnd] ; hDlg
call SendDlgItemMessageA
mov ecx, -1
loc_40119C: ; CODE XREF: _ProcDlgMain+10Bj
inc ecx
movsx eax, ds:szUserName[ecx]
cmp eax, 0 ; 是否已到达串尾
jz short loc_4011DB
mov esi, -1
cmp eax, 'A'
jl short badboy
cmp eax, 'z'
ja short badboy
cmp eax, 'Z'
jl short loc_4011C0
sub eax, 20h ; 转大写字母
loc_4011C0: ; CODE XREF: _ProcDlgMain+EDj
; _ProcDlgMain+FCj
inc esi
movsx edx, byte ptr ds:szIndex[esi] ; "A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9"
cmp eax, edx
jnz short loc_4011C0
movsx eax, byte ptr ds:szTable[esi] ; "SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF"
mov ds:szUnlockCode[ecx], eax
jmp short loc_40119C
loc_4011DB: ; CODE XREF: _ProcDlgMain+D9j
push ds:uNameLen
push offset szUnlockCode
push offset szSerial
call sub_401244 ; 比较上面二个字符串
cmp eax, 1
jz loc_4010D7
jmp short badboy
loc_4011FB: ; CODE XREF: _ProcDlgMain+2Dj
cmp [ebp+wParam], ID_CHECK
jz loc_401127
cmp [ebp+wParam], ID_CLOSE
jnz short loc_40123A
loc_40120B: ; CODE XREF: _ProcDlgMain+40j
call ExitProcess
mov eax, 1
jmp loc_401119
badboy: ; CODE XREF: _ProcDlgMain+71j
; _ProcDlgMain+7Aj ...
push MB_TASKMODAL ; uType
push offset szCaption ; "Duelist's Crackme #4"
push offset szTxtRegFail ; "Your registration info is invalid... No"...
push NULL ; hWnd
call MessageBoxA
mov eax, 0
jmp loc_401119
loc_40123A: ; CODE XREF: _ProcDlgMain+13Bj
mov eax, 0
jmp loc_401119
_ProcDlgMain endp sub_401244 proc near ; CODE XREF: _ProcDlgMain+11Dp
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch
arg_8 = dword ptr 10h
enter 0, 0
mov eax, 1
mov edi, [ebp+arg_0]
mov esi, [ebp+arg_4]
mov ecx, [ebp+arg_8]
repe cmpsb
jcxz locret_401260
mov eax, 0
locret_401260: ; CODE XREF: sub_401244+14j
leave
retn 0Ch
sub_401244 endp DATA segment para public 'DATA' use32
assume cs:DATA
;org 402000h
db 20h
; char szCaption[]
szCaption db 'Duelist',27h,'s Crackme #4',0 ; DATA XREF: _ProcDlgMain+Eo
; _ProcDlgMain+151o
db 20h
szIndex db 'A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9',0 ; DATA XREF: _ProcDlgMain+F3r
db 20h
szTable db 'SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF',0 ; DATA XREF: _ProcDlgMain+FEr
db 20h
; char szTxtRegSucc[]
szTxtRegSucc db 'Congratulations! Please send your keygen (working one) to du'
; DATA XREF: _ProcDlgMain+13o
db 'elist@beer.com!',0
db 20h
; char szTxtRegFail[]
szTxtRegFail db 'Your registration info is invalid... Note that most of the s'
; DATA XREF: _ProcDlgMain+156o
db 'pecial chars may raise registration problems!',0
stMyMsg db 0 ; DATA XREF: CODE:0040107Ao
; CODE:0040108Ao ...
db 0
db 0
db 0
db 0
db 0
db 0
db 0
unk_402120 db 0 ; DATA XREF: CODE:loc_4010A0r
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
stMyclass WNDCLASSEX <0> ; DATA XREF: start+Cw start+16w ...
szUserName db 19h dup (0) ; DATA XREF: _ProcDlgMain+A3o
szSerial db 1Bh dup (0) ; DATA XREF: _ProcDlgMain+B6o
; _ProcDlgMain+118o
szUnlockCode dd 0 ; DATA XREF: _ProcDlgMain+105w
; _ProcDlgMain+113o
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
; HINSTANCE hInstance
hInstance dd 0 ; DATA XREF: start+7w start+34r ...
uNameLen dd 0 ; DATA XREF: _ProcDlgMain+69w
; _ProcDlgMain:loc_4011DBr
===========================以上是代码========================
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: