2011年成都信息工程学院第二季极客大挑战逆向第二题Crackwho破文

【文章标题】: CUIT极客大挑战Crackwho破文
【软件名称】: Crackwho
【软件大小】: 36.5KB
【下载地址】: http://www.kuaipan.cn/file/id_32222188979355669.html
【加壳方式】: yoda's Protector 1.03.2 -> Ashkbiz Danehkar
【保护方式】: 序列号保护
【编写语言】: Microsoft Visual C++ 8.0 *
【使用工具】: PEiD,OD
【操作平台】: Windows Xp sp3
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
首先PEID查壳,一看yoda's Protector 1.03.2,貌似没见过,因为用得比较少。
我们还是先脱壳吧。

首先,调试设置除了内存访问异常,其他都忽略掉。

 1 0040E549 > E8 03000000 call Crackwho.0040E551//OD加载程序
 2 0040E54E EB 01 jmp short Crackwho.0040E551//F9运行
 3 0040E550 E8 BB550000 call Crackwho.00413B10//此时注意堆栈
 4 0040E555 00E8 add al,ch
 5 0040E557 0300 add eax,dword ptr ds:[eax]
 6 0040E559 0000 add byte ptr ds:[eax],al
 7 0040E55B EB 01 jmp short Crackwho.0040E55E
 8 //堆栈显示
 9 0012EAF0 0012EC70 指针到下一个 SEH 记录
10 0012EAF4 00410F50 SE 句柄
11 
12 CTRL+G,来到00410F50 
13 
14 00410F50 55 push ebp//F2下断,F9运行,单步走
15 00410F51 8BEC mov ebp,esp
16 00410F53 57 push edi
17 00410F54 36:8B45 10 mov eax,dword ptr ss:[ebp+10]
18 00410F58 3E:8BB8 C400000>mov edi,dword ptr ds:[eax+C4]
19 00410F5F 3E:FF37 push dword ptr ds:[edi]
20 00410F62 33FF xor edi,edi
21 00410F64 64:8F07 pop dword ptr fs:[edi]
22 00410F67 3E:8380 C400000>add dword ptr ds:[eax+C4],8
23 00410F6F 3E:8BB8 A400000>mov edi,dword ptr ds:[eax+A4]
24 00410F76 C1C7 07 rol edi,7
25 00410F79 3E:89B8 B800000>mov dword ptr ds:[eax+B8],edi//运行到此,edi的值就是OEP的地址0040157C
26 00410F80 B8 00000000 mov eax,0//然后ctrl+G来到这个地址0040157C,然后下断点运行到此,然后dump,fix
27 00410F85 5F pop edi
28 00410F86 C9 leave
29 00410F87 C3 retn

 



脱完后,运行,程序主界面变了,发现程序有自校验。我们再将脱壳后的程序用OD载入
用插件查找ascii,未找到任何字符串。
我们接着右键,查找,所有参考文本串,就可以看到相应的字符串,双击来到代码处,ctrl+A,分析下代码,
就可以看到Sorry,You are wrong,和自校验的字符串

 1 0040128B /73 1B jnb short 1.004012A8
 2 0040128D |. |8B4424 04 mov eax,dword ptr ss:[esp+4]
 3 00401291 |. |6A 00 push 0 ; /lParam = NULL
 4 00401293 |. |68 10114000 push 1.00401110 ; |DlgProc = 1.00401110
 5 00401298 |. |6A 00 push 0 ; |hOwner = NULL
 6 0040129A |. |6A 65 push 65 ; |pTemplate = 65
 7 0040129C |. |50 push eax ; |hInst
 8 0040129D |. |FF15 04814000 call dword ptr ds:[<&User32.DialogBoxPara>; \DialogBoxParamW
 9 004012A3 |. |33C0 xor eax,eax
10 004012A5 |. |C2 1000 retn 10
11 004012A8 |> \6A 01 push 1 ; /Style = MB_OKCANCEL|MB_APPLMODAL
12 004012AA |. 68 909A4000 push 1.00409A90 ; |Title = "哎呀"
13 004012AF |. 68 989A4000 push 1.00409A98 ; |Text = "雅蠛蝶!不要脱我~~~~~~"
14 004012B4 |. 6A 00 push 0 ; |hOwner = NULL
15 004012B6 |. FF15 FC804000 call dword ptr ds:[<&User32.MessageBoxW>] ; \MessageBoxW
16 发现0040128B这个跳是跳到自校验这来,所以我们将jnb改为jb,保存运行就可以了。




脱壳完毕。接下来就是破解找码了。



用OD加载脱壳完全的程序,还是右键查找,所有参考字符串,来到关键代码。

 1 004011AC . FFD6 call esi ; \获取用户名,长度返回给eax
 2 004011AE . 6A 09 push 9 ; /Count = 9
 3 004011B0 . 8D4424 0C lea eax,dword ptr ss:[esp+C] ; |
 4 004011B4 . 50 push eax ; |Buffer
 5 004011B5 . 68 EB030000 push 3EB ; |ControlID = 3EB (1003.)
 6 004011BA . 57 push edi ; |hWnd
 7 004011BB . FFD6 call esi ; \获取假码,长度依然给eax
 8 004011BD . 8D7424 08 lea esi,dword ptr ss:[esp+8] ; 假码
 9 004011C1 . 8D4C24 1C lea ecx,dword ptr ss:[esp+1C] ; 用户名
10 004011C5 . E8 36FEFFFF call Crackwho.00401000 //这里就是算法,进去看就知道了,算法了,很简单的,还是比较适合新手,这里我就把注册机贴出来吧。
11 004011CA . 5E pop esi 
12 004011CB . 6A 00 push 0
13 004011CD . 68 3C9A4000 push Crackwho.00409A3C
14 004011D2 . 85C0 test eax,eax
15 004011D4 . 74 20 je short Crackwho.004011F6
16 004011D6 . 68 449A4000 push Crackwho.00409A44 ; UNICODE "Congratulation"
17 004011DB . 57 push edi
18 004011DC . FF15 FC804000 call dword ptr ds:[4080FC]
19 004011E2 . 33C0 xor eax,eax
20 004011E4 . 5F pop edi
21 004011E5 . 8B4C24 28 mov ecx,dword ptr ss:[esp+28]
22 004011E9 . 33CC xor ecx,esp
23 004011EB . E8 D1000000 call Crackwho.004012C1
24 004011F0 . 83C4 2C add esp,2C
25 004011F3 . C2 1000 retn 10
26 004011F6 > 68 649A4000 push Crackwho.00409A64 ; UNICODE "Sorry,You are wrong"
27 004011FB . 57 push edi
28 004011FC . FF15 FC804000 call dword ptr ds:[4080FC]
29 
30 进入call到这发现算法,这只是第一重循环,我想下面的7次循环应该也没问题了
31 0040103E |. 0FB701 movzx eax,word ptr ds:[ecx] ; eax指向用户名
32 00401041 |. 0FB71424 movzx edx,word ptr ss:[esp] ; edx指向syclover
33 00401045 |. 33C2 xor eax,edx ; 第一位用户名和‘s’异或
34 00401047 |. 99 cdq
35 00401048 |. 57 push edi
36 00401049 |. BF 1A000000 mov edi,1A
37 0040104E |. F7FF idiv edi ; 异或的结果与1A的余数给edx
38 00401050 |. 0FB741 02 movzx eax,word ptr ds:[ecx+2] ; 此时将假码第二位给eax,准备进行下一次循环
39 00401054 |. 6A 09 push 9 ; /Arg3 = 00000009
40 00401056 |. 56 push esi ; |Arg2
41 00401057 |. 51 push ecx ; |Arg1
42 00401058 |. 83C2 41 add edx,41 ; |余数加41
43 0040105B |. 66:8911 mov word ptr ds:[ecx],dx ; |结果放回ecx

用户名:JoyChou

注册码:FWAVHZQK
PS:当看到出现一个字符串:syclover就可以猜测注册码是8位的。此题是明码比较的,菜鸟就装B的吧算法写了出来,忘老鸟勿喷。




算法:
用户名每一位和syclover十六进制异或,结果%1A,再+0x41,结果转字符
换成十进制就是,结果%26,再加上65

由于菜鸟只会C语言,所以只能写个苦逼的C程序,忘大牛见怪

 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5 char name[10];
 6 int i, c;
 7 char temp[10] = "syclover";
 8 char key[10];
 9 
10 printf("input your name:");
11 gets(name);
12 
13 
14 
15 for (i = 0; i < 8; i++)
16 {
17 key = ( (name ^ temp)%26 ) + 65;
18 }
19 key= '\0';
20 
21 printf("the key is: ");
22 puts(key);
23 
24 printf("\n");
25 
26 c=getchar();
27 
28 return 0;
29 }

 



--------------------------------------------------------------------------------
【经验总结】
比较简单,适合新手!

--------------------------------------------------------------------------------
【版权声明】: 本文原创于JoyChou, 转载请注明作者并保持文章的完整, 谢谢!

2012年06月12日 15:35:45

posted @ 2012-06-12 15:40  JoyChou  阅读(670)  评论(3编辑  收藏  举报