老文章档案 · 2003 年

算法分析: <献给初学者> 之三

破解教程 · 算法分析 · 2003-08-19 · 作者:goodbao[P.J.CHINA] 人气: · 出处:赢政天下整理收藏)

▲软件名称▲ CRACKME.EXE

▲下载地址▲ http://ddcrack.myetang.com/crackit/crackme/ctm-cm2.zip

▲破解难度▲

应该说无论从破解角度,还是算法角度,它都可以算作较难级别。其本身推荐级别就为2级。特别是它的破解,如果单纯地从动态调试角度去看的话,恐怕作为一名初学者来讲,会被搞得一头雾水。所以,它的破解与算法比较起来则更为困难和复杂。

▲破解思路▲

首先,我们要找到那个Key File文件名和文件类型。然后,正确设置断点:Bpx CreatefileA。此断点的含义是:确定文件是否存在;打开文件并获得句柄。再后,我们就要用16进制编辑器来建立一个假的KEYFILE文件,推荐使用HexWorkshop。而且,本例也必须使用HexWorkshop这样的16进制编辑器方可。建立好假的钥匙文件后,就要在文件里面先随便地写入一些东东,保存并退出该钥匙文件。接下来,再重新运行待破解程序,按照正常破解思路去寻找突破口,争取找到其文件中的内容,以便正确构造这个KEYFILE。

好了,让我们一起出发吧!Let's go!!!!!!

▲破解过程▲

首先,我们来找到Key File的名称及类型。使用反汇编(先脱去其UPX壳)、动态跟踪或者使用 Filemon,这三种方法均可准确找到其钥匙文件的名称类型信息,这个比较简单,不详细叙述了。它的钥匙文件为:CTM_CM02.KEY。是个注册表类型文件,存入路径为安装目录下。所以,我们就可以用HexWorkshop来建立这样一个文件,然后再编辑它,在里面随便写入一些东东。(关于HexWorkshop的使用方法,这里也不详述,请大家参照看雪及相关教程)

好了,准备工作已经做好了,让我们来看看到底这个CRACKME有哪些与众不同之处吧?!

如上面所提设断,然后运行程序(或者先运行程序,在程序还未弹出错误提示前,快速启动SI也可以),程序被成功拦截。然后按2次F12,然后按F10到达下面这里…………

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00426570(C)

|

:00426553 8D85F4FFFEFF lea eax, dword ptr [ebp+FFFEFFF4]

:00426559 BA40674200 mov edx, 00426740

:0042655E E839CEFDFF call 0040339C

:00426563 FE85FBFFFEFF inc byte ptr [ebp+FFFEFFFB]

:00426569 80BDFBFFFEFF00 cmp byte ptr [ebp+FFFEFFFB], 00

:00426570 75E1 jne 00426553

* Possible StringData Ref from Code Obj ->"ctm_cm02.key"=============>可见钥匙文件名称

及文件类型信息。

|

:00426572 BA4C674200 mov edx, 0042674C

:00426577 8D85A8FEFEFF lea eax, dword ptr [ebp+FFFEFEA8]

:0042657D E83FD8FDFF call 00403DC1

:00426582 BA01000000 mov edx, 00000001

:00426587 8D85A8FEFEFF lea eax, dword ptr [ebp+FFFEFEA8]

:0042658D E81EDCFDFF call 004041B0

:00426592 E84DC1FDFF call 004026E4

:00426597 85C0 test eax, eax

:00426599 0F8566010000 jne 00426705

:0042659F 8D85A8FEFEFF lea eax, dword ptr [ebp+FFFEFEA8]

:004265A5 E85AD9FDFF call 00403F04=====================>EAX=你输入的字符 长度值

:004265AA E8F9C0FDFF call 004026A8

:004265AF 8945FC mov dword ptr [ebp-04], eax=======>[ebp-04]=字符长度004265B2 837DFC00 cmp dword ptr [ebp-04], 00000000===>钥匙文件内的字符长度与00比较

:004265B6 7515 jne 004265CD======================>不是00就跳到下边。

* Possible StringData Ref from Code Obj ->"Key file is empty!"======>提示钥匙文件为空!

|

:004265B8 BA64674200 mov edx, 00426764

:004265BD 8B83B0010000 mov eax, dword ptr [ebx+000001B0]

:004265C3 E8CCB6FEFF call 00411C94

:004265C8 E928010000 jmp 004266F5

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004265B6(C)

|

:004265CD 817DFC00000100 cmp dword ptr [ebp-04], 00010000===>钥匙文件内的字符

长度与0x10000比较

:004265D4 7E07 jle 004265DD=======================>不大于则跳!

:004265D6 C745FC00000100 mov [ebp-04], 00010000=============>大于则置[ebp-04]为0x10000。

以上过程是在对钥匙文件内你输入的字符串长度进行比较定位,如果不大于0x10000,就跳走,继续执行下面,如果字符串长度超出0x010000范围,则置[ebp-04]为0x10000。呵呵。。。。

以下是真正要进入关键了。我将以******符号把我的破解中的想法及破解方法标明出来。希望大家可以看得清楚些。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004265D4(C)

|

:004265DD 6A00 push 00000000

:004265DF 8D95FCFFFEFF lea edx, dword ptr [ebp+FFFEFFFC]

:004265E5 8B4DFC mov ecx, dword ptr [ebp-04]=======>字符串长度送ECX

:004265E8 8D85A8FEFEFF lea eax, dword ptr [ebp+FFFEFEA8]

:004265EE E871D8FDFF call 00403E64

:004265F3 E8B0C0FDFF call 004026A8

:004265F8 53 push ebx

:004265F9 57 push edi

:004265FA 56 push esi

:004265FB 8D75FC lea esi, dword ptr [ebp-04]

:004265FE 8B0E mov ecx, dword ptr [esi]

:00426600 8DB5FCFFFEFF lea esi, dword ptr [ebp+FFFEFFFC]

:00426606 8DBDFBFFFEFF lea edi, dword ptr [ebp+FFFEFFFB]

:0042660C 31C0 xor eax, eax======================>EAX=0

:0042660E 83CAFF or edx, FFFFFFFF

:00426611 31DB xor ebx, ebx======================>EBX=0

:00426613 40 inc eax===========================>EAX=01

:00426614 F7D2 not edx===========================>EDX=0

************************关键部分之一******************************

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00426636(U)

|

:00426616 8A1C16 mov bl, byte ptr [esi+edx]******依次取你输入的字符放入

BL中。

:00426619 84DB test bl, bl*********************测试BL是否为0

:0042661B 7429 je 00426646***************** ①测试结果是0就跳到下边

:0042661D E816000000 call 00426638 ▲

:00426622 52 push edx

:00426623 F7E3 mul ebx**************EAX=EBX*EAX,相乘的结果放在EAX中

在前面,EBX已经被初始赋值为0。

:00426625 5A pop edx

:00426626 35326D5463 xor eax,63546D32******执行计算:EAXxor63546D32,并且把相异或的结果存入EAX中。而进一步查看的话,你可以发现:63546D32=“cTm2”。呵呵。。。。

:0042662B FEC2 inc dl===========>DL加1,作为循环的计数器。DL初始为0。

:0042662D 39CA cmp edx, ecx=====>比较循环次数与字符长度

:0042662F 7442 je 00426673********** ②循环完毕跳走

:00426631 80FAFF cmp dl, FF***********比较循环次数与FF(10进制的255)。如果相等,则跳走。这里实际上是一个限制,其作用后面说。

:00426634 743D je 00426673********** ③相等就跳走

:00426636 EBDE jmp 00426616==============>跳回去循环,直到循环完毕。

那么,也许有人会问:这部分代码写的不是很清楚吗?有什么问题吗?事实上,代码的意思是清楚的,只是如果单纯在动态下分析时,会让人一头雾水,因为这一小段代码中,包含的跳转命令太多太复杂,稍微疏忽一点儿,就会搞不清楚它的跳转目标了。所以,我还是把我破解的过程全如实地写出来,供大家参考。

好了,为了弄清楚到底这些跳转做什么用,我们就来看看。按照从下向上的顺序,先看③和②。

★如果②③处的跳转成立,那么,它们都将会跳到以下地方:

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:0042662F(C), :00426634(C), :00426651(C)***************************重点!要害!往下看!

| ▲ ▲ ▲

:00426673 B802000000 mov eax, 00000002******************跳到了这里。它跳过来后做什么呢?呵呵,它使EAX=02。那又怎么样啊?呵呵,请往下看!!!

:00426678 8907 mov dword ptr [edi], eax==========>[edi]=EAX

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:00426668(U), :00426671(U)

|

:0042667A 5E pop esi

:0042667B 5F pop edi

:0042667C 5B pop ebx

:0042667D 8A85FBFFFEFF mov al, byte ptr [ebp+FFFEFFFB]****使AL=02

:00426683 2C01 sub al, 01*************************AL=AL-01

:00426685 7208 jb 0042668F=======================>小于0则跳

:00426687 744A je 004266D3=======================>等于0则跳

:00426689 FEC8 dec al*****************************AL=AL-01

:0042668B 7458 je 004266E5************************等于0则跳

:0042668D EB66 jmp 004266F5

由于我们的EAX=02,因此,我们只会在 je 004266E5 处跳转。看看它跳到了哪里??

* Possible StringData Ref from Code Obj ->"Key file is not valid!"

| ▲▲▲▲▲▲▲▲▲▲

:004266E5 BAE0674200 mov edx, 004267E0***************此处下命令D,可以看见

上面的出错提示信息。

:004266EA 8B83B0010000 mov eax, dword ptr [ebx+000001B0]

:004266F0 E89FB5FEFF call 00411C94

因此,我们必须做到不能让②③跳转,也就是要做到不能让EAX=02。(最为关键之处!!!)

大家再往前面看看,先后共有三个跳转会到EAX=02的地方。因此,我们都要保证其跳转命令不能跳过来方可。如果能够做到这一点,那么,我们就可以从唯一剩下的可供选择的①处顺利往下运行了。

呵呵。那么就接着来!先来看看:如何才能做到程序必须在①处顺利往下运行呢?

****************************关键部分之二******************************

让我们回过头再来研究研究①处的代码吧。(此处真是关键中的关键啊!!!!)

:00426616 8A1C16 mov bl, byte ptr [esi+edx]******依次取你输入的字符放入

BL中。

:00426619 84DB test bl, bl*********************测试BL是否为0

:0042661B 7429 je 00426646***************** ①测试结果是0就跳到下边

:0042661D E816000000 call 00426638 ▲

仔细分析,可以看出:如果能够让BL为0,就会成功跳转;否则,玩完!呵呵,怎样才能为0?说实话,现在想来是挺简单,但是当时可真是感觉无从下手!其实说穿了,就是必须让所取到的字符中含有00!!!呵呵,看看后面的解释----“依次取你输入的字符放入BL中”。因此,只要让程序所取到的字符是00就能够满足跳转条件啦。不过千万别弄错了,这个00是指你输入的字符中含有00!这里就有一个问题了,就是前面提到的那个使用FF进行比较的限制条件,它的作用就是如果程序取FF位时,还没有出现00的话,它就会跳到出错的地方了。由此,我们在此可以获得重大突破:我们输入的字符串的字节中,要含有00,且它一定要出现在255位之前!就是最多只可有254位!那么,还犹豫什么呀?快把KeyFile改过来吧?记住,要用16进制编辑器改哟?

好了,现在我们可以顺利地在①处跳转了。万岁!!!!接着往下看看吧…………★如果①处的跳转成立,那么,它将跳到以下地方:

****************************关键部分之三*****************************

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:0042661B(C)

|

:00426646 E8EDFFFFFF call 00426638===========>我们跳到了这里。此处我们可以

得到如下信息:EAX=计算结果;ECX=字符长度;EDX=循环次数

:0042664B 42 inc edx******************EDX=循环次数+1

:0042664C 83C204 add edx, 00000004********EDX=EDX+04

:0042664F 39D1 cmp ecx, edx*************比较EDX与你输入的字符长度

:00426651 7520 jne 00426673*************不相等则跳!跳到哪里去了?

天哪!这个跳转正是能够使得EAX=02的第三个跳转!!!!因此,我们无论如何不能够让它跳!

怎样才能不让它跳?就是要让最后那个EDX与你输入的字符长度相等!!!!如何能够保证这一点呢?(非常关键!)我们来看:EDX=循环的次数。什么含义?就是00前面的字符长度,因为循环取你所输入的字符时,程序是遇到00才跳转过来的。因此,循环的次数,也就是00前面的字符的个数。那么我们就不难看出,EDX+1 则就是字串00所处的位置。然后呢?程序又让EDX加上了04。什么意思?就是说字符串00后面还有4位字符嘛!!!!!如果不是这样的话,ECX岂不与EDX不等啦?

因此,我们至此可以得出结论:不论前面如何,00后面必须保证有4个字符,方可使得上面的那个跳转指令失效!!!!还等什么,快改过来吧?

好了,我们又过了一关!一鼓作气,接着来!我们上面不跳,则会到达这里了………

****************************关键部分之四*****************************

:00426653 83EA04 sub edx, 00000004=========>EDX=EDX-04

:00426656 85C0 test eax, eax=============>测试EAX。此时,EAX中为前面

我们进行循环并计算的结果。

:00426658 7602 jbe 0042665C==============>不跳

:0042665A D1E8 shr eax, 1================>EAX逻辑右移1,即EAX/2。结果

保存在EAX中。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00426658(C)

|

:0042665C 3B0416 cmp eax, dword ptr [esi+edx]******[esi+edx]与EAX比较

[esi+edx]为你输入的00后的那四位字符!!!

:0042665F 7509 jne 0042666A**********************不等则跳!

后面的就简单了,不再具体陈述。其结果是,如果EAX与你输入的那后半部分字符串不相等,则会跳到出错的地方。所以,我们必须使得EAX与你输入的那后半部分字符串相等。这样,程序会执行下面的那条 JMP 0042667A 的跳转命令,最终跳到成功的地方!!!!!

:00426661 B800000000 mov eax, 00000000

:00426666 8907 mov dword ptr [edi], eax

:00426668 EB10 jmp 0042667A

还等什么?快改吧?(千万记住哟?你在寄存器中看到的EAX的显示数据,可是与实际应该输入的数据是反向的哟?为什么是这样子,就不用过多解释了吧?呵呵。。。。。)

▲破解及算法总结▲

其KeyFiles应该是这样子的:

1、你输入的字符中必须含有00,而且其后面必须保证只有4个字符。

2、这4个字符就是00前面那些字符依次相乘,并与63546D32=cTm2相异或后的结果除以2。

3、将除以2后的结果反转。

结果就是这样子:用户名+00+4位的计算后的结果。那么输入中文也是可以的,只不过计算时多了几步计算罢了。不会有人想偷懒直接在第一个字符的地方就输入00吧??哈哈!那样因为没有前面的循环,也就不会有后面的4位字符存在,自然也就会……………………

收工喽…………………………@!@

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

(出处:赢政天下整理收藏)

相关文章:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

我为人人《《==》》人人为我

关于我们 |

帮助(?)

| 广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright © 1999-2003

winzheng.com All Rights Reserved.

繁体版:由华琦数码技术提供

Powered

by:MeSky.Net

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史