首页
社区
课程
招聘
[原创]DCG_3_1算法分析
2006-8-8 14:33 6665

[原创]DCG_3_1算法分析

2006-8-8 14:33
6665
【文章标题】: DCG_3_1算法分析
【文章作者】: DCracker
【作者邮箱】: dcdevil@126.com
【软件名称】: DCG_3_1
【软件大小】: 2.50KB
【下载地址】: 自己搜索下载
【加壳方式】: 无壳
【保护方式】: name/serial
【使用工具】: OllyDbg
【操作平台】: win32
【软件介绍】: DCG考试题
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  用OllyDbg加载程序,程序停在00401000,向下查看很容易发现读取用户名的地方,在00401092下断,
  输入试练码 DCracker/0123456789,点注册断下:
  
  
  00401092   pushad
  00401093   push 7F                              ; /Count = 7F (127.)
  00401095   push DCG_3_1e.00401E00               ; |Buffer = DCG_3_1e.00401E00
  0040109A   push 3E8                             ; |ControlID = 3E8 (1000.)
  0040109F   push dword ptr ds:[401F00]           ; |hWnd = 00650140 ('Snake ',class='#32770')
  004010A5   call dword ptr ds:[<&USER32.GetDlgIt>; \GetDlgItemTextA                    -----获得用户名DCracker
  004010AB   test eax,eax                                                               -----判断是否输入用户名
  004010AD   jnz short DCG_3_1e.004010CB                                                
  004010AF   push 30                              ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  004010B1   push DCG_3_1e.00401400               ; |Title = "Error"
  004010B6   push DCG_3_1e.00401426               ; |Text = "You forgot to enter a Name..."
  004010BB   push dword ptr ds:[401F00]           ; |hOwner = 00650140 ('Snake ',class='#32770')
  004010C1   call dword ptr ds:[<&USER32.MessageB>; \MessageBoxA                         -----出错提示框
  004010C7   popad
  004010C8   xor eax,eax
  004010CA   retn
  004010CB   push 7F                              ; /Count = 7F (127.)
  004010CD   push DCG_3_1e.00401D00               ; |Buffer = DCG_3_1e.00401D00
  004010D2   push 3E9                             ; |ControlID = 3E9 (1001.)
  004010D7   push dword ptr ds:[401F00]           ; |hWnd = 00650140 ('Snake ',class='#32770')
  004010DD   call dword ptr ds:[<&USER32.GetDlgIt>; \GetDlgItemTextA                    -----获得注册码
  004010E3   test eax,eax                                                               -----判断是否输入注册码
  004010E5   jnz short DCG_3_1e.00401103                                                
  004010E7   push 30                              ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  004010E9   push DCG_3_1e.00401400               ; |Title = "Error"
  004010EE   push DCG_3_1e.00401444               ; |Text = "You forgot to enter a Serial..."
  004010F3   push dword ptr ds:[401F00]           ; |hOwner = 00650140 ('Snake ',class='#32770')
  004010F9   call dword ptr ds:[<&USER32.MessageB>; \MessageBoxA                        -----出错提示框
  004010FF   popad
  00401100   xor eax,eax
  00401102   retn
  00401103   call DCG_3_1e.004012AA                                                     -----判断输入的注册码是否符合要求!
  00401108   test al,al
  0040110A   jnz short DCG_3_1e.00401128                                                
  0040110C   push 30                              ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  0040110E   push DCG_3_1e.00401400               ; |Title = "Error"
  00401113   push DCG_3_1e.00401464               ; |Text = "There is something wrong with your Serial..."
  00401118   push dword ptr ds:[401F00]           ; |hOwner = 00650140 ('Snake ',class='#32770')
  0040111E   call dword ptr ds:[<&USER32.MessageB>; \MessageBoxA                        -----出错提示框
  00401124   popad
  00401125   xor eax,eax
  00401127   retn
  00401128   call DCG_3_1e.00401173                                                     -----开辟一块空间用来生成地图
  0040112D   call DCG_3_1e.0040119B                                                     -----关键子程序!!!生成地图
  00401132   call DCG_3_1e.0040120C                                                     -----关键子程序!!!
  00401137   test al,al
  00401139   jnz short DCG_3_1e.00401157                                                -----爆破点!
  0040113B   push 40                              ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  0040113D   push DCG_3_1e.00401491               ; |Title = "Too bad..."
  00401142   push DCG_3_1e.0040149C               ; |Text = "Common, you can do better then that! :)"
  00401147   push dword ptr ds:[401F00]           ; |hOwner = 00650140 ('Snake ',class='#32770')
  0040114D   call dword ptr ds:[<&USER32.MessageB>; \MessageBoxA                        -----出错提示框
  00401153   popad
  00401154   xor eax,eax
  00401156   retn
  00401157   push 40                              ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  00401159   push DCG_3_1e.004014C4               ; |Title = "Congratulations!"
  0040115E   push DCG_3_1e.004014D5               ; |Text = "Well done!Now for the more difficult part, try to keygen it..."
  00401163   push dword ptr ds:[401F00]           ; |hOwner = 00650140 ('Snake ',class='#32770')
  00401169   call dword ptr ds:[<&USER32.MessageB>; \MessageBoxA                        -----正确提示框
  0040116F   popad
  00401170   xor eax,eax
  00401172   retn
  
  
  判断注册码是否符合要求子程序:
  004012AA   push eax
  004012AB   push esi
  004012AC   mov esi,DCG_3_1e.00401700
  004012B1   /mov eax,dword ptr ds:[esi]
  004012B3   |and dword ptr ds:[esi],0
  004012B6   |add esi,4
  004012B9   |test eax,eax
  004012BB   \jnz short DCG_3_1e.004012B1
  004012BD   mov esi,DCG_3_1e.00401D00            ;  ASCII "0123456789"
  004012C2   /mov al,byte ptr ds:[esi]
  004012C4   |test al,al                          ;  Switch (cases 0..46)
  004012C6   |je short DCG_3_1e.004012E0
  004012C8   |cmp al,30
  004012CA   |jb short DCG_3_1e.004012D8             -----由此可见注册码只能由0--9,A--F构成!
  004012CC   |cmp al,3A
  004012CE   |jb short DCG_3_1e.004012DD
  004012D0   |cmp al,41
  004012D2   |jb short DCG_3_1e.004012D8
  004012D4   |cmp al,47
  004012D6   |jb short DCG_3_1e.004012DD
  004012D8   |pop esi                             ;  Default case of switch 004012C4
  004012D9   |pop eax
  004012DA   |mov al,0
  004012DC   |retn
  004012DD   |inc esi                             ;  Cases 30 ('0'),31 ('1'),32 ('2'), ......
  004012DE   \jmp short DCG_3_1e.004012C2
  004012E0   pop esi                              ;  Case 0 of switch 004012C4
  004012E1   pop eax
  004012E2   mov al,1
  004012E4   retn
  
  
  地址为00401173子程序用来在内存中生成一块空间:地址00401AF0--00401C0F,头16个字节为FF,中间256个字节为00,最后16个字节也为FF。
  00401B00--00401BFF 就成了一个活动场所,两边的FF就是墙!
  
  生成地图子程序:
  
  0040119B   push eax
  0040119C   push ecx
  0040119D   push edx
  0040119E   push esi
  0040119F   push edi
  004011A0   xor ecx,ecx
  004011A2   mov esi,DCG_3_1e.00401E00            ;  ASCII "DCracker"        -----取出用户名地址
  004011A7   mov edi,DCG_3_1e.00401B00                                -----取出地图首地址
  004011AC   push esi
  004011AD   mov dl,0
  004011AF   /mov al,byte ptr ds:[esi]                             
  004011B1   |inc esi
  004011B2   |add dl,al                              -----将用户名求和,结果放到dl中
  004011B4   |test al,al
  004011B6   \jnz short DCG_3_1e.004011AF
  004011B8   pop esi
  004011B9   /movzx eax,byte ptr ds:[esi]            -----取出用户名字符
  004011BC   |xor al,dl                              -----与dl结果作xor运算
  004011BE   |/sub dl,al                             -----dl-al-->dl
  004011C0   ||or byte ptr ds:[eax+edi],0CC          -----原程序此处有Bug! 应为xor! 用来在地图中该位置放入CC,同时判断
  004011C4   ||jnz short DCG_3_1e.004011CA                此处是否已经为CC,若是CC则dl-1,换个位置放入CC,否则CC个数将
  004011C6   ||dec dl                                     不等于用户名个数,有背作者原意!
  004011C8   |\jmp short DCG_3_1e.004011BE
  004011CA   |inc ecx
  004011CB   |inc esi
  004011CC   |cmp byte ptr ds:[esi],0                -----判断是否处理完
  004011CF   \jnz short DCG_3_1e.004011B9
  004011D1   mov dword ptr ds:[401F04],ecx
  004011D7   xor dl,al
  004011D9   /sub al,dl
  004011DB   |cmp byte ptr ds:[edi+eax],0CC          -----判断此处是否为CC
  004011DF   |jnz short DCG_3_1e.004011E5
  004011E1   |dec dl
  004011E3   \jmp short DCG_3_1e.004011D9
  004011E5   mov byte ptr ds:[edi+eax],0DD           -----不为CC则放入DD
  004011E9   mov al,dl
  004011EB   /cmp byte ptr ds:[edi+eax],0CC          -----判断此处是否为CC
  004011EF   |je short DCG_3_1e.004011F7
  004011F1   |cmp byte ptr ds:[edi+eax],0DD          -----判断此处是否为DD
  004011F5   |jnz short DCG_3_1e.004011FB
  004011F7   |dec al
  004011F9   \jmp short DCG_3_1e.004011EB
  004011FB   lea eax,dword ptr ds:[edi+eax]
  004011FE   mov byte ptr ds:[eax],99                 -----不为CC和DD则放入99
  00401201   mov dword ptr ds:[401700],eax
  00401206   pop edi
  00401207   pop esi
  00401208   pop edx
  00401209   pop ecx
  0040120A   pop eax
  0040120B   retn
  
  
  核心运算子程序:
  
  0040120C   pushad
  0040120D   mov esi,DCG_3_1e.00401D00            ;  ASCII "0123456789"    -----取出注册码地址
  00401212   mov edi,DCG_3_1e.00401700                                     -----取出99所在位置
  00401217   /movzx eax,byte ptr ds:[esi]                                  -----取出一个注册码
  0040121A   |test al,al                          ;  Switch (cases 0..39)  -----是否为零
  0040121C   |je short DCG_3_1e.00401260
  0040121E   |sub al,30                                                    -----减30,即:30->0,31->1,32->2......
  00401220   |cmp al,0A                                                    -----是否为大写字母
  00401222   |jb short DCG_3_1e.00401226
  00401224   |sub al,7                            ;  Default case of switch 0040121A
  00401226   |mov ecx,eax                         ;  Cases 30 ('0'),31 ('1'),......eax->ecx
  00401228   |and al,3                                                     -----这里开始计算移动99的距离!
  0040122A   |shr cl,2
  0040122D   |mov edx,10
  00401232   |test al,al
  00401234   |je short DCG_3_1e.00401241
  00401236   |dec eax
  00401237   |je short DCG_3_1e.0040123F
  00401239   |shr edx,4
  0040123C   |dec eax
  0040123D   |jnz short DCG_3_1e.00401241
  0040123F   |neg edx
  00401241   |mov eax,dword ptr ds:[edi]
  00401243   |add eax,edx
  00401245   |mov al,byte ptr ds:[eax]
  00401247   |test al,al                          ;  Switch (cases 0..DD)  -----99的新位置是否为0,  
  00401249   |je short DCG_3_1e.0040127A                                        若是则到0040127A处处理
  0040124B   |cmp al,99                                                    -----99的新位置是否为99,
  0040124D   |je short DCG_3_1e.00401260                                   -----若是则Over!
  0040124F   |cmp al,0CC                                                   -----99的新位置是否为CC,
  00401251   |je short DCG_3_1e.00401268                                   -----若是则到00401268处处理
  00401253   |cmp al,0DD                                                   -----判断是否是DD
  00401255   |jnz short DCG_3_1e.00401260
  00401257   |cmp dword ptr ds:[401F04],0         ;  Case DD of switch 00401247 -----判断剩余CC是否为零
  0040125E   |je short DCG_3_1e.00401264
  00401260   |popad                               ;  Default case of switch 00401247
  00401261   |mov al,0
  00401263   |retn
  00401264   |popad
  00401265   |mov al,1                                                     -----al被置1,注册码正确!
  00401267   |retn
  00401268   |dec dword ptr ds:[401F04]           ;  Case CC of switch 00401247 -----CC剩余个数减1
  0040126E   |call DCG_3_1e.00401289                                            -----处理CC
  00401273   |mov dword ptr ds:[eax],ebx                                   -----取出99原位置
  00401275   |mov byte ptr ds:[ebx],99                                     -----放入99
  00401278   |jmp short DCG_3_1e.0040127F
  0040127A   |call DCG_3_1e.00401289              ;  Case 0 of switch 00401247  -----处理00
  0040127F   |test ecx,ecx                                                 -----移动次数是否为零,为零返回
  00401281   |je short DCG_3_1e.00401286   
  00401283   |dec ecx                                                      -----移动次数减1,返回继续移动99
  00401284   |jmp short DCG_3_1e.00401241
  00401286   |inc esi                                                      -----esi加1处理注册码下一位                                 
  00401287   \jmp short DCG_3_1e.00401217
  00401289   push edi
  0040128A   mov eax,dword ptr ds:[edi]
  0040128C   mov ebx,eax
  0040128E   add eax,edx                                                   -----计算新位置
  00401290   /mov dword ptr ds:[edi],eax               
  00401292   |mov byte ptr ds:[eax],99                                     -----在新位置放入99
  00401295   |mov byte ptr ds:[ebx],0                                      -----99原位置清零
  00401298   |add edi,4
  0040129B   |cmp dword ptr ds:[edi],0                                     -----判断所有99是否移动完,未完继续
  0040129E   |je short DCG_3_1e.004012A6                                        否则返回
  004012A0   |mov eax,ebx
  004012A2   |mov ebx,dword ptr ds:[edi]
  004012A4   \jmp short DCG_3_1e.00401290
  004012A6   mov eax,edi
  004012A8   pop edi
  004012A9   retn
  
  通过以上算法分析可知:该程序注册算法为贪吃蛇游戏!99为蛇,CC为要吃的东西,吃完所有的CC后吃到DD,即注册成功!
  程序根据用户名初始化地图,即初始化99,CC,DD的位置,CC的个数等于用户名的个数。根据输入的注册码来移动99,即贪吃蛇。
  每吃到一个CC后,就会长出一个99,移动99不能撞到自身(即99),也不能撞到墙(即FF),也不能提前吃到DD!注册码不同字符,
  对应不同的移动距离,详见下表:
  
  注册码    移动次数    步长(字节)    移动总距离(步长x次数)    备注
    0          1            16                16          “-”表示向低址移动
    1          1           -16               -16           
    2          1            -1                -1
    3          1             1                 1
    4          2            16                32
    5          2           -16               -32
    6          2            -1                -2
    7          2             1                 2
    8          3            16                48
    9          3           -16               -48
    A          3            -1                -3
    B          3             1                 3
    C          4            16                64
    D          4           -16               -64
    E          4            -1                -4
    F          4             1                 4
  
  由此表即可算出移动路线及长度,从而得到注册码,由于同一用户名对应很多种移动方案,故注册码不唯一!
  例如:DCracker 注册码:DD9EE68F3FFFFB444FFFB1
--------------------------------------------------------------------------------
【经验总结】
  这个程序的注册算法难度一般,不是很复杂,但是注册机编写有些麻烦!实际上,分析注册算法并没有花很长时间,但注册
  机却写了两天!而且还没有完全写好,注册机只对部分用户名适用,可能是因为本人VC是自学的,学得不好......
  文章写得仓促,不当之处还望指教!
  多谢观看!
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创DCracker, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年08月07日 AM 11:25:44

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

收藏
点赞7
打赏
分享
最新回复 (12)
雪    币: 233
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
DCracker 2 2006-8-8 16:20
2
0
程序下载连接:http://rapidshare.de/files/28605336/DCG_3_1ex.exe.html
雪    币: 370
活跃值: (78)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
Ryosuke 24 2006-8-9 07:57
3
0
原文件没有了,麻烦上传一份到本地吧,谢谢。
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yujinjianx 2006-8-9 12:44
4
0
原文件没有了
雪    币: 191
活跃值: (205)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
warshon 6 2006-8-9 16:52
5
0
这是DCG的考试题,不宜公开讨论的吧?
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
bfqyygy 1 2006-8-9 17:06
6
0
下载不了!!
雪    币: 383
活跃值: (41)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
小娃崽 13 2006-8-9 18:40
7
0
怎么就公开了,DCG的考试还算不算?
雪    币: 333
活跃值: (40)
能力值: ( LV9,RANK:730 )
在线值:
发帖
回帖
粉丝
wzwgp 18 2006-8-9 23:02
8
0
最初由 warshon 发布
这是DCG的考试题,不宜公开讨论的吧?


在DCG的论坛上也有,估计是可以公开的。

DCG技术论坛 → 加密与解密技术 → 算法与逆向工程 → [原创]DCG_3_1算法分析
http://www.cracking.com.cn/dispbbs.asp?boardID=3&ID=58&page=1
雪    币: 233
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
DCracker 2 2006-8-10 13:28
9
0
最初由 wzwgp 发布
在DCG的论坛上也有,估计是可以公开的。

DCG技术论坛 → 加密与解密技术 → 算法与逆向工程 → [原创]DCG_3_1算法分析
http://www.cracking.com.cn/dispbbs.asp?boardID=3&ID=58&page=1


那个也是我发的,是DCG主管让我发的,所以我想应该是可以公开的,于是就在这里也发了.另外DCG考题并不是只有这一道而已......
上传的附件:
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
happytown 31 2006-8-10 20:11
10
0
好像以前碰到过个类似的CrackMe,就是贪吃蛇。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
usingasm 2006-8-11 14:09
11
0
学习中,争取加入DCG,好像在哪里有他们的考试群号吧??
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xoojo 2006-9-1 15:12
12
0
不错的好文!!
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
bxm 29 2006-9-1 20:59
13
0
好文,支持!
游客
登录 | 注册 方可回帖
返回