[反汇编练习] 160个CrackMe之029
[反汇编练习] 160个CrackMe之029.
本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西。
其中,文章中按照如下逻辑编排(解决如下问题):
1、使用什么环境和工具
2、程序分析
3、思路分析和破解流程
4、注册机的探索
----------------------------------
提醒各位看客: 如果文章中的逻辑看不明白,那你一定是没有亲手操刀!OD中的跳转提示很强大,只要你跟踪了,不用怎么看代码就理解了!
----------------------------------
1、工具和环境:
WinXP SP3 + 52Pojie六周年纪念版OD + PEID + 汇编金手指。
160个CrackMe的打包文件。
下载地址: http://pan.baidu.com/s/1xUWOY 密码: jbnq
注:
1、Win7系统对于模块和程序开启了随机初始地址的功能,会给分析带来很大的负担,所以不建议使用Win7进行分析。
2、以上工具都是在52PoJie论坛下的原版程序,NOD32不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。
2、程序分析:
想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。
和上一节一样,打开CHM,选择第29个CoSH.2.exe,保存下来。运行程序,程序界面如下:
点击上面的Check按钮,弹出了信息框,很好。
注意的是,点击确定按钮后,程序直接退出了。
PEID:Microsoft Visual C++ 6.0
哈哈哈,VC++的,我最喜欢了!
3、思路分析和破解流程
没有信息框,我们可以试试查找文本的办法。
1、打开OD,将exe拖到OD窗口中,等程序暂停后,直接点击运行按钮(F9),不用理会。
2、随意输入伪码:BBDXF 123123。点击CHECK按钮,弹出信息框,不要关闭,回到OD。
3、Ctrl+K查看堆栈信息:
和之前的一样,找到Messagebox的下一个调用处,右键->Show call。
4、在反汇编窗口查看代码信息:
004015C1 |. EB 16 jmp short 004015D9 ; // 关键跳转?没有判断,肯定不是的
004015C3 |> 6A 00 push 0x0
004015C5 |. 68 6C304000 push 0040306C ; ASCII "ERROR"
004015CA |. 68 40304000 push 00403040 ; ASCII "One of the Details you entered was wrong"
004015CF |. 8B4D E0 mov ecx,[local.8]
004015D2 |. E8 BB020000 call <jmp.&MFC42.#4224> ; // 返回到这里
附近的几个随意看看,没有找到关键跳转,哎,全部都看看吧:
004014B0 /. 55 push ebp
004014B1 |. 8BEC mov ebp,esp
004014B3 |. 6A FF push -0x1
004014B5 |. 68 C21B4000 push 00401BC2 ; SE handler installation
004014BA |. 64:A1 0000000>mov eax,dword ptr fs:[0]
004014C0 |. 50 push eax
004014C1 |. 64:8925 00000>mov dword ptr fs:[0],esp
004014C8 |. 83EC 14 sub esp,0x14
004014CB |. 53 push ebx
004014CC |. 56 push esi
004014CD |. 57 push edi
004014CE |. 894D E0 mov [local.8],ecx
004014D1 |. 8D4D E4 lea ecx,[local.7]
004014D4 |. E8 83030000 call <jmp.&MFC42.#540>
004014D9 |. C745 FC 00000>mov [local.1],0x0
004014E0 |. 8D4D F0 lea ecx,[local.4]
004014E3 |. E8 74030000 call <jmp.&MFC42.#540>
004014E8 |. C645 FC 01 mov byte ptr ss:[ebp-0x4],0x1
004014EC |. 8B4D E0 mov ecx,[local.8]
004014EF |. 81C1 A0000000 add ecx,0xA0
004014F5 |. E8 AA030000 call <jmp.&MFC42.#3876> ; // 猜测是获取文本长度
004014FA |. 8945 EC mov [local.5],eax ; // eax = 5
004014FD |. 837D EC 05 cmp [local.5],0x5 ; // 文本长度大于5
00401501 7F 05 jg short 00401508 ; // 这个才是关键跳转
00401503 E9 BB000000 jmp 004015C3 ; // 直接跳到失败
00401508 |> 8B4D E0 mov ecx,[local.8]
0040150B |. 83C1 60 add ecx,0x60
0040150E |. E8 91030000 call <jmp.&MFC42.#3876>
00401513 |. 8945 E8 mov [local.6],eax
00401516 |. 837D E8 05 cmp [local.6],0x5
0040151A |. 7F 05 jg short 00401521
0040151C |. E9 A2000000 jmp 004015C3
00401521 |> 8B45 E0 mov eax,[local.8]
00401524 |. 05 E0000000 add eax,0xE0
00401529 |. 50 push eax
0040152A |. 8B4D E0 mov ecx,[local.8]
0040152D |. 81C1 A0000000 add ecx,0xA0
00401533 |. E8 66030000 call <jmp.&MFC42.#3874>
00401538 |. 8B4D E0 mov ecx,[local.8]
0040153B |. 81C1 E4000000 add ecx,0xE4
00401541 |. 51 push ecx
00401542 |. 8B4D E0 mov ecx,[local.8]
00401545 |. 83C1 60 add ecx,0x60
00401548 |. E8 51030000 call <jmp.&MFC42.#3874>
0040154D |. 8B55 E0 mov edx,[local.8]
00401550 |. 81C2 E0000000 add edx,0xE0
00401556 |. 52 push edx
00401557 |. 8D4D E4 lea ecx,[local.7]
0040155A |. E8 39030000 call <jmp.&MFC42.#858>
0040155F |. 8B45 E0 mov eax,[local.8]
00401562 |. 05 E4000000 add eax,0xE4
00401567 |. 50 push eax
00401568 |. 8D4D F0 lea ecx,[local.4]
0040156B |. E8 28030000 call <jmp.&MFC42.#858>
00401570 |. 33C0 xor eax,eax ; // eax = 0
00401572 |. 33DB xor ebx,ebx ; // ebx = 0
00401574 |. 33C9 xor ecx,ecx ; // ecx = 0
00401576 |. B9 01000000 mov ecx,0x1 ; // ecx = 1
0040157B |. 33D2 xor edx,edx ; // edx = 0
0040157D |. 8B45 E4 mov eax,[local.7] ; // "bbdxf1"
00401580 |> 8A18 /mov bl,byte ptr ds:[eax]
00401582 |. 32D9 |xor bl,cl
00401584 |. 8818 |mov byte ptr ds:[eax],bl
00401586 |. 41 |inc ecx ; // ecx++
00401587 |. 40 |inc eax ; // eax++, 字符串向右一个
00401588 |. 8038 00 |cmp byte ptr ds:[eax],0x0
0040158B |.^ 75 F3 \jnz short 00401580 ; // 得到字符串 "c`g|c7"
0040158D |. 33C0 xor eax,eax ; 0
0040158F |. 33DB xor ebx,ebx ; 0
00401591 |. 33C9 xor ecx,ecx ; 0
00401593 |. B9 0A000000 mov ecx,0xA ; 0x0A
00401598 |. 33D2 xor edx,edx ; 0
0040159A |. 8B45 F0 mov eax,[local.4] ; // "123123"
0040159D |> 8A18 /mov bl,byte ptr ds:[eax]
0040159F |. 32D9 |xor bl,cl
004015A1 |. 8818 |mov byte ptr ds:[eax],bl
004015A3 |. 41 |inc ecx
004015A4 |. 40 |inc eax
004015A5 |. 8038 00 |cmp byte ptr ds:[eax],0x0 ; // 得到字符串 ";9?<<<"
004015A8 |.^ 75 F3 \jnz short 0040159D
004015AA |. 8B45 E4 mov eax,[local.7] ; ASCII "c`g|c7"
004015AD |. 8B55 F0 mov edx,[local.4] ; ASCII ";9?<<<"
004015B0 |> 33C9 /xor ecx,ecx ; 0
004015B2 |. 8A18 |mov bl,byte ptr ds:[eax]
004015B4 |. 8A0A |mov cl,byte ptr ds:[edx]
004015B6 |. 3AD9 |cmp bl,cl ; // 循环比较字符串的每一个字符
004015B8 |. 75 09 |jnz short 004015C3 ; // 有一个不相等则失败
004015BA |. 40 |inc eax
004015BB |. 42 |inc edx
004015BC |. 8038 00 |cmp byte ptr ds:[eax],0x0
004015BF |.^ 75 EF \jnz short 004015B0
004015C1 |. EB 16 jmp short 004015D9 ; // 关键跳转?没有判断,肯定不是的
004015C3 |> 6A 00 push 0x0
004015C5 |. 68 6C304000 push 0040306C ; ASCII "ERROR"
004015CA |. 68 40304000 push 00403040 ; ASCII "One of the Details you entered was wrong"
004015CF |. 8B4D E0 mov ecx,[local.8]
004015D2 |. E8 BB020000 call <jmp.&MFC42.#4224> ; // 返回到这里
004015D7 |. EB 14 jmp short 004015ED
004015D9 |> 6A 00 push 0x0
004015DB |. 68 34304000 push 00403034 ; ASCII "YOU DID IT"
004015E0 |. 68 20304000 push 00403020 ; ASCII "Well done,Cracker"
004015E5 |. 8B4D E0 mov ecx,[local.8]
004015E8 |. E8 A5020000 call <jmp.&MFC42.#4224>
004015ED |> 6A 64 push 0x64 ; /Timeout = 100. ms
004015EF |. FF15 00204000 call dword ptr ds:[<&KERNEL32.Sleep>] ; \Sleep
004015F5 |. C645 FC 00 mov byte ptr ss:[ebp-0x4],0x0
004015F9 |. 8D4D F0 lea ecx,[local.4]
004015FC |. E8 65010000 call <jmp.&MFC42.#800>
00401601 |. C745 FC FFFFF>mov [local.1],-0x1
00401608 |. 8D4D E4 lea ecx,[local.7]
0040160B |. E8 56010000 call <jmp.&MFC42.#800>
00401610 |. 8B4D F4 mov ecx,[local.3]
00401613 |. 64:890D 00000>mov dword ptr fs:[0],ecx
0040161A |. 5F pop edi
0040161B |. 5E pop esi
0040161C |. 5B pop ebx
0040161D |. 8BE5 mov esp,ebp
0040161F |. 5D pop ebp
00401620 \. C3 retn
这个流程已经很简单了,爆破似乎都没什么必要了!
比如:00401501 7F 05 jg short 00401508 原本用来判断字符串长度的跳转就可以,我们直接修改为jmp 004015D9.哈哈!!
4、注册机的探索
算法其实很简单,核心内容为:
00401570 |. 33C0 xor eax,eax ; // eax = 0
00401572 |. 33DB xor ebx,ebx ; // ebx = 0
00401574 |. 33C9 xor ecx,ecx ; // ecx = 0
00401576 |. B9 01000000 mov ecx,0x1 ; // ecx = 1
0040157B |. 33D2 xor edx,edx ; // edx = 0
0040157D |. 8B45 E4 mov eax,[local.7] ; // "bbdxf1"
00401580 |> 8A18 /mov bl,byte ptr ds:[eax]
00401582 |. 32D9 |xor bl,cl
00401584 |. 8818 |mov byte ptr ds:[eax],bl
00401586 |. 41 |inc ecx ; // ecx++
00401587 |. 40 |inc eax ; // eax++, 字符串向右一个
00401588 |. 8038 00 |cmp byte ptr ds:[eax],0x0
0040158B |.^ 75 F3 \jnz short 00401580 ; // 得到字符串 "c`g|c7"
就是将Name的每一个字符都与ecx异或,ecx从1每次递增1,最后得到的字符串1。然后再对Serial做类似的处理得到字符串2,最后将字符串1和2比较,如果相等,则通过。
总体来讲就是两个大于5个字符的字符串,通过只有一个常量不同的算法,得到的字符串相等。这…..
C/CPP算法模拟:
// 用户名算法模拟
char* pName = "bbdxf1";
char pOut[10] = {0};
for(int i=0;i<strlen(pName);i++)
{
pOut[i] = pName[i] ^ (i+1);
}
printf("%s\r\n",pOut); // 注册码算法模拟
char* pKey = "123123";
char pOut[10] = {0};
for(int i=0;i<strlen(pKey);i++)
{
pOut[i] = pKey[i] ^ (i+0x0A);
}
printf("%s\r\n",pOut);
好吧,算法出来了,但是我们不可能凭空想到一个字符串能够完成这样的结果。所以,只有反算法了!
算法是通过异或得到【密文】比较相等,我们可以反过来,指定一个密文,分别反出来两个【原文】,即CPP算法中的Name和Key内容相同,输出的两个非别为Name和Key即可。
// CrackMeDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream" int _tmain(int argc, _TCHAR* argv[])
{
// 用户名算法模拟
char* pName = "bbdxf1";
printf("%s\r\n",pName);
char pOut[10] = {0};
for(int i=0;i<strlen(pName);i++)
{
pOut[i] = pName[i] ^ (i+1);
}
printf("Name:%s\r\n",pOut); // 注册码算法模拟
char* pKey = pName;
for(int i=0;i<strlen(pKey);i++)
{
pOut[i] = pKey[i] ^ (i+0x0A);
}
printf("key:%s\r\n",pOut);
system("pause");
return 0;
}
BY 笨笨D幸福
[反汇编练习] 160个CrackMe之029的更多相关文章
- [反汇编练习] 160个CrackMe之027
[反汇编练习] 160个CrackMe之027. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之026
[反汇编练习] 160个CrackMe之026. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之025
[反汇编练习] 160个CrackMe之025. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之024
[反汇编练习] 160个CrackMe之024. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之022
[反汇编练习] 160个CrackMe之022. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之021
[反汇编练习] 160个CrackMe之021. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之020
[反汇编练习] 160个CrackMe之020. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之019
[反汇编练习] 160个CrackMe之018. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之018
[反汇编练习] 160个CrackMe之018. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
随机推荐
- configurationChanges
在Android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置.在activity加上android:c ...
- Java多线程框架源码阅读之---ReentrantLock
ReentrantLock基于Sync内部类来完成锁.Sync有两个不同的子类NonfairSync和FairSync.Sync继承于AbstractQueuedSynchronizer. Reent ...
- javaScript流程控制与函数
流程控制 1.1 条件语句 分支结构 单向分支 if (条件表达式) { code... } <!DOCTYPE html> <html> <head> <m ...
- Concept with HTTP API && RPC
RPC=Remote Produce Call 是一种技术的概念名词. HTTP是一种协议,RPC可以通过HTTP来实现,也可以通过Socket自己实现一套协议来实现.所以楼主可以换一个问法,为何RP ...
- [BZOJ4318] WJMZBMR打osu! / Easy (期望DP)
题目链接 Solution Wa,我是真的被期望折服了,感觉这道题拿来练手正好. DP的难度可做又巧妙... 我们定义: \(f[i]\) 代表到第 \(i\) 次点击的时候的最大答案. \(g[i] ...
- P1382 楼房 (扫描线,线段树)
题目描述 地平线(x轴)上有n个矩(lou)形(fang),用三个整数h[i],l[i],r[i]来表示第i个矩形:矩形左下角为(l[i],0),右上角为(r[i],h[i]).地平线高度为0.在轮廓 ...
- iOS-sqlite3&FMDB使用代码示范
数据库操作是我们使用十分频繁的一份操作,在iOS中如何使用数据库,使用什么数据库,是我们不得不考虑的一个问题. 小型数据我们可以使用plist文件,或者NSUserDefaults存储.数据量比较多得 ...
- java面试题之死锁产生的条件,以及如何避免死锁,银行家算法,产生死锁后如何解决(阿里面试题)
死锁产生的四个必要条件: 互斥:一个资源每次只能被一个进程使用(资源独立) 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放(不释放锁) 不剥夺:进程已获得的资源,在未使用之前,不能强行 ...
- 聊聊 Spring Boot 2.0 的 WebFlux
聊聊 Spring Boot 2.0 的 WebFlux## 前言 对照下 Spring Web MVC ,Spring Web MVC 是基于 Servlet API 和 Servlet 容器设计的 ...
- 使用 Spring Boot 2.0 + WebFlux 实现 RESTful API
概述 什么是 Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发框架. 要深入了解 Spring WebFlux, 首先要了知道 R ...