首页
社区
课程
招聘
[原创]Brad Soblesky.2的算法分析
发表于: 2006-3-28 17:57 8037

[原创]Brad Soblesky.2的算法分析

2006-3-28 17:57
8037

题目:Brad Soblesky.2的算法分析
软件:Brad Soblesky.2
工具:PEID,OD
破文作者:rockandtcl
个人网页:http://18232.tianyablog.com
介绍:这是从《加密解密实战攻略》的光盘上拿来的,在第七章。书中是通过WINHEX查看内存方式得到注册码的,最近的我几乎痴迷的对算法有了很大的破解愿望。所以就做了算法分析。有不足的地方和错误的地方还请指教,谢谢!

首先运行下
输入注册名:rockandtcl
输入注册码:123456789
出现错误提示:
好开始破解
用PEID看了下发现无壳

用OD载入,我比较喜欢的是查看参考字符串,于是就找到了个,双击进入CPU查看。
往上找呀找呀,历经了千辛万苦总算被我找到断点(要不怎么说我菜呢),呵呵。设置断点,重新载入
还是输入刚才的注册名和注册码
现在开始分析代码:
0040156D   |.  E8 DE020000 call Brad_Sob.00401850
关键断点
00401572   |.  8945 E4     mov dword ptr ss:[ebp-1C],eax
00401575   |.  837D E4 05  cmp dword ptr ss:[ebp-1C],5
00401579   |.  7D 43       jge short Brad_Sob.004015BE
比较注册名是否大于等于5位,如果成立就跳到循环位置。
0040157B   |.  6A 40       push 40
0040157D   |.  68 20404000 push Brad_Sob.00404020            ;  ASCII "CrackMe"
00401582   |.  68 28404000 push Brad_Sob.00404028            ;  ASCII "User Name must have at least 5 characters."
代码省略..............
004015BE   |>  C745 E0 000>mov dword ptr ss:[ebp-20],0
计算前清零,以后这个就是保存计算结果的
004015C5   |.  EB 09       jmp short Brad_Sob.004015D0
以下是循环部分。不过第一次循环是从004015D0  mov eax,dword ptr ss:[ebp-20]开始的

004015C7   |>  8B55 E0     /mov edx,dword ptr ss:[ebp-20]
004015CA   |.  83C2 01     |add edx,1
004015CD   |.  8955 E0     |mov dword ptr ss:[ebp-20],edx

004015D0   |>  8B45 E0      mov eax,dword ptr ss:[ebp-20]
004015D3   |.  3B45 E4     |cmp eax,dword ptr ss:[ebp-1C]
004015D6   |.  7D 42       |jge short Brad_Sob.0040161A
比较是否取完
004015D8   |.  8B4D E0     |mov ecx,dword ptr ss:[ebp-20]
004015DB   |.  51          |push ecx                         ; /Arg1
004015DC   |.  8D4D EC     |lea ecx,dword ptr ss:[ebp-14]    ; |
004015DF   |.  E8 1C030000 |call Brad_Sob.00401900           ; \Brad_Sob.00401900
逐个取注册码,并换成16进制数值,现在是rockandtcl所以第一次的话取'r'->72
004015E4   |.  0FBED0      |movsx edx,al
EDX=72
004015E7   |.  8B45 F0     |mov eax,dword ptr ss:[ebp-10]
第一次是装入常数81276345(16进制)放在EAX
004015EA   |.  03C2        |add eax,edx
EAX与EDX相加保存在EAX=812763B7
004015EC   |.  8945 F0     |mov dword ptr ss:[ebp-10],eax
保存相加的结果
004015EF   |.  8B4D E0     |mov ecx,dword ptr ss:[ebp-20]
取位置数,因为是C编写的,根据字符数组的定义,第一个字符是STRING[0],所以这时候ECX=0
004015F2   |.  C1E1 08     |shl ecx,8
移位,现在是0,所以移位后还是0,如果是1的话就是100,依此类推
004015F5   |.  8B55 F0     |mov edx,dword ptr ss:[ebp-10]
EDX=812763B7
004015F8   |.  33D1        |xor edx,ecx
异或运算后 保存在EDX
004015FA   |.  8955 F0     |mov dword ptr ss:[ebp-10],edx
保存刚才异或运算后的结果 812763B7
004015FD   |.  8B45 E0     |mov eax,dword ptr ss:[ebp-20]
取相加的结果 812763B7
00401600   |.  83C0 01     |add eax,1
注册名字符的位置数加1放在EAX,EAX=1
00401603   |.  8B4D E4     |mov ecx,dword ptr ss:[ebp-1C]
00401606   |.  0FAF4D E0   |imul ecx,dword ptr ss:[ebp-20]
注册名字符的位置数与注册名的总长度相乘,放在ECX,第一次的时候位置数为0
所以相乘的结果是0,保存在ECX中
0040160A   |.  F7D1        |not ecx
非运算 ECX=FFFFFFFF
0040160C   |.  0FAFC1      |imul eax,ecx
这时候EAX=FFFFFFFF
0040160F   |.  8B55 F0     |mov edx,dword ptr ss:[ebp-10]
取异或的结果 放在EDX。EDX=812763B7
00401612   |.  0FAFD0      |imul edx,eax
这得想说明下,理清下思路:
1.首先装入个初始值:81276345
2,加上了'r'的ASCII码的值:72这时候的值为812763B7
3,对注册名字符串位置数,做移8位处理,转为16进制,然后与相加的值做异或运算
4,r的位置在字符串[根据C的定义]为0,加上1(放着)
5,位置数与总长度相乘,然后取非,与(位置+1)相乘。
6,5的结果和3的结果相乘,如果溢出取后32位

总结下,这时候第一次取注册码的结果是:7ED89C49
00401615   |.  8955 F0     |mov dword ptr ss:[ebp-10],edx
保存结果
00401618   |.^ EB AD       \jmp short Brad_Sob.004015C7
重新开始循环

那循环开始的代码什么意思呢?

004015C7   |>  8B55 E0     /mov edx,dword ptr ss:[ebp-20]
004015CA   |.  83C2 01     |add edx,1
004015CD   |.  8955 E0     |mov dword ptr ss:[ebp-20],edx

004015D0   |>  8B45 E0      mov eax,dword ptr ss:[ebp-20]
004015D3   |.  3B45 E4     |cmp eax,dword ptr ss:[ebp-1C]
004015D6   |.  7D 42       |jge short Brad_Sob.0040161A

只是判断是否取完。这个判断是从第二次循环开始的

所以呢:总结下
注册码是:rockandtcl
对应的数值是:72 6F 63 6B 61 6E 64 74 63 6C
第一做完后的结果是:7ED89C49,第二次:19627230,第三次:C0C64BD3,第四次:9FF19DF8
第五次:EB8766BB第六次:782CAAFE,第七次:8D7ACD8A,第八次:178D9C70,第九次:EDD33325,第十次:9B25D092

十次循环结束了,现在继续分析:
0040161A   |> \8B45 F0     mov eax,dword ptr ss:[ebp-10]
保存结果,EAX=9B25D092
0040161D   |.  50          push eax
0040161E   |.  68 54404000 push Brad_Sob.00404054            ;  ASCII "%lu"
00401623   |.  8D4D DC     lea ecx,dword ptr ss:[ebp-24]
00401626   |.  51          push ecx
00401627   |.  E8 52070000 call <jmp.&MFC42.#2818>
把9B25D092换成十进制的数后转化成字符串:2602946706
0040162C   |.  83C4 0C     add esp,0C
0040162F   |.  8D4D DC     lea ecx,dword ptr ss:[ebp-24]
00401632   |.  E8 79020000 call Brad_Sob.004018B0
00401637   |.  50          push eax                          ; /Arg1
00401638   |.  8D4D E8     lea ecx,dword ptr ss:[ebp-18]     ; |
0040163B   |.  E8 80020000 call Brad_Sob.004018C0            ; \Brad_Sob.004018C0
步入,省略代码
     004018CB   |.  8B4D FC     mov ecx,dword ptr ss:[ebp-4]      ; |
     取计算好的值
     004018CE   |.  8B11        mov edx,dword ptr ds:[ecx]        ; |
     取输入的假的注册码
      004018D0   |.  52          push edx                          ; |Arg1
     004018D1   |.  E8 0A000000 call Brad_Sob.004018E0
                                          ;        \Brad_Sob.004018E0
     两者对比。不等于则-1保存在EAX中

返回,
00401640   |.  85C0        test eax,eax
00401642   |.  0F85 FF0000>jnz Brad_Sob.00401747
不相等,则死。相等的话就继续往下。得到正确的提示窗口
00401648   |.  8D8D ACFEFF>lea ecx,dword ptr ss:[ebp-154]
0040164E   |.  E8 19070000 call <jmp.&MFC42.#540>
00401653   |.  C645 FC 03  mov byte ptr ss:[ebp-4],3
00401657   |.  6A 66       push 66
00401659   |.  8D8D ACFEFF>lea ecx,dword ptr ss:[ebp-154]
0040165F   |.  E8 02070000 call <jmp.&MFC42.#4160>
00401664   |.  B9 07000000 mov ecx,7
00401669   |.  BE 58404000 mov esi,Brad_Sob.00404058         ;  ASCII "Correct!!                     "
主要是算法很是麻烦,有很多的位运算和一些溢出后的取值等,我是十分菜,写不出注册机
还请各位高手指点一二,在此先谢过。
最后再总结下
注册码是:rockandtcl
对应的数值是:72 6F 63 6B 61 6E 64 74 63 6C
1.首先装入个初始值:81276345
2,加上了'r'的ASCII码的值:72这时候的值为812763B7
3,对注册名字符串位置数,做移8位处理,转为16进制,然后与相加的值做异或运算
4,r的位置在字符串[根据C的定义]为0,加上1(放着)
5,位置数与总长度相乘,然后取非,与(位置+1)相乘。
6,5的结果和3的结果相乘,如果溢出取后32位,保留数值
7, 继续第2步操作

第一做完后的结果是:7ED89C49,第二次:19627230,第三次:C0C64BD3,第四次:9FF19DF8
第五次:EB8766BB第六次:782CAAFE,第七次:8D7ACD8A,第八次:178D9C70,第九次:EDD33325,第十次:9B25D092
然后把9B25D092,转化成10进制的数值就是注册码:2602946706

所以
注册名为:rockandtcl
注册码为:2602946706

有错误的地方还请指出,谢谢

压缩包中有破文和这个Brad Soblesky.2


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 225
活跃值: (1211)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我第一个来顶
2006-3-29 09:20
0
雪    币: 269
活跃值: (51)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
分析的不错,我也曾粗略分析过,没你那么详细.再学习一下.
2006-3-29 12:37
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
4
提供一个注册机:
#include<iostream>
using namespace std;

void main()
{
        char szName[80];
        int nCode = 0x81276345;        //[ebp-10]
        int        nLength;                        //[ebp-1c]
        int n = 0;                                //[ebp-20]
        int eax, ecx;

        do
        {
                cout<<"请输入用户名(至少5位):";
                cin>>szName;
        } while(strlen(szName) < 5);
        nLength = strlen(szName);

        goto label;
        for (;;)
        {
                n++;
label:        if (n >= nLength) break;
                nCode += szName[n];
                ecx = n;
                ecx <<= 8;
                nCode ^= ecx;
                eax = n + 1;
                ecx = nLength;
                ecx *= n;
                ecx = ~ecx;
                eax *= ecx;
                nCode *= eax;
        }
        cout<<"注册码为:"<<(unsigned)nCode<<endl;
}
2006-3-29 13:38
0
雪    币: 222
活跃值: (100)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
最初由 WAKU 发布
提供一个注册机:
#include<iostream>
using namespace std;

void main()
........


非常感谢楼上的师兄
小弟真是功底太浅了,今天看了您的注册机十分佩服。看来得好好学下C++了。
学习
2006-3-29 17:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
小子不错啊
你的帖我每篇必看
嘿嘿
学习中...............
2006-3-29 19:34
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
7
最初由 rockandtcl 发布
非常感谢楼上的师兄
小弟真是功底太浅了,今天看了您的注册机十分佩服。看来得好好学下C++了。
学习


别用您,折我寿啊

我也是初学者,大家一起交流,共同进步吧
2006-3-29 21:15
0
游客
登录 | 注册 方可回帖
返回
//