吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 17832|回复: 127
收起左侧

[CrackMe] 【暑假活动后续】"最后的CM"破解超详细解析 追码爆破+文图说明+演示教程

    [复制链接]
Kris 发表于 2011-8-2 18:20
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

本帖最后由 Peace 于 2011-8-5 14:59 编辑

【暑假活动后续】"最后的CM"详细解析(追码+爆破)  CM的破解探讨
作者:Kris
感谢指导:qaz大大,小生吾怕怕大大
帖子链接:http://bbs.52pojie.cn/thread-101488-1-1.html
废话不多说,俺是菜菜,第一次写破文,写的不对的地方还请大大指教!
如果觉得做得好,求加分!!!!!!!!!!!!!!!!~~~~
首先,我们打开CM看一下

看到这个CM的界面以后,可以明确2点:
1.该CM应该的单机单号,有机器码和注册码,也就是说在点注册按钮的时候应该会计算出真码
2.该CM存在按钮,应该是按下按钮以后才会检测Key是否正确,而不是在输入Key的时候就检测或者用其他方式检测的
明确了这2点后,把CM放到E-Debug中运行,并点击按钮,E-Debug告诉我们按钮事件的位置为004026B7

为什么有那么多个事件,却说按钮事件为004026B7呢?因为我们只点击了一次按钮,在这些事件中只有一次的就只有
事件发生: 00401A11
事件发生: 004026B7
注意,事件发生: 00401A11是在窗体创建的时候就已经发生的事件,而不是在我们点击按钮之后才发生的,因此,按钮事件就为004026B7了

得到了按钮事件的地址,我们可以关闭掉E-Debug了,现在打开今天的主角OD,把CM拖入OD后运行,在按钮事件004026B7处下断点,然后点击按钮,就中断住了

F7单步跟踪,跟到0044F223的时候发现关键代码

调用CreateThread创建线程,堆栈窗口信息如下

线程的地址是40340A,我们在40340A处下断,然后继续让程序运行,很快,OD就中断在40340A了,F8继续跟踪,执行完
00403438    E8 0AF3FFFF     call 00402747
出现了可疑字符串,有可能是真码

因此,我们把断点清除一下,然后在00403438处下断,重新载入运行并点击按钮,然后会中断在00403438,这个时候我们F7跟进这个CALL
发现了一大堆算法指令,果断无视它们,写注册机以我的水平简直就是天方夜谭,况且这个CM还是qaz大大写的,因此我们不研究算法,只研究追码和爆破
在算法指令跑完之后,好像没有发现什么可疑的判断真码和假码是否相同的代码,但是在算法结束后,发现了这样一句指令
004028A4    C705 1CFE4A00 01000000  mov dword ptr ds:[0x4AFE1C],0x1
把4AFE1C这个位置赋值为1,至于为什么要这样做,程序里面肯定有用到这个的地方,
因此,我们执行这一句指令的时候,在004AFE1C处下内存访问断点,然后点运行按钮,继续让程序运行
不久后OD中断在
00401F4B    833D 1CFE4A00 01    cmp dword ptr ds:[0x4AFE1C],0x1
00401F52    0F85 4A000000          jnz 00401FA2
这两句的作用是用[4AFE1C]与1作比较,如果不同则跳,
我们知道,在执行完刚才的生成真码的函数以后这里才会变为1,否则这里一直是为0的,因此这里判断它是否为1,很可能就是判断是否已经产生了真码,
也就是说这里很可能将会对真码和假码做比较,看是否相同,所以我们这里继续F7单步步入,不久后又看到了关键代码
以下回复可见
又调用CreateThread创建线程,堆栈窗口信息如下

线程的地址是402612,我们在402612处下断,然后继续让程序运行,很快,OD就中断在402612了,F8继续跟踪,当执行
00402638    E8 41FAFFFF         call 0040207E
的时候,OD卡死了,因此这里可能是一个关键CALL,把断点清除一下,然后在这里下断,重新载入运行并点击按钮,不久后中断在这里,F7单步步入,
进入这个函数以后,发现里面有一些CALL一样会导致OD卡死,因此,这里F7单步步入的时候,碰到CALL,全部在CALL的下一句指令下断,然后直接点运行,执行到如下命令的时候会发现

eax=真码(如果要追码的话,这里就可以追到咯^_^),我的真注册码是
185?193?28?51?214?75?60?225?~72?216?51?11?76?117?205?46?133?120?237?7?132?180?113?198?~214?145?46?17?227?174?147?109?13?69?67?72?247?184?72?172?~128?147?0?108?147?136?240?34?203?254?21?237?107?72?81?188?~145?123?116?91?136?92?253?114?110?131?161?9?209?64?160?115?~229?245?181?64?249?155?197?109?161?253?240?171?123?110?43?19?~19?12?130?170?241?95?77?84?252?150?2?31?208?97?11?210?~180?27?9?57?49?207?100?99?87?69?224?179?144?231?73?65?~124?181?30?228?153?206?141?184?144?41?7?43?186?195?95?217?~13?136?198?245?219?216?127?128?206?198?75?4?84?250?20?231?~1?199?126?41?8?114?8?177?
[ebp-0x8]=假码,并且调用函数比较它们,这里就是我们要找的检测Key是否正确的关键代码了,那么我们继续往下执行,注意当执行到
004020DA   0F84 6A000000       je 0040214A
的时候,跳转是未实现的,并且这个跳转是取决于刚才那个比较函数的返回值,因此,这个跳转是一个关键跳,
把断点清除一下,并在这里设置断点,然后先按着程序原来的流程继续跟踪一下,发现不久后弹出了框框,注册失败就会弹出这种框框了,
因此这里就更加清楚了,如果这个跳转是未实现的就是注册失败了,因此我们要爆破它,这个跳转就应该改为JMP
重新载入运行并点击按钮,断在刚才的004020DA处,把je改为JMP,完成第一处关键跳的修改,
继续单步跟踪,执行到402184的时候发现二次效验

很明显00402196   0F85 ED000000       jnz 00402289是关键跳,把它用NOP代替,即可完成爆破
总结一下"最后的CM"注册流程:
1.按下按钮后,触发Button,调用线程,线程再调用BuildKey
2.BuildKey函数生成了Key之后,把CheckKey标志赋值为TRUE
3.在窗体启动的时候,有一个时钟(Timer)始终检测CheckKey标志是否为TRUE,检测到后创建CheackKeyThread线程
4.CheackKeyThread线程调用函数Check,Check为最终判断Key是否正确的函数
//下面是我模拟该程序的C代码
//设置Key已经产生的标志,高级语言里面可以这样写:
//(由于我没学E语言,所以用C语言代替)
//(注:在C中FALSE宏为0,TRUE宏为1)
BOOL CheckKey=FALSE;
//CheckKey为布尔型,并且初始化值为FALSE
void Check()
{
......
效验①
004020AC    50                           push eax                                       eax=真码
004020AD    FF75 F8                   push dword ptr ss:[ebp-0x8]       dword ptr ss:[ebp-0x8]=假码
004020B0    E8 2CFFFFFF           call 00401FE1                               判断是否相同,相同返回0
004020DA   0F84 6A000000      je 0040214A               如果返回不为0,则说明不相同,那么这个je跳转是不实现的,就会无限弹窗了,明显,这个应该改为JMP
......
效验②
00402184    50                           push eax                                    eax=假码
00402185    FF35 20FE4A00      push dword ptr ds:[0x4AFE20]   dword ptr ss:[ebp-0x8]=真码
0040218B    E8 51FEFFFF          call 00401FE1              判断是否相同,相同返回0
00402196    0F85 ED000000   jnz 00402289              如果返回不为0,则说明不相同,那么这个je跳转是实现的,那么窗口就会无限乱弹,明显,这个应该改为NOP
......
}
DWORD WINAPI CheackKeyThread()//00402612,检测Key是否正确的线程
{
......
00402638    E8 41FAFFFF     call 0040207E ;//调用一个子程序来判断
......
}
Timer()//00401F3D,检测CheckKey是否为TRUE的时钟
{
    //00401F4B    833D 1CFE4A00 01        cmp dword ptr ds:[0x4AFE1C],0x1
    if(CheckKey==TRUE)//如果CheckKey标志为TRUE
    {
    CreateThread(NULL,NULL,NULL,(LPTHREAD_START_ROUTINE)CheackKeyThread,NULL,NULL,NULL);
    //创建线程创建线程来判断输入的注册码和真码是否相同
    }
}
char * BuildKey()//004028ED
{
    char Key[256];
    BuildKey Code....
    CheckKey=TRUE;
    //004028A4    C705 1CFE4A00 01000000  mov dword ptr ds:[0x4AFE1C],0x1
    //算出Key以后把检测标志改为TRUE,让Timer对Key进行判断
    return Key;
}
void Button()//004026B7
{
......//这里调用了一大堆的子程序,最后CALL BuildKey函数
}

演示教程:http://u.115.com/file/e6yps6cn如果觉得做得好,求加分!!!!!!!!!!!!!!!!~~~~


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 9热心值 +9 收起 理由
liuxuda + 1 不用浪费
125096 + 1 很好啊,支持你
yjd333 + 1 精品文章!
xiaorong520 + 1 你说你是菜菜......
吾爱、硬币 + 1 和小驴一样只能膜拜
小花匠 + 1 膜拜小曾大牛!!!
热火朝天 + 1 精彩
tianlinghu + 1 写的好!学习了~
Rookietp + 1 Kris湿傅!!小弟给你加分了!!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

阿杰 发表于 2011-8-2 18:29
  膜拜K大牛,  第一名是你的了。
tianlinghu 发表于 2011-8-2 18:45
热火朝天 发表于 2011-8-2 19:09
Sloth 发表于 2011-8-2 19:27
膜拜..你懂的.
头像被屏蔽
zhi5231 发表于 2011-8-2 19:32
提示: 作者被禁止或删除 内容自动屏蔽
LShang 发表于 2011-8-2 19:33
还没看完呢。。 怎么成了回复可见了
qq523683017 发表于 2011-8-2 19:36
膜拜第一名
变化 发表于 2011-8-2 19:59
sb123456

免费评分

参与人数 1违规 +1 收起 理由
Kris + 1 污蔑诽谤骂人灌水

查看全部评分

吾爱、硬币 发表于 2011-8-2 20:48
来看教程咯~~
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-3 16:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表