首页
社区
课程
招聘
[原创]算法分析初步
发表于: 2006-8-6 18:20 6588

[原创]算法分析初步

2006-8-6 18:20
6588

【破文标题】算法分析初步
【破文作者】逍遥风
【破解工具】OD,计算器
【破解平台】WINXP
【破解声明】由于这个CRACKME的算法的关键只有一步加法运算,所以只需分析出加法就可以了
----------------------------------------------------------------------
                     今天的任务就是让大家大概了解一下简单的算法分析是如何得来的。
首先用OD载入这个CRACKME,发现加了壳。根据经验判断应该是UPX的壳,脱壳很简单,几下就脱掉了
它的马甲。这不用关心因为重点不是脱壳所以这部分一笔带过。用OD载入脱壳后的CRACKME。
根据错误提示很容易找到关键代码。

1)整体感知:
先看一下整个的流程:
00447EAC  |.  8BF0          mov     esi, eax
00447EAE  |.  33C0          xor     eax, eax
00447EB0  |.  55            push    ebp
00447EB1  |.  68 A17F4400   push    00447FA1
00447EB6  |.  64:FF30       push    dword ptr fs:[eax]
00447EB9  |.  64:8920       mov     fs:[eax], esp
00447EBC  |>  8D55 F0       /lea     edx, [ebp-10]
00447EBF  |.  8B86 D0020000 |mov     eax, [esi+2D0]
00447EC5  |.  E8 36C2FDFF   |call    00424100                        ;  取注册名进行计算
00447ECA  |.  8B55 F0       |mov     edx, [ebp-10]                   ;  使EDX等于注册名
00447ECD  |.  8D45 FC       |lea     eax, [ebp-4]
00447ED0  |.  E8 EFBCFBFF   |call    00403BC4
00447ED5  |.  8B45 FC       |mov     eax, [ebp-4]                    ;  使EAX等于注册名
00447ED8  |.  E8 DFBCFBFF   |call    00403BBC                        ;  取注册名位数
00447EDD  |.  83F8 06       |cmp     eax, 6                          ;  注册名位数与6比较
00447EE0  |.^ 7C DA         \jl      short 00447EBC
00447EE2  |.  8D45 F8       lea     eax, [ebp-8]
00447EE5  |.  BA B87F4400   mov     edx, 00447FB8                    ;  xxxxxx
00447EEA  |.  E8 E5BAFBFF   call    004039D4
00447EEF  |.  BB 01000000   mov     ebx, 1                           ;  使EBX等于1,开始算法计算
00447EF4  |>  8D45 F8       /lea     eax, [ebp-8]
00447EF7  |.  E8 90BEFBFF   |call    00403D8C                        ;  用计算结果替换固定字符串中的X
00447EFC  |.  8B55 FC       |mov     edx, [ebp-4]
00447EFF  |.  8A541A FF     |mov     dl, [edx+ebx-1]                 ;  取注册名每一位的ASCII码
00447F03  |.  80C2 05       |add     dl, 5                           ;  注册名每一位的ASCII码加上5
00447F06  |.  885418 FF     |mov     [eax+ebx-1], dl                 ;  将计算的结果保存,并转换成对应的字母
00447F0A  |.  43            |inc     ebx                             ;  每计算一次EBX+1
00447F0B  |.  83FB 07       |cmp     ebx, 7                          ;  计算次数与7比较
00447F0E  |.^ 75 E4         \jnz     short 00447EF4                  ;  循环计算
00447F10  |.  8D45 F4       lea     eax, [ebp-C]                     ;  使EAX等于循环计算的结果
00447F13  |.  BA C87F4400   mov     edx, 00447FC8                    ;  hey, u r realy good!\n\nsend ur solution to moon.86@gmx.de!
00447F18  |.  E8 B7BAFBFF   call    004039D4
00447F1D  |.  8D55 EC       lea     edx, [ebp-14]
00447F20  |.  8B86 EC020000 mov     eax, [esi+2EC]
00447F26  |.  E8 F9C4FFFF   call    00444424                         ;  取输入的注册码
00447F2B  |.  8B55 EC       mov     edx, [ebp-14]                    ;  使EDX等于输入的注册码
00447F2E  |.  8B45 F8       mov     eax, [ebp-8]                     ;  使EAX等于真正的注册码
00447F31  |.  E8 96BDFBFF   call    00403CCC                         ;  真假注册码比较。
00447F36  |.  75 26         jnz     short 00447F5E                   ;  不相等就跳向失败
----------------------------------------------------------------------
   

2)各个击破
以下面这段简单的代码进行说明:(省略了一些无关的代码和操作,直接来到算法的核心部分:)
00447EE2  |.  8D45 F8       lea     eax, [ebp-8]
00447EE5  |.  BA B87F4400   mov     edx, 00447FB8                ;  xxxxxx(固定字符串)
00447EEA  |.  E8 E5BAFBFF   call    004039D4            
00447EEF  |.  BB 01000000   mov     ebx, 1                       ;  使EBX等于1,开始算法计算
00447EF4  |>  8D45 F8       /lea     eax, [ebp-8]
00447EF7  |.  E8 90BEFBFF   |call    00403D8C                    ;  用计算结果替换固定字符串中的X
00447EFC  |.  8B55 FC       |mov     edx, [ebp-4]
00447EFF  |.  8A541A FF     |mov     dl, [edx+ebx-1]             ;  取注册名每一位的ASCII码
00447F03  |.  80C2 05       |add     dl, 5                       ;  注册名每一位的ASCII码加上5
00447F06  |.  885418 FF     |mov     [eax+ebx-1], dl             ;  将计算的结果保存,并转换成对应的字母
00447F0A  |.  43            |inc     ebx                         ;  每计算一次EBX+1
00447F0B  |.  83FB 07       |cmp     ebx, 7                      ;  计算次数与7比较
00447F0E  |.^ 75 E4         \jnz     short 00447EF4              ;  循环计算
00447F10  |.  8D45 F4       lea     eax, [ebp-C]                 ;  使EAX等于循环计算的结果
现在、就简单说说这个算法的分析过程是如何得来的。
----------------------------------------------------------------------
                        这个算法的可以归结为3个问题:
1)取注册名的ASCII码
2)注册名ASCII码加5,并将计算结果转换成对应的字符
3)用计算得到的字符替换固定字符串中的X
下面开始详细说说,上面的计算过程是怎样得来的:
         问题1:
  为什么00447EFF处的代码的作用是“取注册名每一位的ASCII码”
我们先运行到这段代码上,这时注意OD中各个窗口的情况,尤其是寄存器窗口(如图1)
再用F8单步走过这里,注意寄存器窗口的值变化了,信息窗口也出现了提示(如图2,3)

在这里实验用的注册名是lovetc,l对应的ASCII码就是6C。当步过这句代码时寄存器EDX中的值变为了******6C
信息窗口也出现"dl=6C('l')"的字样。
所以就可以确定这句代码的作用就是取注册名第一位的ASCII码。
注意:现在只能确定是取注册名第一位的ASCII码,还不能确定是取注册码每一位的ASCII码。
         
        问题2:
  为什么00447F03处的代码的作用是“注册名每一位的ASCII码加上5”
这句代码"add dl 5",结合上一个问题中信息窗口的提示:dl=6C('l')
也就是说:将DL中的值与5相加 ,而DL中的值等于6C,6C又是注册名第一位的ASCII码。
那么就可以猜测一下,打开WINDOWS自带的计算器。计算6C+5=71。
结合这句代码,可以猜测得出经过计算DL中的值应该等于71。现在F8步过这句代码,
注意信息窗口和寄存器窗口的情况(如图4,5)

寄存器窗口中的EDX中的值变成了******71,信息窗口的内容也提示"dl=71('q')"
所以就可以得出结论:这句代码作用是注册名第一位的ASCII码加上5。

         问题3:
  为什么00447EF7处的代码的作用是“用计算结果替换固定字符串中的X”
首先:还是运行到00447EF7这个位置,注意各个窗口的情况以寄存器窗口为例(如图6)。
再F8步过这个CALL,再以次观察寄存器窗口(如图7)
字符串“XXXXXX”现在变成了“qXXXXX”。结合上个问题的结论,71既是加法计算的结果
又是字母q对应的ASCII码。
所以可以确定这个CALL的作用就是用计算的结果对应的字符替换字符串中的X。

解决完了这3个问题,还有一点需要注意,现在得出得结论都是对于单个字符而言的,是否适用
于整个循环过程呢?也就是说:“取注册名第一位的ASCII码”
是否可以推广成“取注册码每一位的ASCII码”
这个时候就要做进一步的跟踪分析,注意各个窗口值的变化。方法和上文中提到的一样。
----------------------------------------------------------------------

现在经过了算法的计算,就该进行真假注册码的比较了,这里又提供了依次巩固练习的机会
00447F26  |.  E8 F9C4FFFF   call    00444424                     ;  取输入的注册码
00447F2B  |.  8B55 EC       mov     edx, [ebp-14]                ;  使EDX等于输入的注册码
00447F2E  |.  8B45 F8       mov     eax, [ebp-8]                 ;  使EAX等于真正的注册码
00447F31  |.  E8 96BDFBFF   call    00403CCC                     ;  真假注册码比较。
00447F36  |.  75 26         jnz     short 00447F5E               ;  不相等就跳向失败
。。。
00447F65  |.  BA 1C804400   mov     edx, 0044801C                ;  u fuckin noob!
问题1
1)为什么说00447F2B处代码的作用是“使EDX等于输入的注册码”
2)为什么说00447F2E处代码的作用是“使EAX等于真正的注册码”
这两个问题现在已经可以自己动手,轻松解决了。

----------------------------------------------------------------------
一篇班门弄斧的文章,大家见笑了。
----------------------------------------------------------------------
【版权声明】本文只为交流,转载请保留作者及文章完整性


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (10)
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
分析的好!!复制下来学习!!
2006-8-6 22:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
usa
3
支持并学习!
2006-8-6 22:42
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错啊,很适合新手看不错
2006-8-7 01:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
当用户名小于6的时候会复制一次用户名看是否大于6,比如我输入flyin,在前面的运算中会变成flyinflyin再进入计算注册码,请问一下这如何在VB中实现?
2006-8-7 13:57
0
雪    币: 2384
活跃值: (766)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
6
最初由 flyin 发布
当用户名小于6的时候会复制一次用户名看是否大于6,比如我输入flyin,在前面的运算中会变成flyinflyin再进入计算注册码,请问一下这如何在VB中实现?

Dim Name As String
Name = Text1.Text
While Len(Name) < 6 '直到Name长度等于大于6位。
  Name = Name & Text1.Text
Wend
2006-8-7 18:06
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
多谢。。。
2006-8-7 19:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这才是我们菜鸟真切需要的呀.......看起来"老师"没有白叫呀.还要多叫呀.不然的话,老师好"吝色"呀.哈哈
2006-8-7 19:04
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
能否把此CrackMe脱壳后上传来呀,走还不会,无法跑呀.
2006-8-8 07:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错的菜鸟教材,顶...........
2006-8-8 10:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
能否把脱壳的详细过程补上呀,不然无法实习呀
2006-8-9 06:44
0
游客
登录 | 注册 方可回帖
返回
//