系统 : Windows xp

程序 : crackme

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

要求 : 注册机编写

使用工具 : IDA Pro & OD

可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“简单分析crackme算法之一”。

运行程序,在Help-》Register菜单项中注册,输入测试用户名密码。程序提示错误,错误字串为:“No luck there, mate!”。打开IDA载入程序,通过字串表定位错误字串,并通过交叉参考在关键算法处下断:

   > \6A          push                                    ; /lParam = NULL
0040120B . push ; |DlgProc = CRACKME.00401253
. FF75 push dword ptr [ebp+] ; |hOwner
. push ; |pTemplate = "DLG_REGIS"
. FF35 CA204000 push dword ptr [4020CA] ; |hInst = 00400000
0040121E . E8 7D020000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
. 83F8 cmp eax,
.^ BE je short 004011E6
. 8E214000 push 0040218E ; 用户名入栈
0040122D . E8 4C010000 call 0040137E ; 根据用户名进行一些操作得出一个值
. push eax
. 7E214000 push 0040217E ; 序列号入栈
. E8 9B010000 call 004013D8 ; 根据序列号进行一些操作得出一个值
0040123D . 83C4 add esp, ; 平衡堆栈
. pop eax
. 3BC3 cmp eax, ebx ; F(用户名) == F(序列号)?
. je short 0040124C

40137E处汇编代码:

0040137E  /$  8B7424      mov     esi, dword ptr [esp+]           ;  取用户名
|. push esi
|> 8A06 /mov al, byte ptr [esi]
|. 84C0 |test al, al ; 如果迭代结束
|. |je short 0040139C ; 跳出循环
|. 3C |cmp al, ; 字符小于0x41,则提示错误
0040138B |. 1F |jb short 004013AC
0040138D |. 3C 5A |cmp al, 5A ; 如果字符大于等于5A,
0040138F |. |jnb short ; 则转化字符为大写
|. |inc esi ; 循环变量自增
|.^ EB EF |jmp short
|> E8 |call 004013D2
|. |inc esi ; 循环变量自增
0040139A |.^ EB E7 \jmp short
0040139C |> 5E pop esi ; 取用户名
0040139D |. E8 call 004013C2
004013A2 |. 81F7 xor edi,
004013A8 |. 8BC7 mov eax, edi ; 异或结果保存在eax里
004013AA |. EB jmp short 004013C1
004013AC |> 5E pop esi
004013AD |. 6A push ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF |. push ; |Title = "No luck!"
004013B4 |. push ; |Text = "No luck there, mate!"
004013B9 |. FF75 push dword ptr [ebp+] ; |hOwner
004013BC |. E8 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004013C1 \> C3 retn
004013C2 /$ 33FF xor edi, edi
004013C4 |. 33DB xor ebx, ebx
004013C6 |> 8A1E /mov bl, byte ptr [esi]
004013C8 |. 84DB |test bl, bl ; 如果迭代结束
004013CA |. |je short 004013D1 ; 跳出循环
004013CC |. 03FB |add edi, ebx ; 累加字符值
004013CE |. |inc esi ; 循环变量自增
004013CF |.^ EB F5 \jmp short 004013C6
004013D1 \> C3 retn ; 结果保存在edi
004013D2 /$ 2C sub al,
004013D4 |. mov byte ptr [esi], al
004013D6 \. C3 retn

4013D8处汇编代码:

004013D8  /$  33C0          xor     eax, eax
004013DA |. 33FF xor edi, edi
004013DC |. 33DB xor ebx, ebx
004013DE |. 8B7424 mov esi, dword ptr [esp+] ; 取序列号
004013E2 |> B0 0A /mov al, 0A
004013E4 |. 8A1E |mov bl, byte ptr [esi]
004013E6 |. 84DB |test bl, bl ; 如果迭代结束
004013E8 |. 0B |je short 004013F5 ; 则跳出循环
004013EA |. 80EB |sub bl, ; 将字符转化为它对应的数字
004013ED |. 0FAFF8 |imul edi, eax
004013F0 |. 03FB |add edi, ebx
004013F2 |. |inc esi ; 循环变量自增
004013F3 |.^ EB ED \jmp short 004013E2
004013F5 |> 81F7 xor edi, ; 结果与0x1234异或
004013FB |. 8BDF mov ebx, edi ; 存入ebx
004013FD \. C3 retn

以上就是关键处代码,通过观察不难发现,该程序采用的是非明码比较(F(用户名)=F(序列号))。这样的程序我们用高级语言写出F(用户名),再算出F(序列号)的逆算法即可。

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

void CKengen_TemplateDlg::OnBtnDecrypt()
{
// TODO: Add your control notification handler code here
CString str;
GetDlgItemText( IDC_EDIT_NAME,str ); //获取用户名字串基本信息。
int len = str.GetLength();
bool StrIsOk = true; for ( int i = ; i != len ; i++ ){
if ( str[i] < 0x41 ){
StrIsOk = false;
break;
}
} if ( StrIsOk ){ //格式控制。
str.MakeUpper(); //转化为大写。 unsigned int sum = ;
int i;
for ( i = ; i != len ; i++ )
sum += str[i]; sum ^= 0x5678; /*
//模拟F(序列号)
CString Serial = "1234";
unsigned int res = 0,num = 0;
int al = 0xA;
for ( i = 0 ; i != len ; i++ ){
num = Serial[i] - 0x30;
res *= al;
res += num;
} res ^= 0x1234;
*/ //写出F(序列号)的逆算法
/*
一开始想的是进行异或操作后,逆向整个for循环,类似于从最后一个元素Serial[len]反推,
res-=num;res/=al;这样,但发现要求的就是num的值,感觉该函数根本不可逆。
想来想去只好翻书看看有没有求解方法,发现程序与《解密与解密》P107处的Serial程序算法居然一样。
原来F(序列号)中的for循环只是将字串转化为了它对应的十进制数!最后做了一个异或而已。
也就是说,将F(用户名)的结果与0x1234进行异或,得出的就是本来的序列号!
通过这次破解,我知道了逆向不一定要微观上一步步反推,还可以从宏观上判断函数到底做了什么。
*/ str.Format( "%d",( sum ^ 0x1234 ) );
SetDlgItemText( IDC_EDIT_PASSWORD,str );
}
else
MessageBox( "用户名格式错误!" );
}

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("CRACKME_Keygen"));

运行效果:

-------------------------------------------------------------------------------------------------------------------

后记:

  在测试注册机时发现了一个问题,当输入的字串长度过长,注册机算出的序列号是错误的。反复确认算法无误之后,怀疑是CRACKME中的字串有“猫腻”。这里,对GetDlgItemText下断点:

004012B5  |.  6A 0B         |push    0B                              ; /Count = B (11.)
004012B7 |. 8E214000 |push 0040218E ; |Buffer = CRACKME.0040218E
004012BC |. E8030000 |push 3E8 ; |ControlID = 3E8 (1000.)
004012C1 |. FF75 |push dword ptr [ebp+] ; |hWnd
004012C4 |. E8 |call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA

对比GetDlgItemText的定义:

int GetDlgItemText( HWND hDlg , int nID, LPTSTR lpStr, int nMaxCount) const;

nID 指定了要获取其标题的控件的整数标识符。 lpStr 指向要接收控件的标题或文本的缓冲区。 nMaxCount 指定了要拷贝到lpStr的字符串的最大长度(以字节为单位)。如果字符串比nMaxCount要长,它将被截断。 rString 对一个CString对象的引用。

nMaxCount 在程序中被设为11,实际保存的字符也就是10个。怪不得过长的用户名算出的序列号是错误的。这里,我们将OnBtnDecrypt函数的if ( StrIsOk )判断语句做个改动,在开始处增加一行代码:str = str.Left( 10 );就可以解决问题。

破解 crackme(“不可逆“函数)的更多相关文章

  1. 破解 CrackMe#1 [UBC] by bRaINbuSY

    系统 : Windows xp 程序 : CrackMe#1 程序下载地址 :http://pan.baidu.com/s/1nuagj6h 要求 : 编写注册机 使用工具 :IDA & OD ...

  2. 软件破解入门(暴力破解CrackMe)

    ---恢复内容开始--- 所谓暴力破解,就是通过修改汇编代码进而控制程序的运行流程,达到不需注册码也能正常使用软件的目的.相对于解出算法进而编写注册机,暴破的技术含量是比较低的.但也正是因为一本05年 ...

  3. 破解 crackme(完全拆解警告窗口)

    系统 : Windows xp 程序 : crackme 程序下载地址 :http://pan.baidu.com/s/1kUrbcAr 要求 : 注册机编写 & 去除Nag窗口 使用工具 : ...

  4. obdg反汇编破解crackme

    obdg是一个反汇编软件 直接将要反汇编的exe文件拖入或者file->open打开文件,等待一段时间就会显示出来 界面中分别为汇编代码(程序内存内容),寄存器内容,数据内存内容,栈内容 代码界 ...

  5. 如何通过Python暴力破解网站登陆密码

    首先申明,该文章只可以用于交流学习,不可以用于其他用途,否则后果自负. 现在国家对网络安全的管理,越来越严,但是还是有一些不法网站逍遥法外,受限于国内的人力.物力,无法对这些网站进行取缔. 今天演示的 ...

  6. 分享总结:更好地CodeReview

            代码质量分享    2016_06_24_舒琴_代码质量.key    For 代码提交人     基本原则 Review时机: 对于普通bugfix或优化,CodeReview最迟要 ...

  7. 逆向project实战--Acid burn

    0x00 序言 这是第二次破解 crackme 小程序,感觉明显比第一次熟练.破解过程非常顺利,差点儿是分分钟就能够找到正确的 serial,可是我们的目标是破解计算过程.以下将具体介绍. 0x01 ...

  8. 【转】PHP代码审计

    PHP代码审计 目录 1. 概述3 2. 输入验证和输出显示3 2.1 命令注入4 2.2 跨站脚本4 2.3 文件包含5 2.4 代码注入5 2.5 SQL注入6 2.6 XPath注入6 2.7 ...

  9. CodeReview实践与总结

    CodeReview 是大型软件工程中公认的必不可少的保证工程质量的重要手段之一.但凡正规软件作战军团都是非常重视 CodeReview 的作用和意义的.那么,如何做好 CodeReview 呢?这里 ...

随机推荐

  1. ZZC语言代码风格

    程序员之路--关于代码风格 优秀的代码风格如同一身得体的打扮,能够给人以良好的印象.初学程序设计,首先必须建立良好的编程习惯,这其中就包括代码风格.本文就代码风格中的几个重点问题进行了讨论,并在文后给 ...

  2. solr 4.3.0 配置

    scheme.xml <?xml version="1.0" encoding="UTF-8" ?> <schema name="t ...

  3. DWR框架简单应用

    各种Dwr简介不需要多说,知道是实现局部刷新就差不多了,至于实现原理,慢慢参透吧,一下说明怎么使用DWR 首先建一个web工程,然后添加如下jar包:

  4. Windows内核对象

    1. 内核对象 Windows中每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核进行访问,应用程序不能在内存中定位这些数据结构并直接更改其内容.这个内存块是一个数据结构,其成员 ...

  5. POJ 1050 To the Max 暴力,基础知识 难度:0

    http://poj.org/problem?id=1050 设sum[i][j]为从(1,1)到(i,j)的矩形中所有数字之和 首先处理出sum[i][j],此时左上角为(x1,y1),右下角为(x ...

  6. Operating System Concepts 项目:生产者-消费者问题 线程

    一. 实验目的 实现一个c程序,该程序能模拟解决有限缓冲问题,其中消费者和生产者产生和消耗随机数 二.实验内容 缓冲区 元数据类型为buffer_item,大小为1000的数组,按环形队列处理 生产者 ...

  7. ARM2440 LCD实验

    1. S3C2440内部LCD控制器结构图: 我们根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器: a:LCD控制器由REGBANK.LCDCDMA.TIMEGEN.VIDPRCS寄 ...

  8. wScratchPad 实现刮刮卡效果

    插件网址http://wscratchpad.websanova.com/

  9. python下的复杂网络编程包networkx的安装及使用

    由于py3.x与工具包的兼容问题,这里采用py2.7 1.python下的复杂网络编程包networkx的使用: http://blog.sina.com.cn/s/blog_720448d30101 ...

  10. JSP中的EL

    1.为什么要使用EL 使用<jsp:getProperty>,只能访问bean属性的性质,不能访问嵌套性质.例如一个含有Dog对象的Person对象. 当然使用脚本可以工作,但是如果不想使 ...