一个有趣的CM
2016-08-04 16:30
211 查看
系统 : Windows xp
程序 : Crackme#3 - Self Destructed
程序下载地址 :http://pan.baidu.com/s/1kVxwlaZ
要求 : 注册机编写
使用工具 : OD
可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“适合新手的D4ph1_-_Crackme#3的破解”。
利用超级字符串插件看下程序内的文本:
好像检索出了什么不得了的内容,双击debugger found...i think im gonna kill myself!:( 查看引用位置:
程序启动时利用WINAPI 查看是否被调试,如果被调试则创建批处理文件:
启动批处理开始循环删除之后,退出程序。批处理删除源程序之后,再删除自身。很有想法的一个反调试机制。
再来看看算法部分:
中间的子程序:
整体算法不困难,就是稍微有点复杂,有点耐心就可以搞定啦。
打开/article/11870525.html中搭建的框架,新增类函数如下:
再将OnBtnDecrypt函数编辑如下:
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("CRACKME_Keygen"));
运行效果:
程序 : Crackme#3 - Self Destructed
程序下载地址 :http://pan.baidu.com/s/1kVxwlaZ
要求 : 注册机编写
使用工具 : OD
可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“适合新手的D4ph1_-_Crackme#3的破解”。
利用超级字符串插件看下程序内的文本:
Ultra String Reference Address Disassembly Text String 00401000 mov esi, dword ptr [esp] (initial cpu selection) 00401068 push 0040313A kernel32.dll 00401229 push 00403147 \eraser.bat 00401255 push 00403147 \eraser.bat 0040125C push 00403153 :loop\n\ndel "%s"\n\nif exist "%s" goto loop\n\ndel "%s" 00401289 push 00403000 crackme#3 by d4ph1 0040128E push 00403186 debugger found...i think im gonna kill myself!:( 004012A0 push 00403147 \eraser.bat 00401346 push 00403000 crackme#3 by d4ph1 0040134B push 00403013 *======== your target is to create a valid keygenerator.contact : fistiks16@hotmail.com ========* 004014AB push 00403000 crackme#3 by d4ph1 004014B0 push 004030E0 great work!hope this is coming from your keygenerator!:) 004014C0 push 00403000 crackme#3 by d4ph1 004014C5 push 00403119 this is not the right serial... 004014D5 push 00403000 crackme#3 by d4ph1 004014DA push 004030BB you have to write a serial first...! 004014F3 push 00403000 crackme#3 by d4ph1 004014F8 push 00403098 you have to write a name first...! 00401508 push 00403000 crackme#3 by d4ph1 0040150D push 00403075 the name you write is not correct!
好像检索出了什么不得了的内容,双击debugger found...i think im gonna kill myself!:( 查看引用位置:
004011F3 /$ 68 D1314000 push 004031D1 ; /isdebuggerpresent 004011F8 |. FF35 F0344000 push dword ptr [4034F0] ; |hModule = NULL 004011FE |. E8 8B030000 call <jmp.&kernel32.GetProcAddress> ; \GetProcAddress 00401203 |. FFD0 call eax 00401205 |. 0BC0 or eax, eax 00401207 |. 75 0C jnz short 00401215 00401209 |. 8A1D 07124000 mov bl, byte ptr [401207] 0040120F |. 80FB 75 cmp bl, 75 00401212 |. 75 03 jnz short 00401217 00401214 |. C3 retn 00401215 |> EB 00 jmp short 00401217 00401217 |> 6A 00 push 0 ; /hTemplateFile = NULL 00401219 |. 68 80000000 push 80 ; |Attributes = NORMAL 0040121E |. 6A 02 push 2 ; |Mode = CREATE_ALWAYS 00401220 |. 6A 00 push 0 ; |pSecurity = NULL 00401222 |. 6A 00 push 0 ; |ShareMode = 0 00401224 |. 68 00000040 push 40000000 ; |Access = GENERIC_WRITE 00401229 |. 68 47314000 push 00403147 ; |\eraser.bat 0040122E |. E8 37030000 call <jmp.&kernel32.CreateFileA> ; \CreateFileA 00401233 |. 8BD8 mov ebx, eax 00401235 |. 8D35 0A394000 lea esi, dword ptr [40390A] 0040123B |. 68 04010000 push 104 ; /BufSize = 104 (260.) 00401240 |. 56 push esi ; |PathBuffer => Crackme#.0040390A 00401241 |. 6A 00 push 0 ; |hModule = NULL 00401243 |. E8 3A030000 call <jmp.&kernel32.GetModuleFileName>; \GetModuleFileNameA 00401248 |. 56 push esi ; /pDest => Crackme#.0040390A 00401249 |. 56 push esi ; |pSrc => "" 0040124A |. E8 E5020000 call <jmp.&user32.CharToOemA> ; \CharToOemA 0040124F |. 8D3D 0A354000 lea edi, dword ptr [40350A] 00401255 |. 68 47314000 push 00403147 ; /\eraser.bat 0040125A |. 56 push esi ; |<%s> => "" 0040125B |. 56 push esi ; |<%s> => "" 0040125C |. 68 53314000 push 00403153 ; |:loop\n\ndel "%s"\n\nif exist "%s" goto loop\n\ndel "%s" 00401261 |. 57 push edi ; |s => Crackme#.0040350A 00401262 |. E8 C7020000 call <jmp.&user32.wsprintfA> ; \wsprintfA 00401267 |. 83C4 14 add esp, 14 0040126A |. 57 push edi ; /String 0040126B |. E8 3C030000 call <jmp.&kernel32.lstrlenA> ; \lstrlenA 00401270 |. 8D15 0E3A4000 lea edx, dword ptr [403A0E] 00401276 |. 6A 00 push 0 ; /pOverlapped = NULL 00401278 |. 52 push edx ; |pBytesWritten => Crackme#.00403A0E 00401279 |. 50 push eax ; |nBytesToWrite 0040127A |. 57 push edi ; |Buffer 0040127B |. 53 push ebx ; |hFile 0040127C |. E8 25030000 call <jmp.&kernel32.WriteFile> ; \WriteFile 00401281 |. 53 push ebx ; /hObject 00401282 |. E8 DD020000 call <jmp.&kernel32.CloseHandle> ; \CloseHandle 00401287 |. 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL 00401289 |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 0040128E |. 68 86314000 push 00403186 ; |debugger found...i think im gonna kill myself!:( 00401293 |. 6A 00 push 0 ; |hOwner = NULL 00401295 |. E8 B2020000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 0040129A |. 6A 00 push 0 ; /IsShown = 0 0040129C |. 6A 00 push 0 ; |DefDir = NULL 0040129E |. 6A 00 push 0 ; |Parameters = NULL 004012A0 |. 68 47314000 push 00403147 ; |\eraser.bat 004012A5 |. 6A 00 push 0 ; |Operation = NULL 004012A7 |. 6A 00 push 0 ; |hWnd = NULL 004012A9 |. E8 04030000 call <jmp.&shell32.ShellExecuteA> ; \ShellExecuteA 004012AE |. 6A 00 push 0 ; /ExitCode = 0 004012B0 \. E8 BB020000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
程序启动时利用WINAPI 查看是否被调试,如果被调试则创建批处理文件:
:LOOP DEL "D:\IT\逆向工程\CrackMe\crackme3selfdestructed\Crackme#3 - Self Destructed.exe" IF EXIST "D:\IT\逆向工程\CrackMe\crackme3selfdestructed\Crackme#3 - Self Destructed.exe" GOTO LOOP DEL "\ERASER.BAT"
启动批处理开始循环删除之后,退出程序。批处理删除源程序之后,再删除自身。很有想法的一个反调试机制。
再来看看算法部分:
00401366 |. 68 EC314000 push 004031EC ; /123 0040136B |. 68 80000000 push 80 ; |wParam = 80 00401370 |. 6A 0D push 0D ; |Message = WM_GETTEXT 00401372 |. 68 EA030000 push 3EA ; |ControlID = 3EA (1002.) 00401377 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 0040137A |. E8 D9010000 call <jmp.&user32.SendDlgItemMessageA>; \SendDlgItemMessageA 0040137F |. A3 6C324000 mov dword ptr [40326C], eax 00401384 |. 83F8 04 cmp eax, 4 ; 长度低于等于4? 00401387 |. 0F86 60010000 jbe 004014ED ; 是则报错 0040138D |. 83F8 14 cmp eax, 14 ; 长度高于等于14? 00401390 |. 0F83 57010000 jnb 004014ED ; 是则报错 00401396 |. 68 70324000 push 00403270 ; /lParam = 403270 0040139B |. 68 00010000 push 100 ; |wParam = 100 004013A0 |. 6A 0D push 0D ; |Message = WM_GETTEXT 004013A2 |. 68 EB030000 push 3EB ; |ControlID = 3EB (1003.) 004013A7 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 004013AA |. E8 A9010000 call <jmp.&user32.SendDlgItemMessageA>; \SendDlgItemMessageA 004013AF |. 83F8 00 cmp eax, 0 ; 长度为0则报错 004013B2 |. 0F84 1B010000 je 004014D3 004013B8 |. 33C9 xor ecx, ecx ; 开始初始化 004013BA |. 49 dec ecx 004013BB |. 33D2 xor edx, edx 004013BD |. 4A dec edx 004013BE |. 33F6 xor esi, esi 004013C0 |. 4E dec esi 004013C1 |. 33C0 xor eax, eax 004013C3 |. A1 6C324000 mov eax, dword ptr [40326C] ; 载入用户名长度 004013C8 |. 48 dec eax 004013C9 |. 50 push eax 004013CA |> 46 /inc esi 004013CB |. 41 |inc ecx 004013CC |. 0FBE81 F03440>|movsx eax, byte ptr [ecx+4034F0] ; 遍历一个特定字符串 004013D3 |. 0FBE9E EC3140>|movsx ebx, byte ptr [esi+4031EC] ; 遍历用户名字符串 004013DA |. 83F0 12 |xor eax, 12 004013DD |. 83C0 34 |add eax, 34 004013E0 |. C1E3 03 |shl ebx, 3 004013E3 |. 83EB 20 |sub ebx, 20 004013E6 |. 83F3 66 |xor ebx, 66 004013E9 |. 32C3 |xor al, bl 004013EB |. 03C3 |add eax, ebx 004013ED |. E8 5CFDFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存 004013F2 |. 58 |pop eax 004013F3 |. 3BF0 |cmp esi, eax ; 是否已经遍历结束? 004013F5 |. 50 |push eax 004013F6 |. 74 0A |je short 00401402 004013F8 |. 83F9 03 |cmp ecx, 3 ; 第4次循环的时候,重置ecx为-1 004013FB |. 75 03 |jnz short 00401400 004013FD |. 33C9 |xor ecx, ecx 004013FF |. 49 |dec ecx 00401400 |>^ EB C8 \jmp short 004013CA 00401402 |> 58 pop eax 00401403 |. 42 inc edx 00401404 |. C682 70334000>mov byte ptr [edx+403370], 2D ; 添加连字符- 0040140B |. 33C9 xor ecx, ecx 0040140D |. 49 dec ecx 0040140E |. BB 13000000 mov ebx, 13 00401413 |. 33C0 xor eax, eax 00401415 |> 41 /inc ecx 00401416 |. 0FBEB1 F43440>|movsx esi, byte ptr [ecx+4034F4] ; 遍历一个特定字符串 0040141D |. 0FBEBB B73140>|movsx edi, byte ptr [ebx+4031B7] ; 遍历一个特定字符串 00401424 |. 2BFE |sub edi, esi 00401426 |. 03C7 |add eax, edi 00401428 |. 2BC6 |sub eax, esi 0040142A |. C1E0 04 |shl eax, 4 0040142D |. 83F9 01 |cmp ecx, 1 ; 循环两次了? 00401430 |.^ 75 E3 \jnz short 00401415 00401432 |. C1E8 04 shr eax, 4 00401435 |. 33C9 xor ecx, ecx 00401437 |. 49 dec ecx 00401438 |> 41 /inc ecx 00401439 |. E8 10FDFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存 0040143E |. 8AC4 |mov al, ah 00401440 |. 83F9 01 |cmp ecx, 1 ; 循环两次了? 00401443 |.^ 75 F3 \jnz short 00401438 00401445 |. 42 inc edx 00401446 |. C682 70334000>mov byte ptr [edx+403370], 2D ; 添加连字符- 0040144D |. 33C9 xor ecx, ecx 0040144F |. 49 dec ecx 00401450 |. 33FF xor edi, edi 00401452 |. 0FBE35 063540>movsx esi, byte ptr [403506] 00401459 |> 41 /inc ecx 0040145A |. 0FBE81 F63440>|movsx eax, byte ptr [ecx+4034F6] ; 遍历一个特定字符串 00401461 |. 8B9F 07124000 |mov ebx, dword ptr [edi+401207] ; 遍历一个代码区段 00401467 |. 33C3 |xor eax, ebx 00401469 |. 331D 06354000 |xor ebx, dword ptr [403506] 0040146F |. 2BD8 |sub ebx, eax 00401471 |. 2B1D 06354000 |sub ebx, dword ptr [403506] 00401477 |. 03C3 |add eax, ebx 00401479 |. E8 D0FCFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存 0040147E |. 83C7 04 |add edi, 4 00401481 |. 4E |dec esi ; 循环结束? 00401482 |.^ 75 D5 \jnz short 00401459 00401484 |. 68 70334000 push 00403370 ; /String = "" 00401489 |. E8 1E010000 call <jmp.&kernel32.lstrlenA> ; \lstrlenA 0040148E |. 8BC8 mov ecx, eax 00401490 |. 41 inc ecx 00401491 |> 49 /dec ecx ; 密码和序列号是否一致? 00401492 |. 0FBE81 703240>|movsx eax, byte ptr [ecx+403270] 00401499 |. 0FBE99 703340>|movsx ebx, byte ptr [ecx+403370] 004014A0 |. 3BC3 |cmp eax, ebx 004014A2 |. 75 1A |jnz short 004014BE 004014A4 |. 83F9 00 |cmp ecx, 0 004014A7 |.^ 75 E8 \jnz short 00401491 004014A9 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 004014AB |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 004014B0 |. 68 E0304000 push 004030E0 ; |great work!hope this is coming from your keygenerator!:) 004014B5 |. 6A 00 push 0 ; |hOwner = NULL 004014B7 |. E8 90000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 004014BC |. EB 28 jmp short 004014E6 004014BE |> 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL 004014C0 |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 004014C5 |. 68 19314000 push 00403119 ; |this is not the right serial... 004014CA |. 6A 00 push 0 ; |hOwner = NULL 004014CC |. E8 7B000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 004014D1 |. EB 13 jmp short 004014E6 004014D3 |> 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL 004014D5 |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 004014DA |. 68 BB304000 push 004030BB ; |you have to write a serial first...! 004014DF |. 6A 00 push 0 ; |hOwner = NULL 004014E1 |. E8 66000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 004014E6 |> E8 93FCFFFF call 0040117E 004014EB |. EB 2C jmp short 00401519 004014ED |> 0BC0 or eax, eax 004014EF |. 75 15 jnz short 00401506 004014F1 |. 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL 004014F3 |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 004014F8 |. 68 98304000 push 00403098 ; |you have to write a name first...! 004014FD |. 6A 00 push 0 ; |hOwner = NULL 004014FF |. E8 48000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 00401504 |. EB 13 jmp short 00401519 00401506 |> 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL 00401508 |. 68 00304000 push 00403000 ; |crackme#3 by d4ph1 0040150D |. 68 75304000 push 00403075 ; |the name you write is not correct! 00401512 |. 6A 00 push 0 ; |hOwner = NULL 00401514 |. E8 33000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA 00401519 |> EB 09 jmp short 00401524 0040151B |> B8 00000000 mov eax, 0 00401520 |. C9 leave 00401521 |. C2 1000 retn 10 00401524 |> B8 01000000 mov eax, 1 00401529 |. C9 leave 0040152A \. C2 1000 retn 10
中间的子程序:
0040114E /$ 66:50 push ax 00401150 |. C0E8 04 shr al, 4 00401153 |. 24 0F and al, 0F 00401155 |. 04 30 add al, 30 00401157 |. 3C 39 cmp al, 39 00401159 |. 7E 02 jle short 0040115D 0040115B |. 04 07 add al, 7 0040115D |> 42 inc edx 0040115E |. 8882 70334000 mov byte ptr [edx+403370], al 00401164 |. 66:58 pop ax 00401166 |. C0E0 04 shl al, 4 00401169 |. C0E8 04 shr al, 4 0040116C |. 24 0F and al, 0F 0040116E |. 04 30 add al, 30 00401170 |. 3C 39 cmp al, 39 00401172 |. 7E 02 jle short 00401176 00401174 |. 04 07 add al, 7 00401176 |> 42 inc edx 00401177 |. 8882 70334000 mov byte ptr [edx+403370], al 0040117D \. C3 retn
整体算法不困难,就是稍微有点复杂,有点耐心就可以搞定啦。
打开/article/11870525.html中搭建的框架,新增类函数如下:
void CKengen_TemplateDlg::CreateStr(CString &str, DWORD num) { BYTE Temp = 0; __asm{ push eax mov eax,num shr al,4 and al,0x0F add al,0x30 cmp al,0x39 jle NotAdd add al,7 NotAdd: mov Temp,al pop eax } str += (char)Temp; __asm{ push eax mov eax,num shl al,4 shr al,4 and al,0x0F add al,0x30 cmp al,0x39 jle NotAdd2 add al,7 NotAdd2:mov Temp,al pop eax } str += (char)Temp; return ; }
再将OnBtnDecrypt函数编辑如下:
void CKengen_TemplateDlg::OnBtnDecrypt() { // TODO: Add your control notification handler code here CString str; GetDlgItemText( IDC_EDIT_NAME,str ); //获取用户名字串基本信息。 int len = str.GetLength(); if ( len > 4 && len < 14 ){ //格式控制。 char CharArr[] = { 0x58,0x50,0x80,0x7C,0x05,0x01 }; char ComputerName[] = { 0x32,0x30,0x31,0x36,0x30,0x34,0x30,0x35,0x2D,0x32,0x30,0x30,0x37,0x00 }; DWORD CodeSegment[] = { 0x1D8A0C75, 0x00401207, 0x7575FB80, 0x00EBC303, 0x8068006A, 0x6A000000, 0x6A006A02, 0x00006800, 0x47684000, 0xE8004031, 0x00000337, 0x358DD88B, 0x0040390A, 0x00010468, 0x006A5600, 0x00033AE8, }; CString Serial = ""; int i = 0,j = 0 ; for ( ; i != str.GetLength() ; i++,j++ ){ DWORD Char = CharArr[j]; DWORD Temp = str.GetAt( i ); DWORD Res = 0; Char = ( Char^0x12 ) + 0x34; Temp = ( ((Temp<<3) - 0x20) ^ 0x66 ); __asm{ push eax push ebx mov eax,Char mov ebx,Temp xor al,bl add eax,ebx mov Res,eax pop eax pop ebx } CreateStr( Serial,Res ); if ( j == 3 ) j = -1; } Serial += "-"; CreateStr( Serial,0x536 ); CreateStr( Serial,0x505 ); Serial += "-"; for ( i = 0 ; i != 0x0D ; i++ ){ DWORD EAX = ( ComputerName[i] ^ CodeSegment[i] ); DWORD EBX = ( CodeSegment[i] ^ 0x0D ) - EAX - 0x0D; DWORD Res = EAX + EBX; CreateStr( Serial,Res ); } SetDlgItemText( IDC_EDIT_PASSWORD,Serial ); } else MessageBox( "用户名格式错误!" ); }
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("CRACKME_Keygen"));
运行效果:
相关文章推荐
- 今天发现一个有趣的东西Havok,喜欢FPS游戏的朋友对这单词应该有所耳闻吧
- 想到一个有趣的功能
- 在telnet 里发现了一个很有趣的网站!
- 一个面向对象有趣的问题
- windows 98 设置 TEMP 环境变量时的一个有趣现象
- 关于javascript程序内存占用的一个有趣的实验
- 一个有趣的查找--搜索最大值所在的ID号
- 一个有趣的查找--搜索最大值所在的ID号 (轉自:http://blog.csdn.net/dhlhh)
- 发现一个专么收集Google图标的有趣站点
- 很有趣的一个小游戏--打企鹅
- 关于DropDownList的一个有趣的Bug~
- 免费发布一个简单而有趣的计算工具
- 看好多论坛的签名很有趣,自己也搞了一个,赫赫
- C++标准库的一个有趣的小bug
- 一个很有趣的话题
- JDK中的一个有趣的变量命名
- 一个有趣的GDI图形测试程序
- 发现一个有趣的网站-www.breakthechain.org
- 一个有趣的游戏
- 一个c语言构造函数调用的问题(有趣)