首页
社区
课程
招聘
[原创]简单CrackMe的快速分析
发表于: 2010-5-24 11:26 7101

[原创]简单CrackMe的快速分析

2010-5-24 11:26
7101

这个CrackMe很简单,但是简单不代表白痴,个人认为这个CM还是有一定意义的(具体是什么我最后再说^_^)。
对先最简单的方法,字符串查找。看能不能发现什么线索。

00401000  /$  81EC D0070000 sub     esp, 7D0
00401006  |.  68 70704000   push    00407070                         ;  can you guess the code:
0040100B  |.  E8 AA010000   call    004011BA
00401010  |.  8D4424 04     lea     eax, dword ptr [esp+4]
00401014  |.  50            push    eax
00401015  |.  E8 56010000   call    00401170
0040101A  |.  8D4C24 08     lea     ecx, dword ptr [esp+8]
0040101E  |.  51            push    ecx
0040101F  |.  E8 3C000000   call    00401060                         ;  call后不远处有个跳转,很经典的关键call。F7跟进去。
00401024  |.  83C4 0C       add     esp, 0C
00401027  |.  85C0          test    eax, eax
00401029  |.  74 16         je      short 00401041
0040102B  |.  68 48704000   push    00407048                         ;  good! the key is your input o(^o^)o\n
00401030  |.  E8 85010000   call    004011BA
00401035  |.  83C4 04       add     esp, 4
00401038  |.  33C0          xor     eax, eax
0040103A  |.  81C4 D0070000 add     esp, 7D0
00401040  |.  C3            retn
00401041  |>  68 30704000   push    00407030                         ;  you don't guess it~\n
00401046  |.  E8 6F010000   call    004011BA
0040104B  |.  83C4 04       add     esp, 4
0040104E  |.  33C0          xor     eax, eax
00401050  |.  81C4 D0070000 add     esp, 7D0
00401056  \.  C3            retn
00401060  /$  83EC 10       sub     esp, 10
00401063  |.  A1 8C704000   mov     eax, dword ptr [40708C]          ;  指向加密的key的第一个字符
00401068  |.  8B0D 90704000 mov     ecx, dword ptr [407090]          ;  指向加密key的第5个字符
0040106E  |.  53            push    ebx                              ;  这样的push除了保护现场外,还有临时变量的作用。
0040106F  |.  894424 04     mov     dword ptr [esp+4], eax
00401073  |.  66:A1 9870400>mov     ax, word ptr [407098]            ;  指向加密key的倒数第2个字符
00401079  |.  894C24 08     mov     dword ptr [esp+8], ecx
0040107D  |.  8A0D 9A704000 mov     cl, byte ptr [40709A]            ;  指向加密key的末尾,空字符的地方。
00401083  |.  56            push    esi
00401084  |.  8B7424 1C     mov     esi, dword ptr [esp+1C]          ;  esi指向我们输入的序列号
00401088  |.  57            push    edi
00401089  |.  66:894424 18  mov     word ptr [esp+18], ax
0040108E  |.  884C24 1A     mov     byte ptr [esp+1A], cl
00401092  |.  8BFE          mov     edi, esi                         ;  准备计算字符串的长度
00401094  |.  83C9 FF       or      ecx, FFFFFFFF
00401097  |.  33C0          xor     eax, eax
00401099  |.  8B15 94704000 mov     edx, dword ptr [407094]
0040109F  |.  F2:AE         repne   scas byte ptr es:[edi]           ;  重复串操作,直到ecx为0
004010A1  |.  F7D1          not     ecx
004010A3  |.  49            dec     ecx                              ;  ecx为真实长度,就是我们输入的序列号的长度。
004010A4  |.  895424 14     mov     dword ptr [esp+14], edx
004010A8  |.  8BD1          mov     edx, ecx
004010AA  |.  8D7C24 0C     lea     edi, dword ptr [esp+C]           ;  也是计算字符串长度,计算的是加密key
004010AE  |.  83C9 FF       or      ecx, FFFFFFFF
004010B1  |.  F2:AE         repne   scas byte ptr es:[edi]
004010B3  |.  F7D1          not     ecx
004010B5  |.  49            dec     ecx                              ;  ecx为真实的长度
004010B6  |.  3BD1          cmp     edx, ecx                         ;  输入的序列号长度一定要是14位
004010B8  |.  0F85 9C000000 jnz     0040115A                         ;  如果2个字符串长度不相等,则直接失败。
004010BE  |.  8BFE          mov     edi, esi                         ;  准备计算假序列号的长度
004010C0  |.  83C9 FF       or      ecx, FFFFFFFF                    ;  计算字符串长度,其实这个就是strlen 优化编译后的代码
004010C3  |.  33D2          xor     edx, edx                         ;  清零edx,为下面的循环做准备,也就是初始化变量为0.
004010C5  |.  F2:AE         repne   scas byte ptr es:[edi]
004010C7  |.  F7D1          not     ecx
004010C9  |.  49            dec     ecx                              ;  保存着真实的字符串长度
004010CA  |.  74 19         je      short 004010E5                   ;  如果长度为0,跳走
004010CC  |>  8A0432        /mov     al, byte ptr [edx+esi]          ;  对假序列号逐个处理
004010CF  |.  8BFE          |mov     edi, esi
004010D1  |.  34 20         |xor     al, 20                          ;  字符逐个与0x20做异或运算,应该就是解密了。
004010D3  |.  83C9 FF       |or      ecx, FFFFFFFF                   ;  经典对白,又要计算字符串长度了
004010D6  |.  880432        |mov     byte ptr [edx+esi], al          ;  解密后保存
004010D9  |.  33C0          |xor     eax, eax
004010DB  |.  42            |inc     edx                             ;  递增,到这里明白了,原来edx还有做字符串数组索引的作用。
004010DC  |.  F2:AE         |repne   scas byte ptr es:[edi]
004010DE  |.  F7D1          |not     ecx
004010E0  |.  49            |dec     ecx                             ;  保存着字符串长度
004010E1  |.  3BD1          |cmp     edx, ecx                        ;  比较看解密完了没有,没有就继续。
004010E3  |.^ 72 E7         \jb      short 004010CC
004010E5  |>  8D7C24 0C     lea     edi, dword ptr [esp+C]           ;  计算加密key的长度
004010E9  |.  83C9 FF       or      ecx, FFFFFFFF                    ;  又要计算字符长度了
004010EC  |.  33C0          xor     eax, eax
004010EE  |.  33D2          xor     edx, edx
004010F0  |.  F2:AE         repne   scas byte ptr es:[edi]
004010F2  |.  F7D1          not     ecx
004010F4  |.  49            dec     ecx                              ;  ecx保存着长度
004010F5  |.  74 1D         je      short 00401114                   ;  为零就跑了
004010F7  |>  8A4414 0C     /mov     al, byte ptr [esp+edx+C]        ;  逐个字符处理加密key。
004010FB  |.  8D7C24 0C     |lea     edi, dword ptr [esp+C]
004010FF  |.  04 FB         |add     al, 0FB                         ;  每个字符的ASCII值加上0xFB
00401101  |.  83C9 FF       |or      ecx, FFFFFFFF
00401104  |.  884414 0C     |mov     byte ptr [esp+edx+C], al
00401108  |.  33C0          |xor     eax, eax
0040110A  |.  42            |inc     edx
0040110B  |.  F2:AE         |repne   scas byte ptr es:[edi]
0040110D  |.  F7D1          |not     ecx
0040110F  |.  49            |dec     ecx
00401110  |.  3BD1          |cmp     edx, ecx                        ;  循环处理每个字符
00401112  |.^ 72 E3         \jb      short 004010F7
00401114  |>  8D7C24 0C     lea     edi, dword ptr [esp+C]           ;  这回是计算经过处理后的加密key的长度
00401118  |.  83C9 FF       or      ecx, FFFFFFFF
0040111B  |.  33C0          xor     eax, eax
0040111D  |.  33D2          xor     edx, edx
0040111F  |.  F2:AE         repne   scas byte ptr es:[edi]
00401121  |.  F7D1          not     ecx
00401123  |.  49            dec     ecx                              ;  保存着长度
00401124  |.  74 28         je      short 0040114E                   ;  不能为0,要不就跑了
00401126  |.  8D4424 0C     lea     eax, dword ptr [esp+C]
0040112A  |.  2BF0          sub     esi, eax
0040112C  |>  8A5C14 0C     /mov     bl, byte ptr [esp+edx+C]        ;  [esp+C]指向的是处理后的key的地址,edx用来做索引
00401130  |.  8D4414 0C     |lea     eax, dword ptr [esp+edx+C]
00401134  |.  8A0C06        |mov     cl, byte ptr [esi+eax]          ;  [esi]指向处理后的假key的首地址,eax用来做索引
00401137  |.  3ACB          |cmp     cl, bl                          ;  逐个字节比较
00401139  |.  75 1F         |jnz     short 0040115A                  ;  不相等就跳向失败
0040113B  |.  8D7C24 0C     |lea     edi, dword ptr [esp+C]
0040113F  |.  83C9 FF       |or      ecx, FFFFFFFF
00401142  |.  33C0          |xor     eax, eax
00401144  |.  42            |inc     edx
00401145  |.  F2:AE         |repne   scas byte ptr es:[edi]
00401147  |.  F7D1          |not     ecx
00401149  |.  49            |dec     ecx
0040114A  |.  3BD1          |cmp     edx, ecx
0040114C  |.^ 72 DE         \jb      short 0040112C
0040114E  |>  5F            pop     edi
0040114F  |.  5E            pop     esi
00401150  |.  B8 01000000   mov     eax, 1
00401155  |.  5B            pop     ebx
00401156  |.  83C4 10       add     esp, 10
00401159  |.  C3            retn
0040115A  |>  5F            pop     edi
0040115B  |.  5E            pop     esi
0040115C  |.  33C0          xor     eax, eax
0040115E  |.  5B            pop     ebx
0040115F  |.  83C4 10       add     esp, 10
00401162  \.  C3            retn
A = 假码 ^ 0x20;
B = 加密key + 0xFB;
if (A == B)
  成功,返回TRUE
else
  失败,返回FALSE

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
2
很久没玩CM了,支持一下!
2010-5-24 13:17
0
雪    币: 136
活跃值: (48)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
收藏,学习,写的很简明
2010-5-24 13:35
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不会分析,我直接F5,再分析f5之后的c代码
2010-5-24 15:07
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好帖,学习了
2010-5-24 15:26
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
6
F5也把计算字符串给认错了。它认的是 lstren(xxx) - 1
2010-5-24 15:57
0
雪    币: 506
活跃值: (318)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7

我希望 多看看 逆向分析 带 anti 的 cm !!!
2010-5-25 12:43
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
很不错,学习学习
2010-6-3 14:37
0
雪    币: 268
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
GUX
9
不错, 适合我等菜鸟学习。。
2010-6-3 14:52
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
-----------------------
2010-6-7 15:12
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
char key[] = {0x68, 0x57, 0x19, 0x48, 0x50, 0x6E, 0x58, 0x78, 0x54, 0x6A, 0x19, 0x58, 0x5E, 0x06}; 

int f(char* inputstr)
{
unsigned long a = &key[0];
unsigned long b = &key[4];
unsigned short c = &key[12];
char d = &key[13];
///////////////////这是我反汇编的结果,不明白上面这4句代码的作用是什么?


if (strlen(inputstr) == strlen(key))
{
if (strlen(inputstr)!=0)
{
for(int i =0; i < strlen(inputstr); i++)
{
inputstr[i] ^= 0x20;
}
}
}

if (strlen(key) != 0)
{
for (int i = 0;i < strlen(key); i++)
key[i] += 0xfb;
}
for(int i = 0;i < strlen(key);i++)
{if (key[i] != inputstr[i])
{
return 0;
}
}
return 1;
}

void main ()
{
char inputstr[10];
printf("can you guess the code:");
gets(inputstr);
if (f(inputstr) != 0)
	printf("good! the key is your input o(^o^)o\n");
else
	printf("you don't guess it~\n");
}

附上我转换的c,请看看有什么错误,尤其是前面的赋值指令,有什么作用,实在是很迷茫。
2010-6-7 15:56
0
雪    币: 60
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
学习,收藏.
2010-6-22 14:42
0
游客
登录 | 注册 方可回帖
返回
//