【文章标题】: CRC32CrackMe分析过程及汇编注册机源码
【文章作者】: WindRand
【作者邮箱】: WindRand@163.com
【软件名称】: CRC32CrackMe
【软件大小】: 13KB
【下载地址】: http://bbs.pediy.com/showthread.php?t=47488
【软件介绍】: 用CRC32作为校验算法的CrackMe。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
首先打开CRC32CrackMe,随便输入一个用户名字,我这里输入用户名为:WindRand,注册码为:1234567890,点“注册认证”提示错误。 到这里已经收集到注册失败后的信息,在OD中载入,通过查找Label,找到获取用户信息的API函数,在GetDlgItemTextA函数上F2下断,运行起来点击注册认证按钮后断在这里:
00401275 . 8B1D A4504000 mov ebx, dword ptr [<&USER32.GetDlgI>; ;断在这里
0040127B . 8D8C24 0C0100>lea ecx, dword ptr [esp+10C]
00401282 . 68 00010000 push 100 ; /;缓冲区大小
00401287 . 51 push ecx ; |;缓冲区
00401288 . 68 E8030000 push 3E8 ; |;控件ID
0040128D . 56 push esi ; |;句柄
0040128E . FFD3 call ebx ; \;调用GetDlgItemTextA函数
00401290 . 8DBC24 0C0100>lea edi, dword ptr [esp+10C] ; ;取得输入的用户名
00401297 . 83C9 FF or ecx, FFFFFFFF
0040129A . 33C0 xor eax, eax
0040129C . F2:AE repne scas byte ptr es:[edi]
0040129E . F7D1 not ecx
004012A0 . 49 dec ecx
004012A1 . 83F9 01 cmp ecx, 1 ; ;判断用户名是否为空
004012A4 . 73 1F jnb short 004012C5 ; ;不小于的话走
004012A6 . 6A 40 push 40 ; /;按钮样式
004012A8 . 68 8C604000 push 0040608C ; |;标题内容
004012AD . 68 74604000 push 00406074 ; |;内容
004012B2 . 56 push esi ; |;句柄
004012B3 . FF15 A8504000 call dword ptr [<&USER32.MessageBoxA>>; \调用MessageBoxA函数
004012B9 . 5F pop edi
004012BA . 5E pop esi
004012BB . 33C0 xor eax, eax
004012BD . 5B pop ebx
004012BE . 81C4 00030000 add esp, 300
004012C4 . C3 retn
004012C5 > 8D5424 0C lea edx, dword ptr [esp+C]
004012C9 . 68 00010000 push 100
004012CE . 52 push edx
004012CF . 68 07040000 push 407
004012D4 . 56 push esi
004012D5 . FFD3 call ebx ; ;调用GetDlgItemTextA函数
004012D7 . 8D7C24 0C lea edi, dword ptr [esp+C] ; ;取得输入的注册码
004012DB . 83C9 FF or ecx, FFFFFFFF
004012DE . 33C0 xor eax, eax
004012E0 . F2:AE repne scas byte ptr es:[edi] ; ;取注册码长度
004012E2 . F7D1 not ecx
004012E4 . 49 dec ecx
004012E5 . 83F9 01 cmp ecx, 1 ; ;判断注册码是否为空
004012E8 . 73 1F jnb short 00401309 ; ;不为空则跳走
004012EA . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004012EC . 68 8C604000 push 0040608C ; |Title = ""D7,"",A2,"",B2,"崽崾?
004012F1 . 68 5C604000 push 0040605C ; |Text = ""D7,"",A2,"",B2,"崧?,B2,"",BB,"能为空请输入!"
004012F6 . 56 push esi ; |hOwner
004012F7 . FF15 A8504000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
004012FD . 5F pop edi
004012FE . 5E pop esi
004012FF . 33C0 xor eax, eax
00401301 . 5B pop ebx
00401302 . 81C4 00030000 add esp, 300
00401308 . C3 retn
00401309 > 8D8424 0C0200>lea eax, dword ptr [esp+20C] ; ;返回参数
00401310 . 8D8C24 0C0100>lea ecx, dword ptr [esp+10C] ; ;输入的用户名
00401317 . 50 push eax
00401318 . 51 push ecx
00401319 . E8 F2FDFFFF call 00401110 ; ;算法实现Call,F7跟进去
0040131E . 8D9424 140200>lea edx, dword ptr [esp+214] ; ;上一个Call计算得到的值
00401325 . 8D4424 14 lea eax, dword ptr [esp+14] ; ;输入的注册码
00401329 . 52 push edx ; ;正确的注册码压栈
0040132A . 50 push eax ; ;输入的注册码压栈
0040132B . E8 D0FCFFFF call 00401000 ; ;比较注册码是否正确的call,F7跟进
00401330 . 83C4 10 add esp, 10
00401333 . 83F8 01 cmp eax, 1
00401336 . 6A 40 push 40 ; /;MessageBox函数的样式
00401338 . 68 8C604000 push 0040608C ; |;提示信息的标题内容
0040133D . 75 18 jnz short 00401357 ; |
0040133F . 68 48604000 push 00406048 ; |;要显示的成功提示内容
00401344 . 56 push esi ; |;句柄
00401345 . FF15 A8504000 call dword ptr [<&USER32.MessageBoxA>>; \;显示注册成功的信息
0040134B . 5F pop edi
0040134C . 5E pop esi
0040134D . 33C0 xor eax, eax
0040134F . 5B pop ebx
00401350 . 81C4 00030000 add esp, 300
00401356 . C3 retn
00401357 > 68 30604000 push 00406030 ; |;要显示的错误提示内容
0040135C . 56 push esi ; |;句柄
0040135D . FF15 A8504000 call dword ptr [<&USER32.MessageBoxA>>; \;显示注册错误的信息
00401363 . 5F pop edi ; 0012FAE8
00401364 . 5E pop esi
00401365 . 33C0 xor eax, eax
00401367 . 5B pop ebx
00401368 . 81C4 00030000 add esp, 300
0040136E . C3 retn
计算码表的Call:
004010D0 /$ 56 push esi ; CRC32Cra.00400964
004010D1 |. 33D2 xor edx, edx
004010D3 |. B9 20854000 mov ecx, 00408520 ; ;输入的用户名
004010D8 |> 8BC2 /mov eax, edx ; ;外层循环累加次数传给eax
004010DA |. BE 08000000 |mov esi, 8 ; ;内层循环次数
004010DF |> A8 01 |/test al, 1 ; ;进行与操作,相当于add al,1
004010E1 |. 74 09 ||je short 004010EC ; ;判断ZF标志位来实现跳转
004010E3 |. D1E8 ||shr eax, 1 ; ;右移1位,值保存在eax
004010E5 |. 35 2083B8ED ||xor eax, EDB88320 ; ;与常量EDB88320进行异或
004010EA |. EB 02 ||jmp short 004010EE ; ;跳到比较语句外
004010EC |> D1E8 ||shr eax, 1 ; ;右移1位,值保存在eax
004010EE |> 4E ||dec esi ; ;减1
004010EF |.^ 75 EE |\jnz short 004010DF ; ;不等于0继续执行
004010F1 |. 8901 |mov dword ptr [ecx], eax ; ;值存入码表
004010F3 |. 83C1 04 |add ecx, 4 ; ;码表下标增加1
004010F6 |. 42 |inc edx ; ;循环计数加1
004010F7 |. 81F9 20894000 |cmp ecx, 00408920 ; ;判断是否计算完所有值
004010FD |.^ 7C D9 \jl short 004010D8
004010FF |. 5E pop esi
00401100 \. C3 retn
计算CRC32值的Call:
00401110 /$ 83EC 0C sub esp, 0C
00401113 |. 56 push esi
00401114 |. 57 push edi
00401115 |. E8 B6FFFFFF call 004010D0 ; ;计算码表的Call,F7跟进
0040111A |. 8B7424 18 mov esi, dword ptr [esp+18] ; ;用户名
0040111E |. 83C9 FF or ecx, FFFFFFFF
00401121 |. 8BFE mov edi, esi
00401123 |. 33C0 xor eax, eax
00401125 |. 83CA FF or edx, FFFFFFFF
00401128 |. F2:AE repne scas byte ptr es:[edi] ; ;循环取值
0040112A |. F7D1 not ecx
0040112C |. 49 dec ecx
0040112D |. 85C9 test ecx, ecx
0040112F |. 7E 1F jle short 00401150
00401131 |. 53 push ebx
00401132 |> 8BC2 /mov eax, edx
00401134 |. 33DB |xor ebx, ebx ; ;清空ebx
00401136 |. 8A1E |mov bl, byte ptr [esi] ; ;逐一取字符串
00401138 |. 25 FF000000 |and eax, 0FF ; ;与eax进行与操作
0040113D |. 33C3 |xor eax, ebx ; ;再与eax进行异或操作
0040113F |. C1EA 08 |shr edx, 8 ; ;右移8位
00401142 |. 8B0485 208540>|mov eax, dword ptr [eax*4+408520] ; ;取码表对应的值
00401149 |. 33D0 |xor edx, eax ; ;码表对应的值与右移8位后的值进行异或
0040114B |. 46 |inc esi ; ;计算剩余的字符串
0040114C |. 49 |dec ecx ; ;循环计数
0040114D |.^ 75 E3 \jnz short 00401132
0040114F |. 5B pop ebx
00401150 |> 33C9 xor ecx, ecx
00401152 |. 8D4424 08 lea eax, dword ptr [esp+8]
00401156 |. 894C24 09 mov dword ptr [esp+9], ecx
0040115A |. 6A 10 push 10
0040115C |. F7D2 not edx
0040115E |. 894C24 11 mov dword ptr [esp+11], ecx
00401162 |. 50 push eax
00401163 |. 52 push edx
00401164 |. C64424 14 00 mov byte ptr [esp+14], 0
00401169 |. 884C24 1D mov byte ptr [esp+1D], cl
0040116D |. E8 24380000 call 00404996
00401172 |. 8D7C24 14 lea edi, dword ptr [esp+14]
00401176 |. 83C9 FF or ecx, FFFFFFFF
00401179 |. 33C0 xor eax, eax
0040117B |. 83C4 0C add esp, 0C
0040117E |. 33F6 xor esi, esi
00401180 |. F2:AE repne scas byte ptr es:[edi]
00401182 |. F7D1 not ecx
00401184 |. 49 dec ecx
00401185 |. 74 25 je short 004011AC
00401187 |> 0FBE4C34 08 /movsx ecx, byte ptr [esp+esi+8] ; ;逐一取字符串
0040118C |. 51 |push ecx
0040118D |. E8 4E020000 |call 004013E0
00401192 |. 884434 0C |mov byte ptr [esp+esi+C], al
00401196 |. 83C4 04 |add esp, 4
00401199 |. 8D7C24 08 |lea edi, dword ptr [esp+8] ; ;计算得到的值
0040119D |. 83C9 FF |or ecx, FFFFFFFF
004011A0 |. 33C0 |xor eax, eax
004011A2 |. 46 |inc esi
004011A3 |. F2:AE |repne scas byte ptr es:[edi] ; ;循环取值
004011A5 |. F7D1 |not ecx
004011A7 |. 49 |dec ecx
004011A8 |. 3BF1 |cmp esi, ecx
004011AA |.^ 72 DB \jb short 00401187
004011AC |> 8B4424 1C mov eax, dword ptr [esp+1C]
004011B0 |. 8D5424 08 lea edx, dword ptr [esp+8]
004011B4 |. 52 push edx ; /;注册码
004011B5 |. 50 push eax ; |;eax作为返回用
004011B6 |. FF15 00504000 call dword ptr [<&KERNEL32.lstrcpyA>] ; \;用lstrcpy函数把结果拷贝eax
004011BC |. 5F pop edi
004011BD |. 5E pop esi
004011BE |. 83C4 0C add esp, 0C
004011C1 \. C3 retn
比较是否为正确注册码的Call:
00401000 /$ 81EC 00020000 sub esp, 200
00401006 |. 56 push esi
00401007 |. 57 push edi
00401008 |. B9 3F000000 mov ecx, 3F
0040100D |. 33C0 xor eax, eax
0040100F |. 8D7C24 09 lea edi, dword ptr [esp+9]
00401013 |. C64424 08 00 mov byte ptr [esp+8], 0
00401018 |. F3:AB rep stos dword ptr es:[edi]
0040101A |. 66:AB stos word ptr es:[edi]
0040101C |. AA stos byte ptr es:[edi]
0040101D |. B9 3F000000 mov ecx, 3F
00401022 |. 33C0 xor eax, eax
00401024 |. 8DBC24 090100>lea edi, dword ptr [esp+109]
0040102B |. C68424 080100>mov byte ptr [esp+108], 0
00401033 |. F3:AB rep stos dword ptr es:[edi]
00401035 |. 66:AB stos word ptr es:[edi]
00401037 |. 8B35 00504000 mov esi, dword ptr [<&KERNEL32.lstrc>; kernel32.lstrcpyA
0040103D |. 8D4C24 08 lea ecx, dword ptr [esp+8]
00401041 |. AA stos byte ptr es:[edi]
00401042 |. 8B8424 0C0200>mov eax, dword ptr [esp+20C] ; ;输入的假码
00401049 |. 50 push eax ; /;假码
0040104A |. 51 push ecx ; |;接收变量
0040104B |. FFD6 call esi ; \;拷贝假码到ecx
0040104D |. 8B9424 100200>mov edx, dword ptr [esp+210] ; ;真码
00401054 |. 8D8424 080100>lea eax, dword ptr [esp+108] ; ;取假码的地址
0040105B |. 52 push edx ; /;真码
0040105C |. 50 push eax ; |;假码地址
0040105D |. FFD6 call esi ; \;拷贝真码到eax
0040105F |. 8DBC24 080100>lea edi, dword ptr [esp+108]
00401066 |. 83C9 FF or ecx, FFFFFFFF
00401069 |. 33C0 xor eax, eax
0040106B |. F2:AE repne scas byte ptr es:[edi] ; ;循环取真码的值
0040106D |. F7D1 not ecx
0040106F |. 49 dec ecx
00401070 |. 8D7C24 08 lea edi, dword ptr [esp+8]
00401074 |. 8BD1 mov edx, ecx
00401076 |. 83C9 FF or ecx, FFFFFFFF
00401079 |. F2:AE repne scas byte ptr es:[edi] ; ;循环取假码的值
0040107B |. F7D1 not ecx
0040107D |. 49 dec ecx
0040107E |. 3BCA cmp ecx, edx ; ;比较两个字符串的长度系统
00401080 |. 75 40 jnz short 004010C2
00401082 |. 8D7C24 08 lea edi, dword ptr [esp+8]
00401086 |. 83C9 FF or ecx, FFFFFFFF
00401089 |. 33D2 xor edx, edx
0040108B |. F2:AE repne scas byte ptr es:[edi] ; ;循环取值
0040108D |. F7D1 not ecx
0040108F |. 49 dec ecx
00401090 |. 74 22 je short 004010B4
00401092 |> 8A4414 08 /mov al, byte ptr [esp+edx+8] ; ;取假码的第X位
00401096 |. 8A8C14 080100>|mov cl, byte ptr [esp+edx+108] ; ;取真码的第X位
0040109D |. 3AC1 |cmp al, cl ; ;比较真码与假码的第X位
0040109F |. 75 21 |jnz short 004010C2
004010A1 |. 8D7C24 08 |lea edi, dword ptr [esp+8]
004010A5 |. 83C9 FF |or ecx, FFFFFFFF
004010A8 |. 33C0 |xor eax, eax
004010AA |. 42 |inc edx
004010AB |. F2:AE |repne scas byte ptr es:[edi]
004010AD |. F7D1 |not ecx
004010AF |. 49 |dec ecx
004010B0 |. 3BD1 |cmp edx, ecx ; ;判断是否比较完真码的位数
004010B2 |.^ 72 DE \jb short 00401092
004010B4 |> 5F pop edi
004010B5 |. B8 01000000 mov eax, 1
004010BA |. 5E pop esi
004010BB |. 81C4 00020000 add esp, 200
004010C1 |. C3 retn
004010C2 |> 5F pop edi
004010C3 |. 33C0 xor eax, eax
004010C5 |. 5E pop esi
004010C6 |. 81C4 00020000 add esp, 200
004010CC \. C3 retn
最后跟出一组可用注册码,用户名:WindRand,注册码:E3131671
后面附汇编注册机源码:
.386
.model flat,stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
DLG_MAIN equ 1
IDC_USER_EDIT equ 10
IDC_CODE_EDIT equ 20
IDC_GETCODE_BUTTON equ 30
IDC_GETEXIT_BUTTON equ 40
CRC_VALUE equ 0EDB88320h
;函数声明
GetCRCTable proto
GetCRCCode proto
MainProc proto :DWORD,:DWORD,:DWORD,:DWORD
.data
CRC32Table dd 256 dup(0)
szFormat db '%X',0
.data?
hInst dd ?
szUserName dd ?
szUserCode dd ?
.code
start:
invoke GetModuleHandle,NULL
mov hInst,eax
;调用窗口过程
invoke DialogBoxParam,hInst,DLG_MAIN,NULL,offset MainProc,NULL
invoke ExitProcess,NULL
;窗口过程
MainProc proc hDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_COMMAND
.if wParam==IDC_GETCODE_BUTTON;计算注册码按钮
;获取输入的用户名
invoke GetDlgItemText, hDlg, IDC_USER_EDIT, offset szUserName, 256
invoke GetCRCTable
lea ebx, szUserName
invoke GetCRCCode
;格式化注册码为16进制格式
invoke wsprintf, offset szUserCode,offset szFormat,eax
;把注册码写到注册码框中
invoke SetDlgItemText,hDlg,IDC_CODE_EDIT,offset szUserCode
.elseif wParam==IDC_GETEXIT_BUTTON;退出按钮
invoke EndDialog,hDlg,NULL
.else
ret
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hDlg,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
MainProc endp
;动态生成码表
GetCRCTable proc
mov ecx, 256
@@1:;外层循环,计数为256
lea eax, [ecx-1]
push ecx
mov ecx, 8
@@2:;内存循环,计数为8
shr eax, 1
jnc @@3
xor eax, CRC_VALUE;与常量EDB88320进行异或操作
@@3:
dec ecx
jne @@2
pop ecx
mov [CRC32Table+ecx*4-4], eax
dec ecx
jne @@1
ret
GetCRCTable endp
;计算CRC32值
GetCRCCode proc
mov eax, -1
or ebx, ebx
jz @@1
@@2:
mov dl, [ebx]
or dl, dl
je @@1
xor dl, al
movzx edx, dl
shr eax, 8
xor eax, [CRC32Table+edx*4];与码表进行异或操作
inc ebx
jmp @@2
@@1:
not eax
ret
GetCRCCode endp
end start
资源文件内容:
#include <resource.h>
#define DLG_MAIN 1
#define IDC_USER_EDIT 10
#define IDC_CODE_EDIT 20
#define IDC_GETCODE_BUTTON 30
#define IDC_GETEXIT_BUTTON 40
//主窗口
DLG_MAIN DIALOG DISCARDABLE 0, 0, 273, 90
STYLE DS_FIXEDSYS |DS_SETFONT |DS_MODALFRAME |DS_CENTER |WS_POPUP |WS_CAPTION |WS_VISIBLE |WS_SYSMENU |WS_MINIMIZEBOX
CAPTION "CRC32CrackMe KeyGen by WindRand"
FONT 9, "宋体"
{
LTEXT "用户名:",-1,6,12,51,10
EDITTEXT IDC_USER_EDIT,37,10,230,13
LTEXT "注册码:",-1,6,42,51,10
EDITTEXT IDC_CODE_EDIT,37,40,230,13
PUSHBUTTON "计算",IDC_GETCODE_BUTTON,50,65,90,15
PUSHBUTTON "退出",IDC_GETEXIT_BUTTON,150,65,90,15
}
附一个编译好的KeyGen程序
CRCKeyGen.rar
--------------------------------------------------------------------------------
【经验总结】
好长时间没有写破文了,写的很乱,大家凑合着看一下吧。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年08月21日 16:08:30
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课