首页
社区
课程
招聘
CRACKME算法分析(简单的anti-debugging)
发表于: 2006-7-26 19:15 9593

CRACKME算法分析(简单的anti-debugging)

2006-7-26 19:15
9593

【破文标题】CRACKME算法分析
【破文作者】逍遥风
【破解工具】OD 计算器
【保护方式】anti-debugging
----------------------------------------------------------------------
菜鸟偶得一点心得与大家分享
----------------------------------------------------------------------
综合简单的anti-debugging和算法分析,希望对大家有帮助。
话不多说,直接开始
用OD载入这个CRACKME ,根据字符串提示里的注册成功的信息,来到关键代码处
00447FA5  |.  E8 A2040000   call    0044844C                         ;  在这里下断点
00447FAA  |.  84C0          test    al, al
00447FAC  |.  75 14         jnz     short 00447FC2
00447FAE  |.  B8 FC7F4400   mov     eax, 00447FFC                    ;  error! incorrect serial!
00447FB3  |.  E8 38DBFFFF   call    00445AF0
00447FB8  |.  33C0          xor     eax, eax
00447FBA  |.  8983 34020000 mov     [ebx+234], eax
00447FC0  |.  EB 0A         jmp     short 00447FCC
00447FC2  |>  B8 20804400   mov     eax, 00448020                    ;  thanks for registering our product :)))!
下完断点后,F9运行程序,但是OD这时的反应却是“已经终止”
基本可以确定这个CRACKME有anti-debugging
重新载入程序,打开“当前模块中的名称”(Ctrl+N)
找到这个
名称位于 crackme2, 条目 213
地址=0044B500
区段=.idata
类型=输入    (已知)
名称=user32.IsDialogMessageA
1)解决它的
根据它来到这里:anti-debugging
0044833C   .  E8 5BFFFFFF   call    <jmp.&kernel32.IsDebuggerPresent>; [IsDebuggerPresent
00448341   .  85C0          test    eax, eax
00448343   .  74 0C         je      short 00448351
将这里的跳转改为:
00448343     /EB 0C         jmp     short 00448351
保存修改后,重新载入修改后的CRACKME。此时crackme就可以正常运行了。
2)分析算法
根据错误提示来到关键代码处
00447FA5  |.  E8 A2040000   call    0044844C                         ;  在这里下断点(关键CALL,跟进)
00447FAA  |.  84C0          test    al, al
00447FAC  |.  75 14         jnz     short 00447FC2
00447FAE  |.  B8 FC7F4400   mov     eax, 00447FFC                    ;  error! incorrect serial!
00447FB3  |.  E8 38DBFFFF   call    00445AF0                     
00447FB8  |.  33C0          xor     eax, eax
00447FBA  |.  8983 34020000 mov     [ebx+234], eax
00447FC0  |.  EB 0A         jmp     short 00447FCC
00447FC2  |>  B8 20804400   mov     eax, 00448020                    ;  thanks for registering our product :)))!
----------------------------------------------------------------------
跟进关键CALL
来到这里:
0044844C  /$  55            push    ebp
0044844D  |.  8BEC          mov     ebp, esp
省略一些代码。。。。。。
0044846D  |.  E8 6EB4FBFF   call    004038E0
00448472  |.  80BF F4020000>cmp     byte ptr [edi+2F4], 4            ;  注册名与4比较位数
00448479  |.  73 07         jnb     short 00448482                   ;  注册名必须大于4位
0044847B  |.  33DB          xor     ebx, ebx
0044847D  |.  E9 42010000   jmp     004485C4
00448482  |>  80BF F9030000>cmp     byte ptr [edi+3F9], 2D           ;  取注册码的第5位与2D比较(即判断注册码的第5位是否为“-”)
00448489  |.  75 09         jnz     short 00448494                   ;  不相等就跳向失败
0044848B  |.  80BF F4030000>cmp     byte ptr [edi+3F4], 9            ;  注册码等于9位吗?
00448492  |.  74 07         je      short 0044849B                   ;  注册码不为9位就失败
到这里,可以看出
1)注册名必须是大于4位
2)注册码必须是9位
   且必须是1234-6789这样的形式

重新载入,将注册码按格式输入,继续分析
省略一些代码。。。。。。
004484B7  |> /33C9  /xor     ecx, ecx
004484B9  |. |8A8C1>|mov     cl, [edi+edx+2F>;  取注册名每一位的ASCII码
004484C0  |. |014D >|add     [ebp-C], ecx    ;  累加注册名每一位的ASCII码结果设为A
004484C3  |. |42    |inc     edx             ;  没计算一次EDX+1
004484C4  |. |48    |dec     eax             ;  每计算一次EAX-1
004484C5  |.^\75 F0 \jnz     short 004484B7  ;  循环计算
这个循环计算的作用是累加注册名ASCII码的值
例如:注册名lovetc

累加结果为28D
累加完后来到这里:
004484CC  |.  BE 01>mov     esi, 1           ;  使ESI=1
004484D1  |>  8A5D >/mov     bl, [ebp-8]
004484D4  |.  8BCE  |mov     ecx, esi
004484D6  |.  81E1 >|and     ecx, 80000001
004484DC  |.  79 05 |jns     short 004484E3
004484DE  |.  49    |dec     ecx
004484DF  |.  83C9 >|or      ecx, FFFFFFFE
004484E2  |.  41    |inc     ecx
004484E3  |>  B8 05>|mov     eax, 5          ;  使EAX等于5
004484E8  |.  2BC6  |sub     eax, esi        ;  EAX=EAX-ESI(结果设为B)
004484EA  |.  8A840>|mov     al, [edi+eax+2F>;  取B对应位数的注册名的ASCII码
004484F1  |.  0AD8  |or      bl, al          ;  OR[第N-1次所取的注册码,Yn]
004484F3  |.  D2E3  |shl     bl, cl          ;  如果是偶数位就用OR运算的结果乘以2的1次方
004484F5  |.  8BCE  |mov     ecx, esi        ;  使ECX=ESI
004484F7  |.  8A45 >|mov     al, [ebp-C]     ;  取注册名ASCII码累加值的后两位
004484FA  |.  D2E0  |shl     al, cl          ;  A的后两位乘以2的N次方(结果设为D)
004484FC  |.  02D8  |add     bl, al          ;  (C+D的后两位)得到E
004484FE  |.  33C0  |xor     eax, eax        ;  EAX清零
00448500  |.  8AC3  |mov     al, bl          ;  使AL等于计算结果E
00448502  |.  B9 1A>|mov     ecx, 1A         ;  使ECX等于固定值0x1A
00448507  |.  33D2  |xor     edx, edx        ;  EDX清零
00448509  |.  F7F1  |div     ecx             ;  EAX中的值除以ECX中的值,商放进EAX余数放进EDX
0044850B  |.  80C2 >|add     dl, 41          ;  所得的余数加上定值0x41,得到结果F
0044850E  |.  8BDA  |mov     ebx, edx        ;  使EBX=EDX(结果F放进EBX中)
00448510  |.  8A843>|mov     al, [edi+esi+3F>;  取注册码第一位的ASCII码
00448517  |.  32D8  |xor     bl, al          ;  计算结果F与注册码第一位的ASCII码做XOR运算
00448519  |.  74 07 |je      short 00448522
0044851B  |.  33DB  |xor     ebx, ebx        ;  不相等就将EBX清零
0044851D  |.  E9 A2>|jmp     004485C4        ;  跳向失败
00448524  |.  8A843>|mov     al, [edi+esi+2F4]   ;  按次取注册名每一位的ASCII码
0044852B  |.  F7EE  |imul    esi                 ;  ASCII码乘以计算次数
0044852D  |.  0145 >|add     [ebp-8], eax        ;  相乘后的积累加(作为Yn)
00448530  |.  46    |inc     esi             ;  每计算一次ESI中的值加1
00448531  |.  83FE >|cmp     esi, 5          ;  计算5次就结束
00448534  |.^ 75 9B \jnz     short 004484D1  ;  循环计算
由于注册码是1234-6789这样的形式,这段代码就是计算注册码的第一部分(即1234对应的部分)

计算的过程为:以注册名lovetc为例:

注意:由于计算过程奇偶有关,所以须分两种情况举例
1)先取定值5,减去计算次数1(第一次计算),得到结果4。
2)在注册名中取4对应的字符(注册名的第4位)e对应的ASCII码65,OR(65,0)=65
                                                                  
3)因为4是偶数,所以就用65  *  2  =  CA  ,取累加结果28D的后两位8D
4)8D乘以2的N=1次方等于11A,取后两位1A
5) CA  +  1A  =  E4 ,E4/1A=8,余数为14,14+41=55,55对应的字母是U
所以注册码第1位就是U:
1)在一次取定值5,减去计算次数2(第二次计算),得到结果3。
2)在注册名中取3对应的字符(注册名的第3位)v对应的ASCII码76,OR(76,6C)=7E
                                                                     |--------n=1,Y1=6C
3)因为3是奇数,取累加结果28D的后两位8D
4)8D乘以2的N=2次方等于234,取后两位34
5)34  +  7E  =  B2,B2/1A,余数为16,16+41=57,57对应的字母是W
所以注册码第2位是W
依次类推:注意累加部分Yn的变化
Y1=6C*1,                       Y2=6F*2+6C=14A(取后两位4A,就是Y2)
   |--|-注册码第一位得ASCII码      |--|--|----------注册码第二位得ASCII码
      |----计算次数                   |--|-------------计算次数
                                         |----------------Y1

最后:得到注册码第一部分是UWSG           

开始计算第2部分
00448536  |.  C745 >mov     dword ptr [ebp-8],>;  取定值0xABCD作为一个字符串
0044853D  |.  BE 01>mov     esi, 1             ;  使ESI等于1
00448542  |>  8A5D >/mov     bl, [ebp-8]       ;  取定值0xABCD中取后两位。设为Z(Z1=CD)
00448545  |.  8BCE  |mov     ecx, esi
00448547  |.  81E1 >|and     ecx, 80000001
0044854D  |.  79 05 |jns     short 00448554
0044854F  |.  49    |dec     ecx
00448550  |.  83C9 >|or      ecx, FFFFFFFE
00448553  |.  41    |inc     ecx
00448554  |>  8B45 >|mov     eax, [ebp-4]      ;  使EAX等于注册名的位数
00448557  |.  2BC6  |sub     eax, esi          ;  EAX=EAX-ESI
00448559  |.  8A840>|mov     al, [edi+eax+2F4] ;  取所得的差对应的注册名的ASCII码
00448560  |.  0AD8  |or      bl, al            ;  OR(注册名的ASCII码,Zn)
00448562  |.  D2E3  |shl     bl, cl            ;  如果是奇数位就用OR运算结果乘以2的一次方(结果设为F)
00448564  |.  8BCE  |mov     ecx, esi
00448566  |.  8B45 >|mov     eax, [ebp-C]      ;  取注册名的累加值(即A)
00448569  |.  D3E8  |shr     eax, cl           ;  A除以2的n次方(商设为G)
0044856B  |.  02D8  |add     bl, al            ;  (F+G的后两位),结果设为H
0044856D  |.  33C0  |xor     eax, eax
0044856F  |.  8AC3  |mov     al, bl            ;  使AL等于H的后两位
00448571  |.  B9 1A>|mov     ecx, 1A           ;  使ECX等于定值0x1A
00448576  |.  33D2  |xor     edx, edx
00448578  |.  F7F1  |div     ecx               ;  EAX中的值除以ECX中的值,商放进EAX余数放进EDX
0044857A  |.  80C2 >|add     dl, 41            ;  所得余数加上定值0x41。得到结果X
0044857D  |.  8BDA  |mov     ebx, edx          ;  使EBX等于结果X
0044857F  |.  8D46 >|lea     eax, [esi+5]
00448582  |.  8A840>|mov     al, [edi+eax+3F4] ;  取注册码对应位数的字符
00448589  |.  32D8  |xor     bl, al            ;  比较结果X与对应位数的注册码
0044858B  |.  74 04 |je      short 00448591    ;  相等就继续比较下一位
0044858D  |.  33DB  |xor     ebx, ebx
0044858F  |.  EB 33 |jmp     short 004485C4
00448591  |>  8B45 >|mov     eax, [ebp-4]      ;  使EAX等于注册名位数
00448594  |.  83E8 >|sub     eax, 4            ;  EAX=EAX-4
00448597  |.  03C6  |add     eax, esi          ;  计算次数与(注册名-4)所得得差相加
00448599  |.  0FB68>|movzx   eax, byte ptr [ed>;  在注册名中取对应位数得字符
004485A1  |.  F7EE  |imul    esi               ;  对应字符得ASCII码乘以计算次数
004485A3  |.  0145 >|add     [ebp-8], eax      ;  第N次计算得结果与第N-1次计算的结果相加(即得到Zn)
004485A6  |.  46    |inc     esi               ;  每计算1次ESI+1
004485A7  |.  83FE >|cmp     esi, 5            ;  计算5次
004485AA  |.^ 75 96 \jnz     short 00448542    ;  循环计算
以注册名lovetc为例:

注意:由于计算过程奇偶有关,所以须分两种情况举例

1)取字符串ABCD,取后两位CD作为Z1。6-1=5(注册名位数减去计算次数),取注册名第5位t对应的ASCII码74,  OR(74,CD)=FD
2)因为5是奇数,所以FD  *  2  =  1FA ,取后两位FA,
3)取注册名累加值28D,除以2,商为146,取后两位46
4)46  +  FA  =  140,取后两位40,40/1A=2,余数是C,C+41=4D,4D对应的字母是M
所以注册码第2部分
第一位是M
注意Zn的变化:Z1=CD,
6-4+1=3,注册名第3位V对应ASCII码76乘以计算次数N=1,得76。76+ABCD=AB43,所以Z2=43
|-|-|----计算次数
  | |
  |-|-----定值4
    |
    |------计算次数

依次类推:得到Zn
计算第2位:
1)6-2=4(注册名位数减去计算次数),取注册名第4位e对应的ASCII码65,OR(65,43)= 67
2)因为4是偶数,所以取注册名累加值28D,除以2*2,商为A3。
3)A3  +  67  =  10A, 取后两位0A,A/1A,余数是A,A+41=4B,4D对应的字母是K
所以所以注册码第2部分
第二位是K
依次类推:
最后可以得出注册码第2部分是MKBV

所以
注册名lovetc
注册码UWSG-MKBV

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

【版权声明】本文只位交流,转载清保留作者及文章完整性


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
2
好文章,收藏~~
2006-7-26 20:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习了逍遥风兄...支持!
2006-7-26 23:08
0
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
4
好文,学习了.
2006-7-26 23:53
0
雪    币: 309
活跃值: (15)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
来跟着逍遥兄学习来拉~~~
2006-7-27 00:34
0
雪    币: 372
活跃值: (31)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
6
支持。。。。
2006-7-27 11:13
0
雪    币: 157
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
分析很详细!!!!

以后!大侠们出的教程!在后面注释越清楚越好!

方便新手学习嘛!!!

谢谢了!
2006-7-27 12:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
支持逍遥风兄!
2006-7-28 10:26
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
okpj:您好
     我是个初中化学教师,以前用您破解的《轻松工具箱7.8》很好,其中化学式自动识别功能弱点,现在已有《轻松工具箱8.2》此项功能很强,想劳烦您给做个注册机,谢谢!!
e-mail:ahhnztz@126.com
QQ:511181363

敬请:版主手下留情!谢谢
2006-7-28 15:58
0
雪    币: 1301
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
版主还真细心,后面注释的很详悉,方便我们这些菜鸟学习。希望各位高手出教程也能像你一样把后面注释越清楚越好。
2006-8-8 10:40
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
[QUOTE]..............................................................
00448472  |.  80BF F4020000>cmp     byte ptr [edi+2F4], 4            ;  注册名与4比较位数
00448479  |.  73 07         jnb     short 00448482                   ;  注册名必须大于4位
0044847B  |.  33DB          xor     ebx, ebx
0044847D  |.  E9 42010000   jmp     004485C4
00448482  |>  80BF F9030000>cmp     byte ptr [edi+3F9], 2D           ;  取注册码的第5位与2D比较(即判断注册码的第5位是否为“-”)
00448489  |.  75 09         jnz     short 00448494                   ;  不相等就跳向失败
0044848B  |.  80BF F4030000>cmp     byte ptr [edi+3F4], 9            ;  注册码等于9位吗?...........
  这里    00448472  cmp byte ptr [edi+2f4],4    和   00448482 cmp byte ptr [edi+3f9],2d.  两个指令,前者指取"注册名共有几位",后者则"指注册码的具体的某一位"这两个指令在没有注解时就无法分别呀..哪是通过看信息窗口和堆栈窗口的数据变化来分别的吗?哪位解析一下呀.笨鸟,郁闷.
2006-8-8 21:44
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
后面挺复杂的,对高手而言当然略显简单啊
2006-8-8 21:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
请问一下
00448482  |>  80BF F9030000>cmp     byte ptr [edi+3F9], 2D           ;  取注册码的第5位与2D比较(即判断注册码的第5位是否为“-”)

是如何看出来的?
2006-8-8 22:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
最初由 flyin 发布
请问一下
00448482 |> 80BF F9030000>cmp byte ptr [edi+3F9], 2D ; 取注册码的第5位与2D比较(即判断注册码的第5位是否为“-”)

是如何看出来的?

   我也有同样地困惑,但我在注册码上写入"333353333"时,运行到此处时信息窗口有"5"显示,从新载入程序在注册码上写入"111181111"时,运行到此处时信息窗口有'8'显示.同理写入"578943210"有"4"显示.....这里显示的"5" "8" "4"都在注册码的第5位. 而"-"的ASCII码为"2D" 逆向推出第5位为"-"
..我是这样理解的,不知对否.
   作者能否解析一下呀......
2006-8-8 22:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
后来我也想了想,应该就是这样推的吧。。。
2006-8-8 23:45
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
支持版主..

大家好..我是每一次来这里...有很多东西还不懂...

请多指教...

谢谢...
2006-8-11 09:48
0
雪    币: 210
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
00448472  |.  80BF F4020000>cmp     byte ptr [edi+2F4], 4            ;  注册名与4比较位数

如何得知edi+2F4即为位数 edi+2F5为注册码的?。。昏倒
2006-8-13 15:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
studying
2006-8-20 19:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
学习~~~~好好研究一下:)
2006-8-21 16:59
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
我们可以通过查看内存,当程序执行到
00448472  |.  80BF F4020000>cmp     byte ptr [edi+2F4],
当我们不知道这里是什么的时候可以看一下这里的内存地址,就是
[edi+2F4]的内容,可以发现,这里结构正好是
用户名位数+用户名
同理看[edi+3F4]的内容是
注册码位数+注册码
2006-8-23 16:05
0
游客
登录 | 注册 方可回帖
返回
//