首页
社区
课程
招聘
[原创]第一次亲密接触_Creakme Analysis
发表于: 2009-2-24 11:22 11017

[原创]第一次亲密接触_Creakme Analysis

2009-2-24 11:22
11017

【文章作者】: moonife
【读者对象】:刚入门:有C,asm的一些基础,至少了解windows编程,掌握常用破解工具的基本操作(ps:我认为既然把文章贴出来了,目的就是希望读者有所得,不会是拿出来秀一下,所以最好有个比较客观的读者对象定位,节约读者时间,仅是个人观点)
【文章难度】:2/10(我自己定义的)
【作者邮箱】: moonife@163.com
【作者QQ号】: 765496322
【软件名称】: codefantasy CrackMe2.exe
【软件大小】: 48.5KB
【下载地址】: 自己搜索(我是在光盘中找到的,还没有上传权限,努力吧!) 
【加壳方式】: 无壳
【保护方式】: 注册名+序列号+明码比较
【编写语言】: Borland Delphi 6.0 - 7.0 
【使用工具】: ollydbg+peid + Microsoft Visual C++ 6.0
【操作平台】: xp-sp3
【软件介绍】: 一个简单的creakme,入门学习用!
【作者说明】: 这是我写的第一个creakme分析文章,也是我第一次在看雪发表文章,在这里我还想谈一下我的感受,还请多多忍耐了!我接触这个加密与解密差不多有一年了吧,但都仅仅只是停留在了解这么一个层次上,没有发生过什么亲密接触了。真正开始学是近一两个月的事,但我以前有学过c,asm的一些知识,但都是浅薄的一点了,感觉人还是浮躁了一点.今年一月份买了kanxue大哥以及诸位大虾的出的《加密与解密》,用春晚老毕的话说是:内容很不错,写得很不错!不过对我来说是有点难了!春节放假回去鼓捣了一阵,今天终于写了第一篇破文,我的心情是从多云转晴了!不说了,不说了,什么时候把感想重写一篇把,还扯不完了还,都快跑偏了!最后我要感谢pediy,感谢cctv,mtv............还是F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7.....................实际~@~
------------------------------------------------------分析过程------------------------------------------------------------
一 收集信息:PEID查壳, Borland Delphi 6.0 - 7.0,无壳

二 踩点:运行程序,填写注册资料:name:moonife,serial:ggggggggggggg,注册,没反应,没有错误提示,也就是说不能简单的用MessageBox设断和查找错误提示字符串快速定位关键注册算法,但是我们可以查找注册成功提示信息,如果它没有经过特殊处理的话

三 动态调试分析:ollydbg载入,思考:我们可以采取什么方法快速定位关键注册代码呢?针对这个Creakme可以用以下几个方法:A 查找注册成功提升信息来定位(用 ultra reference string 插件);B Ctrl+N看输入表,有熟悉的GetDlgItemTextA,就可以bp GetDlgItemTextA 了 或 find references to import; C 如果上述两个方法还不行的话,我们就下WM_LBUTTONUP消息断点;D 还有其他许多方法,只是目前我也不会了,我在这里就当抛砖引玉了,还请诸位大虾赐教了!这个程序用以上任一方法都可以,建议每个都试一下,当做练习。
-----------------定位到的关键代码:
00408D8C  |> \68 FF000000   push    0FF                              ; /Count = FF (255.); Case 3EA of switch 00408D6B
00408D91  |.  68 A0A24000   push    0040A2A0                         ; |Buffer = codefant.0040A2A0
00408D96  |.  68 F2030000   push    3F2                              ; |ControlID = 3F2 (1010.)
00408D9B  |.  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
00408D9E  |.  50            push    eax                              ; |hWnd
00408D9F  |.  E8 90B9FFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00408DA4  |.  8D45 B4       lea     eax, dword ptr [ebp-4C]
00408DA7  |.  BA A0A24000   mov     edx, 0040A2A0                    ;  ASCII "moonife"
00408DAC  |.  B9 FF000000   mov     ecx, 0FF
00408DB1  |.  E8 BAAAFFFF   call    00403870
00408DB6  |.  837D B4 00    cmp     dword ptr [ebp-4C], 0
00408DBA  |.  0F84 9E000000 je      00408E5E
00408DC0  |.  68 FF000000   push    0FF                              ; /Count = FF (255.)
00408DC5  |.  68 A0A34000   push    0040A3A0                         ; |Buffer = codefant.0040A3A0
00408DCA  |.  68 F3030000   push    3F3                              ; |ControlID = 3F3 (1011.)
00408DCF  |.  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
00408DD2  |.  50            push    eax                              ; |hWnd
00408DD3  |.  E8 5CB9FFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00408DD8  |.  8D45 AC       lea     eax, dword ptr [ebp-54]
00408DDB  |.  BA A0A24000   mov     edx, 0040A2A0                    ;  ASCII "moonife"
00408DE0  |.  B9 FF000000   mov     ecx, 0FF
00408DE5  |.  E8 86AAFFFF   call    00403870
00408DEA  |.  8B45 AC       mov     eax, dword ptr [ebp-54]          ;  eax指向用户名
00408DED  |.  8D55 B0       lea     edx, dword ptr [ebp-50]          ;  真注册码存放地址
00408DF0  |.  E8 BFFCFFFF   call    00408AB4                         ;  计算真注册码的算法call,F7跟进去
-----------------注册码关键算法分析开始(部分省略):
00408B01  |> /8B4D F4       /mov     ecx, dword ptr [ebp-C]          ;  1:ecx=2 2:ecx=4
00408B04  |. |8A4437 FF     |mov     al, byte ptr [edi+esi-1]        ;  从用户名的第一个字符开始取并进行计算
00408B08  |. |24 C0         |and     al, 0C0                         ;  al=al&0xc0
00408B0A  |. |25 FF000000   |and     eax, 0FF                        ;  eax不变
00408B0F  |. |D3E8          |shr     eax, cl                         ;  eax右移动2位
00408B11  |. |0845 F3       |or      byte ptr [ebp-D], al            ;  1:【ebp-d】=0012fa5f=10  2:10or4=14
00408B14  |. |8345 F4 02    |add     dword ptr [ebp-C], 2            ;  【ebp-c】=0012fa60=4  2:6
00408B18  |. |8D45 F8       |lea     eax, dword ptr [ebp-8]          ;  eax=0012fa64  ecx=2 edx=0 si=1
00408B1B  |. |E8 58AFFFFF   |call    00403A78                        ;  可能是取eax=*(eax)ecx=0 edx=eax=00900954
00408B20     |8A5437 FF     mov     dl, byte ptr [edi+esi-1]         ;  取用户名的第一个字符(dl)=g edx=00900967  ‘g’=67
00408B24  |. |80E2 3F       |and     dl, 3F                          ;  edx=00900927
00408B27  |. |81E2 FF000000 |and     edx, 0FF                        ;  edx=00000027
00408B2D  |. |8B0D 98A24000 |mov     ecx, dword ptr [40A298]         ;  计算用户名关键字符串ASCII ;指向字符串                          "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz~#%&*+-"
00408B33  |. |8A1411        |mov     dl, byte ptr [ecx+edx]          ;  edx=00000068
00408B36  |. |885418 FF     |mov     byte ptr [eax+ebx-1], dl        ;  dl=68 ('h')  ds:【00900955】=68
00408B3A  |. |46            |inc     esi                             ;  esi=sei+1=2
00408B3B  |. |43            |inc     ebx                             ;  ebx=ebx+1=3
00408B3C  |. |83FB 04       |cmp     ebx, 4                          ;  ebx<=4 所以跳转 计算出三位后开始跳转
00408B3F  |. |7E 36         |jle     short 00408B77
00408B41  |. |8D45 F8       |lea     eax, dword ptr [ebp-8]          ;  *(eax)=放计算出来的注册码的地址(10090054+1)
00408B44  |. |E8 2FAFFFFF   |call    00403A78                        ;  可能是取eax=*(eax)ecx=0 edx=eax=00900954
00408B49  |. |33D2          |xor     edx, edx                        ;  edx=0
00408B4B  |. |8A55 F3       |mov     dl, byte ptr [ebp-D]            ;  dl=15 计算第一个字符的关键
00408B4E  |. |8B0D 98A24000 |mov     ecx, dword ptr [40A298]         ;  CrackMe2.00407FE0
00408B54  |. |8A1411        |mov     dl, byte ptr [ecx+edx]          ;  dl=(00407fe0+edx)=50 'p'
00408B57  |. |8810          |mov     byte ptr [eax], dl              ;  注册码的第一个字符
00408B59  |. |C645 F3 00    |mov     byte ptr [ebp-D], 0             ;  重置【ebp-d】为0
00408B5D  |. |BB 02000000   |mov     ebx, 2                          ;  ebx=2
00408B62  |. |C745 F4 02000>|mov     dword ptr [ebp-C], 2            ;  重置【ebp-c】为2
00408B69  |. |8B45 FC       |mov     eax, dword ptr [ebp-4]          ;  eax=0012fa8c
00408B6C  |. |8B55 F8       |mov     edx, dword ptr [ebp-8]          ;  计算出来注册码的前四个字符
00408B6F  |. |E8 30ADFFFF   |call    004038A4                        ;  ecx=2  edx=0
00408B74  |. |8B45 FC       |mov     eax, dword ptr [ebp-4]
00408B77  |> |8BC7           mov     eax, edi                        ;  eax=edi=00900934=输入的用户名
00408B79  |. |E8 1EADFFFF   |call    0040389C                        ;  返回输入的用户名的字符个数
00408B7E  |. |3BF0          |cmp     esi, eax                        ;  esi=2 eax=0x13
00408B80  |.^\0F8E 7BFFFFFF \jle     00408B01
00408B86  |.  83FB 02       cmp     ebx, 2
00408B89  |.  74 52         je      short 00408BDD
00408B8B  |.  8D45 F8       lea     eax, dword ptr [ebp-8]
00408B8E  |.  E8 E5AEFFFF   call    00403A78
00408B93  |.  C64418 FF 2E  mov     byte ptr [eax+ebx-1], 2E         ;  最后一位用’.’填充
00408B98  |.  8D45 F8       lea     eax, dword ptr [ebp-8]
00408B9B  |.  E8 D8AEFFFF   call    00403A78
00408BA0  |.  33D2          xor     edx, edx
00408BA2  |.  8A55 F3       mov     dl, byte ptr [ebp-D]
00408BA5  |.  8B0D 98A24000 mov     ecx, dword ptr [40A298]          ;  CrackMe2.00407FE0
00408BAB  |.  8A1411        mov     dl, byte ptr [ecx+edx]
00408BAE  |.  8810          mov     byte ptr [eax], dl
00408BB0  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
00408BB3  |.  8B55 F8       mov     edx, dword ptr [ebp-8]
00408BB6  |.  E8 E9ACFFFF   call    004038A4
00408BBB  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
00408BBE  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
00408BC1  |.  8B00          mov     eax, dword ptr [eax]
-----------------------注册码关键算法分析结束

00408DF5  |.  8B45 B0       mov     eax, dword ptr [ebp-50]          ;  此时eax指向计算出来的serial,也可以做内存注册机
00408DF8  |.  50            push    eax
00408DF9  |.  8D45 A8       lea     eax, dword ptr [ebp-58]
00408DFC  |.  BA A0A34000   mov     edx, 0040A3A0                    ;  ASCII "gggggggggggg"
00408E01  |.  B9 FF000000   mov     ecx, 0FF
00408E06  |.  E8 65AAFFFF   call    00403870
00408E0B  |.  8B55 A8       mov     edx, dword ptr [ebp-58]
00408E0E  |.  58            pop     eax
00408E0F  |.  E8 60ABFFFF   call    00403974                         ;  比较注册码是否相等
00408E14  |.  75 48         jnz     short 00408E5E                   ;  关键比较 这里可以nop掉或取反实现爆破
00408E16  |.  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408E18  |.  68 5C8F4000   push    00408F5C                         ; |注册提示
00408E1D  |.  68 688F4000   push    00408F68                         ; |恭喜您,注册码正确!
00408E22  |.  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
00408E25  |.  50            push    eax                              ; |hOwner
00408E26  |.  E8 41B9FFFF   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
-----------------------代码分析结束

四 总结:这个creakme注册过程思路清晰,计算serial的算法也比较简单,具体请看keygen源码

五 浅薄的经验分享:当我们定位到关键代码处的时候,一般摆在我们目前很多个Call,但是关键的call一般就那么两三个,切不要一路F7下去,那样往往会迷路的!这时我们可以先F8路过,路过前注意前两三行代码的执行,看或猜传什么参数进去了,路过后看寄存器的值有何变化或如果参数是指针,地址,堆栈的话看这些地址上的数据有何变化,然后我们就可以判定或猜出这个call是干嘛的了,接下来就不说了,靠你自己尽情的发挥了,good luck!

---------------------------------------------------keygen_C源码-----------------------------------------------------------
//kengen for codefantasy CrackMe
//用dbp_d等这样的变量是因为可以较快的照原算法写出注册机,
//对于我们初学者它还是个不错的想法了,有时间再优化
#include<stdio.h>
#include<string.h>

int main()
{
char key_word[]="23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz~#%&*+-";
char in_name[50]="";
char serial[50]="";
int ebp_d=0,ecx=2,eax=0,edx=0,esi=1,ebx=2,name_length=0,base=0;
printf("please input you name:");
scanf("%s",in_name);
name_length=strlen(in_name);
while(esi<=name_length)
{
ebx=2,ecx=2,ebp_d=0;
for(;ebx<=4 && esi<=name_length;ebx++,esi++)
{
eax=in_name[esi-1];
eax=(eax&0xC0&0xFF)>>ecx;
ebp_d=ebp_d|eax;
ecx+=2;
edx=in_name[esi-1];
edx=edx&0x3F&0xff;
edx=key_word[edx];
serial[base+ebx-1]=(char)edx;
}
serial[base]=key_word[ebp_d];
base+=4;
}
printf("The serial is:%s.\n",serial);//最后的点’.’直接输出
  return 0;
}
-----------------------------------------------------------The end 2009-2-24 10:53:26-------------------------------------------------------------
ps:终于有上传权限了,我把creakme传上来,好给需要的做练习!


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (20)
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
2
支持一下,8错
2009-2-24 11:36
0
雪    币: 204
活跃值: (84)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好啊,支持的
2009-2-24 12:05
0
雪    币: 277
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
内容很不错,写的很不错
支持
2009-2-24 16:44
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
不错,入门的感觉真好!(但千万别像我这样就停留下来)勇进
2009-2-24 17:02
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
6
谢谢谢谢了,能够得到鼓舞还是很高兴的了
2009-2-24 19:11
0
雪    币: 1137
活跃值: (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
谢谢LZ的好文章!

一起努力学习!
2009-2-24 21:29
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
8
楼主内功不浅啊....呵呵,好文多发..
2009-2-24 22:48
0
雪    币: 270
活跃值: (117)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
确实是好帖呀,仔细看了一下学习一下,
收获不小呀,感谢楼主了
2009-2-25 03:07
0
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错,谢谢哦
2009-2-25 09:12
0
雪    币: 123
活跃值: (95)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
不错 ,建议楼主将中断选用方法也写出来一下 .
2009-2-25 10:34
0
雪    币: 421
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
写的不错
可以看懂,看来也要努力一下了
2009-2-25 12:17
0
雪    币: 194
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主的分析思路清晰,唉。。。。。我不知什么时候才能达到楼主的水平哦。
2009-2-25 15:45
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
14
客观的说,我这个没什么水平了,我想关键是改变想法,相信自己也可以做到,也许你会发现其实很简单了
2009-2-25 21:47
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
虽然看不懂,还是支持.
2009-2-27 23:24
0
雪    币: 159
活跃值: (38)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
16
不错不错,很好
2009-2-28 11:27
0
雪    币: 222
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
只能做出内存补丁,注册机还弄不出来,,还得向楼主学习.....
2009-8-18 12:51
0
雪    币: 82
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
看懂了,学习了
2009-8-30 10:58
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
19
support
2009-8-30 12:47
0
雪    币: 208
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
载入F9运行,随便输入用户名和注册码,点注册,查找字串,找到自己输入的注册码,双击进去,向下拉,找到类似于Text = "恭?,B2,"您?,AC,"",D7,"",A2,"",B2,"崧胝",B7,"?,A1,""字样,在上面的jnz下断点,再点注册,把ZF改为1,按F9,OK
2009-9-15 00:58
0
雪    币: 314
活跃值: (271)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
看过还是顶下,我 要什么时候 才能有水平啊
2009-10-8 21:42
0
游客
登录 | 注册 方可回帖
返回
//