160个CrackMe 001 Acid burn

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了160个CrackMe 001 Acid burn相关的知识,希望对你有一定的参考价值。

首先PEID查壳
技术分享

Delphi,没有壳就好说了,OD起来语言关系并不太大。

首先,运行发现有一个nag,一个key,一个name/serial,一个一个来。具体瞎网上输入去看对话框什么的我就不扯了...

Nag:
OD运行起来,F8或者shift+F8,找到这几个CALL的作用
技术分享

在第一个nag弹出的位置下断,F9过去,之后进入Call中。
不断利用F8去找弹出Nag的具体位置,这题挺坑,跳转比较多,耐心一点,最后找到这个MessageBoxA函数的位置。
技术分享

把这个MessageBoxA全部nop掉,顺利爆破掉Nag。

Key:
key也是比较简单的,一般来说仅仅只输入一个字符串的都会硬编码在程序内部。

crtl+F2重新启动程序后,F9运行,输入
技术分享

不要点击确定,F12将程序停下来,去Alk+k去堆栈找这时调用这个对话框的MessageBox函数
因为一开始在Crtl+N查找参考模块中发现函数实在有点多,我不能分辨出来每一个MessageBox函数的作用才这样做,如果只有一个MessageBox函数的话就可以直接Crtl+N CALL过去就好...

找到后Show Call,看到了这是一个函数
push ebp
move ebp,esp
这时太明显不过的建立栈帧的过程。
技术分享

在函数头部push ebp出下断,我要找是从哪里调用的函数


技术分享

注意要F9两次,重新输入,点击Check it Baby!,
在右下角堆栈处找到最近一条Return语句:

0019F810   0042F509  返回到 Acid_bur.0042F509 来自 Acid_bur.0042A170

右键 Follow in Disassm..(反汇编跟随),转到调用位置,向上向下翻一翻(这是个好习惯..)
技术分享

看到了Key果然是硬编码在程序中的,12345是我们输入的key,那么Hello Dude就应该是正确的key,检验一下:
技术分享

最后就是稍费劲一点的name/serial啦,之所以说费劲,是因为不难,因为连我都做出来了...

同样,用F9然后输入序列号去找MessageBox的调用:
技术分享

show call,并且同样的结构在函数头部push ebq出下断点,找到调用这个MessageBox函数
(姑且这么称它吧,因为它的作用就是弹出一个对话框)
的call
找到了,首先可以爆破,把这个call直接nop掉:
技术分享

技术分享
爆破后我们怎么输入都会成功的,不过,这个太low了,于是我们去找算法:

不断的F7,F8,F9在加上下断点去分析上面的程序(你不知道作为一个新手我用了多长时间)对上面的汇编程序进行分析:
首先我们在、

0042FB32  |.  E8 39A6FFFF   call Acid_bur.0042A170

上下断点,在不弹出错误对话框的情况下去分析上面的汇编代码:
看到
技术分享

于是,试一下这个serial,他应该是根据我输入的name生成的。


技术分享,成功了。

换一个name,发现,仅仅只是中间的字符串变了,左右的CW等等字母没变,从上面分析也可以看出来,这个正确的serial是拼接出来的。

show code:

0042FA52  |.  E8 D96EFDFF   call Acid_bur.00406930
0042FA57  |.  83F8 04       cmp eax,0x4                              ;  比较字符串的长度是否大于等于4
0042FA5A  |.  7D 1D         jge short Acid_bur.0042FA79
0042FA5C  |.  6A 00         push 0x0
0042FA5E  |.  B9 74FB4200   mov ecx,Acid_bur.0042FB74                ;  ASCII 54,"ry Again!"
0042FA63  |.  BA 80FB4200   mov edx,Acid_bur.0042FB80                ;  ASCII 53,"orry , The serial is incorect !"
0042FA68  |.  A1 480A4300   mov eax,dword ptr ds:[0x430A48]
0042FA6D  |.  8B00          mov eax,dword ptr ds:[eax]               ;  Acid_bur.00424090
0042FA6F  |.  E8 FCA6FFFF   call Acid_bur.0042A170                   ;  字符串长度小于4回到0042A170位置,输错错误对话框
0042FA74  |.  E9 BE000000   jmp Acid_bur.0042FB37
0042FA79  |>  8D55 F0       lea edx,[local.4]
0042FA7C  |.  8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA82  |.  E8 D1AFFEFF   call Acid_bur.0041AA58
0042FA87  |.  8B45 F0       mov eax,[local.4]
0042FA8A  |.  0FB600        movzx eax,byte ptr ds:[eax]              ;  取出name字符串中的第一个字符
0042FA8D  |.  F72D 50174300 imul dword ptr ds:[0x431750]             ;  乘以0x29(地址431750)
0042FA93  |.  A3 50174300   mov dword ptr ds:[0x431750],eax
0042FA98  |.  A1 50174300   mov eax,dword ptr ds:[0x431750]
0042FA9D  |.  0105 50174300 add dword ptr ds:[0x431750],eax          ;  再乘以2存在0x431750
0042FAA3  |.  8D45 FC       lea eax,[local.1]
0042FAA6  |.  BA ACFB4200   mov edx,Acid_bur.0042FBAC
0042FAAB  |.  E8 583CFDFF   call Acid_bur.00403708
0042FAB0  |.  8D45 F8       lea eax,[local.2]
0042FAB3  |.  BA B8FB4200   mov edx,Acid_bur.0042FBB8
0042FAB8  |.  E8 4B3CFDFF   call Acid_bur.00403708
0042FABD  |.  FF75 FC       push [local.1]                           ;  Acid_bur.0042FBAC
0042FAC0  |.  68 C8FB4200   push Acid_bur.0042FBC8                   ;  UNICODE "-"
0042FAC5  |.  8D55 E8       lea edx,[local.6]
0042FAC8  |.  A1 50174300   mov eax,dword ptr ds:[0x431750]
0042FACD  |.  E8 466CFDFF   call Acid_bur.00406718                   ;  这个call函数中的内容就是生成serial中间数字串的部分
0042FAD2  |.  FF75 E8       push [local.6]                           ;  local.6是中间生成的password数字串
0042FAD5  |.  68 C8FB4200   push Acid_bur.0042FBC8                   ;  UNICODE "-"
0042FADA  |.  FF75 F8       push [local.2]                           ;  Acid_bur.0042FBB8
0042FADD  |.  8D45 F4       lea eax,[local.3]
0042FAE0  |.  BA 05000000   mov edx,0x5
0042FAE5  |.  E8 C23EFDFF   call Acid_bur.004039AC                   ;  字符串拼接
0042FAEA  |.  8D55 F0       lea edx,[local.4]
0042FAED  |.  8B83 E0010000 mov eax,dword ptr ds:[ebx+0x1E0]
0042FAF3  |.  E8 60AFFEFF   call Acid_bur.0041AA58                  ;得到正确的password
0042FAF8  |.  8B55 F0       mov edx,[local.4]                        ;  输入的Password:12345
0042FAFB  |.  8B45 F4       mov eax,[local.3]                        ;  正确的password
0042FAFE  |.  E8 F93EFDFF   call Acid_bur.004039FC                 ;  明显就是两个字符串比较喽
0042FB03  |.  75 1A         jnz short Acid_bur.0042FB1F

 

每个call我们不需要进去,把他看作是黑箱,了解他的功能就可以了。
首先是判断字符串的长度 ,之后取第一个字符,乘以地址0x431750的值(0x431750在数据区Crtl+G一下找到)
技术分享
之后乘2,就得出那一串数字啦,关键的生成代码在:

0042FAC5  |.  8D55 E8       lea edx,[local.6]
0042FAC8  |.  A1 50174300   mov eax,dword ptr ds:[0x431750]
0042FACD  |.  E8 466CFDFF   call Acid_bur.00406718                   ;  这个call函数中的内容就是生成serial中间数字串的部分
0042FAD2  |.  FF75 E8       push [local.6]                           ;  local.6是中间生成的password数字串

 

同样我们下断点进去:
真正的坑来了,进去之后发现了很多的跳转,我只知道对每一个字符都进行了操作,但是跳转太多了,没明白他的实现过程(汇编学的渣...),但确定这里就是生成字符串的位置,于是我又把他当黑箱了。

输入name:12345之后,在0x431750内存操作后得到0x0FB2,之后生成的数字串:4018,好吧,我猜到了:
技术分享
16进制转10进制数字串,这就是整个call的功能...

OK,算法就是name输入后先根据上面的结果生成数字字符串,然后再和其他的字母,符号拼接,成最后的serial。这就是这个name/serial算法的求算过程...

能够写注册机了:

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 10000
using namespace std;

int main()
{
    char buffer[N];
    short int c;
    cout<<"please input name:\n";
    gets(buffer);
    if(strlen(buffer)<4)  //判断序列号长度
    {
        cout<<"Error!"<<endl;
    }
    else
    {
        c=buffer[0];
        c=c*0x29;
        c=c*2;
        cout<<"serial:"<<endl;
        printf("Serial: CW-%4d-CRACKED\r\n",c);
    }
    return 0;
}

技术分享

实话说,题目不难,但是nag,name/serial,key都涉及到了,作为新手的我也废了一些功夫...过程挺详细,比其他的详细多了(啰嗦..)。

 

以上是关于160个CrackMe 001 Acid burn的主要内容,如果未能解决你的问题,请参考以下文章

160CrackMe~001

CrackMe练习——Acid_burn

[CrackMe]160个CrackMe之19

[CrackMe]160个CrackMe之19

[CrackMe]160个CrackMe之40

[CrackMe]160个CrackMe之40