系统 : Windows xp

程序 : Crackme#3 - Self Destructed

程序下载地址 :http://pan.baidu.com/s/1kVxwlaZ

要求 : 注册机编写

使用工具 : OD

可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“适合新手的D4ph1_-_Crackme#3的破解”。

利用超级字符串插件看下程序内的文本:

Ultra String Reference
Address Disassembly Text String
mov esi, dword ptr [esp] (initial cpu selection)
push 0040313A kernel32.dll
push \eraser.bat
push \eraser.bat
0040125C push :loop\n\ndel "%s"\n\nif exist "%s" goto loop\n\ndel "%s"
push crackme# by d4ph1
0040128E push debugger found...i think im gonna kill myself!:(
004012A0 push \eraser.bat
push crackme# by d4ph1
0040134B push *======== your target is to create a valid keygenerator.contact : fistiks16@hotmail.com ========*
004014AB push crackme# by d4ph1
004014B0 push 004030E0 great work!hope this is coming from your keygenerator!:)
004014C0 push crackme# by d4ph1
004014C5 push this is not the right serial...
004014D5 push crackme# by d4ph1
004014DA push 004030BB you have to write a serial first...!
004014F3 push crackme# by d4ph1
004014F8 push you have to write a name first...!
push crackme# by d4ph1
0040150D push the name you write is not correct!

好像检索出了什么不得了的内容,双击debugger found...i think im gonna kill myself!:( 查看引用位置:

004011F3  /$   D1314000   push    004031D1                         ; /isdebuggerpresent
004011F8 |. FF35 F0344000 push dword ptr [4034F0] ; |hModule = NULL
004011FE |. E8 8B030000 call <jmp.&kernel32.GetProcAddress> ; \GetProcAddress
|. FFD0 call eax
|. 0BC0 or eax, eax
|. 0C jnz short
|. 8A1D mov bl, byte ptr []
0040120F |. 80FB cmp bl,
|. jnz short
|. C3 retn
|> EB jmp short
|> 6A push ; /hTemplateFile = NULL
|. push ; |Attributes = NORMAL
0040121E |. 6A push ; |Mode = CREATE_ALWAYS
|. 6A push ; |pSecurity = NULL
|. 6A push ; |ShareMode = 0
|. push ; |Access = GENERIC_WRITE
|. push ; |\eraser.bat
0040122E |. E8 call <jmp.&kernel32.CreateFileA> ; \CreateFileA
|. 8BD8 mov ebx, eax
|. 8D35 0A394000 lea esi, dword ptr [40390A]
0040123B |. push ; /BufSize = 104 (260.)
|. push esi ; |PathBuffer => Crackme#.0040390A
|. 6A push ; |hModule = NULL
|. E8 3A030000 call <jmp.&kernel32.GetModuleFileName>; \GetModuleFileNameA
|. push esi ; /pDest => Crackme#.0040390A
|. push esi ; |pSrc => ""
0040124A |. E8 E5020000 call <jmp.&user32.CharToOemA> ; \CharToOemA
0040124F |. 8D3D 0A354000 lea edi, dword ptr [40350A]
|. push ; /\eraser.bat
0040125A |. push esi ; |<%s> => ""
0040125B |. push esi ; |<%s> => ""
0040125C |. push ; |:loop\n\ndel "%s"\n\nif exist "%s" goto loop\n\ndel "%s"
|. push edi ; |s => Crackme#.0040350A
|. E8 C7020000 call <jmp.&user32.wsprintfA> ; \wsprintfA
|. 83C4 add esp,
0040126A |. push edi ; /String
0040126B |. E8 3C030000 call <jmp.&kernel32.lstrlenA> ; \lstrlenA
|. 8D15 0E3A4000 lea edx, dword ptr [403A0E]
|. 6A push ; /pOverlapped = NULL
|. push edx ; |pBytesWritten => Crackme#.00403A0E
|. push eax ; |nBytesToWrite
0040127A |. push edi ; |Buffer
0040127B |. push ebx ; |hFile
0040127C |. E8 call <jmp.&kernel32.WriteFile> ; \WriteFile
|. push ebx ; /hObject
|. E8 DD020000 call <jmp.&kernel32.CloseHandle> ; \CloseHandle
|. 6A push ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
|. push ; |crackme#3 by d4ph1
0040128E |. push ; |debugger found...i think im gonna kill myself!:(
|. 6A push ; |hOwner = NULL
|. E8 B2020000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
0040129A |. 6A push ; /IsShown = 0
0040129C |. 6A push ; |DefDir = NULL
0040129E |. 6A push ; |Parameters = NULL
004012A0 |. push ; |\eraser.bat
004012A5 |. 6A push ; |Operation = NULL
004012A7 |. 6A push ; |hWnd = NULL
004012A9 |. E8 call <jmp.&shell32.ShellExecuteA> ; \ShellExecuteA
004012AE |. 6A push ; /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"

启动批处理开始循环删除之后,退出程序。批处理删除源程序之后,再删除自身。很有想法的一个反调试机制。

再来看看算法部分:

  |.   EC314000   push    004031EC                         ; /123
0040136B |. push ; |wParam = 80
|. 6A 0D push 0D ; |Message = WM_GETTEXT
|. EA030000 push 3EA ; |ControlID = 3EA (1002.)
|. FF75 push dword ptr [ebp+] ; |hWnd
0040137A |. E8 D9010000 call <jmp.&user32.SendDlgItemMessageA>; \SendDlgItemMessageA
0040137F |. A3 6C324000 mov dword ptr [40326C], eax
|. 83F8 cmp eax, ; 长度低于等于4?
|. 0F86 jbe 004014ED ; 是则报错
0040138D |. 83F8 cmp eax, ; 长度高于等于14?
|. 0F83 jnb 004014ED ; 是则报错
|. push ; /lParam = 403270
0040139B |. push ; |wParam = 100
004013A0 |. 6A 0D push 0D ; |Message = WM_GETTEXT
004013A2 |. EB030000 push 3EB ; |ControlID = 3EB (1003.)
004013A7 |. FF75 push dword ptr [ebp+] ; |hWnd
004013AA |. E8 A9010000 call <jmp.&user32.SendDlgItemMessageA>; \SendDlgItemMessageA
004013AF |. 83F8 cmp eax, ; 长度为0则报错
004013B2 |. 0F84 1B010000 je 004014D3
004013B8 |. 33C9 xor ecx, ecx ; 开始初始化
004013BA |. 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 |. dec eax
004013C9 |. push eax
004013CA |> /inc esi
004013CB |. |inc ecx
004013CC |. 0FBE81 F03440>|movsx eax, byte ptr [ecx+4034F0] ; 遍历一个特定字符串
004013D3 |. 0FBE9E EC3140>|movsx ebx, byte ptr [esi+4031EC] ; 遍历用户名字符串
004013DA |. 83F0 |xor eax,
004013DD |. 83C0 |add eax,
004013E0 |. C1E3 |shl ebx,
004013E3 |. 83EB |sub ebx,
004013E6 |. 83F3 |xor ebx,
004013E9 |. 32C3 |xor al, bl
004013EB |. 03C3 |add eax, ebx
004013ED |. E8 5CFDFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存
004013F2 |. |pop eax
004013F3 |. 3BF0 |cmp esi, eax ; 是否已经遍历结束?
004013F5 |. |push eax
004013F6 |. 0A |je short
004013F8 |. 83F9 |cmp ecx, ; 第4次循环的时候,重置ecx为-1
004013FB |. |jnz short
004013FD |. 33C9 |xor ecx, ecx
004013FF |. |dec ecx
|>^ EB C8 \jmp short 004013CA
|> pop eax
|. inc edx
|. C682 >mov byte ptr [edx+], 2D ; 添加连字符-
0040140B |. 33C9 xor ecx, ecx
0040140D |. dec ecx
0040140E |. BB mov ebx,
|. 33C0 xor eax, eax
|> /inc ecx
|. 0FBEB1 F43440>|movsx esi, byte ptr [ecx+4034F4] ; 遍历一个特定字符串
0040141D |. 0FBEBB B73140>|movsx edi, byte ptr [ebx+4031B7] ; 遍历一个特定字符串
|. 2BFE |sub edi, esi
|. 03C7 |add eax, edi
|. 2BC6 |sub eax, esi
0040142A |. C1E0 |shl eax,
0040142D |. 83F9 |cmp ecx, ; 循环两次了?
|.^ E3 \jnz short
|. C1E8 shr eax,
|. 33C9 xor ecx, ecx
|. dec ecx
|> /inc ecx
|. E8 10FDFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存
0040143E |. 8AC4 |mov al, ah
|. 83F9 |cmp ecx, ; 循环两次了?
|.^ F3 \jnz short
|. inc edx
|. C682 >mov byte ptr [edx+], 2D ; 添加连字符-
0040144D |. 33C9 xor ecx, ecx
0040144F |. dec ecx
|. 33FF xor edi, edi
|. 0FBE35 >movsx esi, byte ptr []
|> /inc ecx
0040145A |. 0FBE81 F63440>|movsx eax, byte ptr [ecx+4034F6] ; 遍历一个特定字符串
|. 8B9F |mov ebx, dword ptr [edi+] ; 遍历一个代码区段
|. 33C3 |xor eax, ebx
|. 331D |xor ebx, dword ptr []
0040146F |. 2BD8 |sub ebx, eax
|. 2B1D |sub ebx, dword ptr []
|. 03C3 |add eax, ebx
|. E8 D0FCFFFF |call 0040114E ; 根据eax的值算出一个对应的值,并保存
0040147E |. 83C7 |add edi,
|. 4E |dec esi ; 循环结束?
|.^ D5 \jnz short
|. push ; /String = ""
|. E8 1E010000 call <jmp.&kernel32.lstrlenA> ; \lstrlenA
0040148E |. 8BC8 mov ecx, eax
|. inc ecx
|> /dec ecx ; 密码和序列号是否一致?
|. 0FBE81 >|movsx eax, byte ptr [ecx+]
|. 0FBE99 >|movsx ebx, byte ptr [ecx+]
004014A0 |. 3BC3 |cmp eax, ebx
004014A2 |. 1A |jnz short 004014BE
004014A4 |. 83F9 |cmp ecx,
004014A7 |.^ E8 \jnz short
004014A9 |. 6A push ; /Style = MB_OK|MB_APPLMODAL
004014AB |. push ; |crackme#3 by d4ph1
004014B0 |. E0304000 push 004030E0 ; |great work!hope this is coming from your keygenerator!:)
004014B5 |. 6A push ; |hOwner = NULL
004014B7 |. E8 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004014BC |. EB jmp short 004014E6
004014BE |> 6A push ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004014C0 |. push ; |crackme#3 by d4ph1
004014C5 |. push ; |this is not the right serial...
004014CA |. 6A push ; |hOwner = NULL
004014CC |. E8 7B000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004014D1 |. EB jmp short 004014E6
004014D3 |> 6A push ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004014D5 |. push ; |crackme#3 by d4ph1
004014DA |. BB304000 push 004030BB ; |you have to write a serial first...!
004014DF |. 6A push ; |hOwner = NULL
004014E1 |. E8 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004014E6 |> E8 93FCFFFF call 0040117E
004014EB |. EB 2C jmp short
004014ED |> 0BC0 or eax, eax
004014EF |. jnz short
004014F1 |. 6A push ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004014F3 |. push ; |crackme#3 by d4ph1
004014F8 |. push ; |you have to write a name first...!
004014FD |. 6A push ; |hOwner = NULL
004014FF |. E8 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
|. EB jmp short
|> 6A push ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
|. push ; |crackme#3 by d4ph1
0040150D |. push ; |the name you write is not correct!
|. 6A push ; |hOwner = NULL
|. E8 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
|> EB jmp short
0040151B |> B8 mov eax,
|. C9 leave
|. C2 retn
|> B8 mov eax,
|. C9 leave
0040152A \. C2 retn

中间的子程序:

0040114E  /$  :         push    ax
|. C0E8 shr al,
|. 0F and al, 0F
|. add al,
|. 3C cmp al,
|. 7E jle short 0040115D
0040115B |. add al,
0040115D |> inc edx
0040115E |. mov byte ptr [edx+], al
|. : pop ax
|. C0E0 shl al,
|. C0E8 shr al,
0040116C |. 0F and al, 0F
0040116E |. add al,
|. 3C cmp al,
|. 7E jle short
|. add al,
|> inc edx
|. mov byte ptr [edx+], al
0040117D \. C3 retn

整体算法不困难,就是稍微有点复杂,有点耐心就可以搞定啦。

打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,新增类函数如下:

void CKengen_TemplateDlg::CreateStr(CString &str, DWORD num)
{
BYTE Temp = ; __asm{
push eax mov eax,num
shr al,
and al,0x0F
add al,0x30
cmp al,0x39
jle NotAdd
add al,
NotAdd: mov Temp,al pop eax
} str += (char)Temp; __asm{
push eax mov eax,num
shl al,
shr al,
and al,0x0F
add al,0x30
cmp al,0x39
jle NotAdd2
add al,
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 > && len < ){ //格式控制。
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 = ,j = ;
for ( ; i != str.GetLength() ; i++,j++ ){
DWORD Char = CharArr[j];
DWORD Temp = str.GetAt( i );
DWORD Res = ; Char = ( Char^0x12 ) + 0x34;
Temp = ( ((Temp<<) - 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 == )
j = -;
} Serial += "-";
CreateStr( Serial,0x536 );
CreateStr( Serial,0x505 );
Serial += "-"; for ( i = ; 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"));

运行效果:

一个有趣的CM的更多相关文章

  1. 【小贴士】关于transitionEnd/animate的一个有趣故事

    前言 在很久之前,我们项目有一个动画功能,功能本身很简单,便是典型的右进左出,并且带动画功能 以当时来说,虽然很简单,但是受限于框架本身的难度,就直接使用了CSS3的方式完成了功能 当时主要使用tra ...

  2. 一个有趣的SQL Server 层级汇总数据问题

        看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题.          具体的问题如下:     parent_id emp_id emp_nam ...

  3. 一个有趣的模拟光照的shader

    一个有趣的模拟光照的shader(类似法线贴图) http://www.cnblogs.com/flytrace/p/3395911.html -----  可否用于需UI中需要加灯的模型.

  4. 一个有趣的 SQL 查询(查询7天连续登陆)

    一个有趣的 SQL 查询 一个朋友有这样一个SQL查询需求: 有一个登录表(tmp_test),包含用户ID(uid)和登录时间(login_time).表结构如下: . row ********** ...

  5. 另一个有趣的Captcha 网站

    今天在一个网站注册时又发现了一个有趣的Captcha形式.给你一个翻转的图片,然后让你拽下面的slide bar让它回到正常的位置,很有趣.下面是提供这个Captcha的网站. minteye – s ...

  6. dubbo debug过程中一个有趣的问题

    最近在debug dubbo代码过程中遇到的很有趣的问题 我们都知道dubbo ReferenceBean是消费者的spring bean包装,为了查一个consumer端的问题,在Reference ...

  7. 一个有趣的小例子,带你入门协程模块-asyncio

    一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...

  8. 一个有趣的js隐式转换的问题

    一个有趣的js隐式转换的问题 在chrome的控制台中打印一下表达式 [] + {} //结果为 [object object] 然后调整顺序打印 {} + [] //结果为 0 然后将两个表达式组合 ...

  9. 举一个有趣的例子,让你轻松搞懂JVM内存管理

    目录 前言 例子 源码 输出 图解 深入分析 学以致用 写在最后 前言 在JAVA虚拟机内存管理中,堆.栈.方法区.常量池等概念经常被提到,对理论知识的理解也常常停留在字面意思上,比如说堆内存中存放对 ...

随机推荐

  1. 【Win10 开发】读取PDF文档

    关于用来读取PDF文档的内容的API,其实在Win8.1的时候就有,不过没关系,既咱们讨论的是10的UAP,连同8.1的内容也包括进去,所以老周无数次强调:把以前的内容学好了,就可以在不学习任何新知识 ...

  2. 【原创】开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  3. ASP.NET MVC之文件上传【二】(九)

    前言 上一节我们讲了简单的上传以及需要注意的地方,查相关资料时,感觉上传里面涉及到的内容还是比较多,于是就将上传这一块分为几节来处理,同时后续也会讲到关于做上传时遗漏的C#应该注意的地方,及时进行查漏 ...

  4. TextView+Fragment实现底部导航栏

    前言:项目第二版刚上线没多久,产品又对需求进行了大改动,以前用的是左滑菜单,现在又要换成底部导航栏,于是今天又苦逼加班了.花了几个小时实现了一个底部导航栏的demo,然后总结一下.写一篇博客.供自己以 ...

  5. 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法

    需要下载Genymotion-ARM-Translation_v1.1.zip  ARM插件包 用于安装ARM架构的程序,将下载好的zip包用鼠标拖到虚拟机窗口中,出现确认对跨框点OK就行.然后重启你 ...

  6. 使用maven来管理java项目

    初学maven,简单总结一下学习心得,若有不对的地方,欢迎各位大神给我指正~ 总结分为6个部分 maven概述 maven安装 maven项目结构和创建方法 maven配置文件settings.xml ...

  7. iOS 保持界面流畅的技巧 (转载)

    这篇文章会非常详细的分析 iOS 界面构建中的各种性能问题以及对应的解决思路,同时给出一个开源的微博列表实现,通过实际的代码展示如何构建流畅的交互. Index 演示项目 屏幕显示图像的原理 卡顿产生 ...

  8. struts2学习笔记--使用Validator校验数据

    我们在进行一些操作是需要对用户的输入数据进行验证,比如网站的注册,需要对各个数据项进行数据校验,Struts2提供了一些默认的校验器,比如数字的检测,邮箱的检测,字符串长度的检测等等. 常用的Vali ...

  9. Front End Developer Questions 前端开发人员问题(二)CSS 后续

    问题来源:http://markyun.github.io/2015/Front-end-Developer-Questions/ 31.视差滚动效果,如何给每页做不同的动画?(回到顶部,向下滑动要再 ...

  10. (十三)WebGIS中工具栏的设计之命令模式

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 从这一章节开始我们将正式进入WebGIS的工具栏中相关功能的 ...