首页
社区
课程
招聘
[原创]Pj一个超简单的Crackme,适合像我一样的新手~_~
发表于: 2006-11-9 21:27 12281

[原创]Pj一个超简单的Crackme,适合像我一样的新手~_~

2006-11-9 21:27
12281

【文章标题】: Pj一个超简单的Crackme,适合像我一样的新手~_~
【文章作者】: 易leww/今朝/Perforce
【下载地址】: http://rapidshare.com/files/2627049/crackme.rar.html
【使用工具】: Peid,Ollydbg
【作者声明】: 新手入门ing,将自己刚取得的一点成就拿出来与大家分享,不足之处大虾们多多指教(哦,由于文章太初级,老鸟不看也罢)。

     也就Crackmes.de上最简单级别的一个Crackme,建议最好不要先看本文,自己去调试一下到不会的地方再来参考;这也是我的体会,总觉得不少时候自己去分析还好,越是看别人的分析还就越迷,看着看着就头大了……(唉,没办法,人太笨了) 好了,废话少说,开始::)

**********************************************************************
                        *>>>PART    1<<<*

     用PEID查下,“MASM32 / TASM32”好,没壳,有壳的话就不会有这篇废话了,俺这可是第一次耶也。。

    “那你还查什么壳哪你,浪费感情!”

    “例行公事呗,前辈们这样教的~~~~~~~~”

     先运行程序看一下,,,,怎么?竟然有个烦人的东西(Nag)!还说什么“Patch me if you can ”,这不挑衅吗这。。

     啊?你还从来没见过这东西呢?嘿嘿,来,握握手~~~,俺也是第一次上路就碰到它了   

     确定之后界面出来了,界面看起来还挺大方的嘛。点Check,没反应!随便输入点什么东西再点,还是没反应!!唉,真命苦呀,第一次就碰上了这么个东西~~~~ 得,不管!硬着头皮上吧

     用OD加载后,先别动!四处找找~~~~~~哦,发现反汇编窗口的注释里面有 Title="Nag" 和 Text="Patch me if you can" 下面还有个红色的MessageBoxA,看名字就知道是弹出消息框!这下知道那个NAG怎么出来的了。

00401037      E8 3B040000   call    00401477

0040103C      6A 10         push    10
0040103E      68 35304000   push    00403035                      ;  ASCII "Nag"
00401043      68 21304000   push    00403021                      ;  ASCII "Patch Me if you can"
00401048      6A 00         push    0
0040104A      E8 33060000   call    <jmp.&user32.MessageBoxA>

     左边的汇编语句是几个Push然后后面一个Call,看来就是这个CALL把那个NAG给CALL了出来,得,干掉它!

     怎么干?
     Nop!!  (选中那行之后,按空格键,弹出的框里填Nop)

     既然那几个Push是给CALL送东西(参数)的,也同时Nop掉 。  

     好,现在我们已经把从0010103C到0040104A的四个PUSH和一个CALL都NOP掉了;按一下OD中有两个向左箭头的按钮(或Ctrl+F12)重新加载程序,F9运行。。。
      "What???"
      "Patch me if you can"!!!!
       明明NOP掉了呀
       怎么办?再看看喽~~~~~     

  注:NOP掉之后,再CTRL+F12重新加载程序的话,原来NOP掉的东西会又出现,但是将以灰颜色显示。

     我们先不要CTRL+F12,看一下原来NOP掉的地方~~~~~发现什么了?   哪里NOP了,分明都还在嘛!但是,,,我们的的确确NOP过呀!

     怎么回事?  

     好,在NOP过的地方下断,我们看看到底怎么一回事。为了保险我们断点稍微靠前下些,我就在00401031处的PUSH处按F2(下断点)。

     CTRL+F12重新加载程序,将刚才的NOP(0040103C-0040104A)过程重复一遍,然后F9运行,程序断在我们所设的断点处,好,看好了:

     现在0010103C至0040104A显示的还是NOP,我们按F8步过这几个汇编指令:PUSH-->MOV-->ADD(F8到这里时看下下面是不是NOP,好,没有变)-->CALL(到这里时再看下下面是不是NOP,还好,还是没变),打住!

     等下再F8,怎么?你偏打不住?那好,你再F8,注意到下面没~~~~~什么?代码一下子又回来了!!!

     怎么回事??

     哦,原来那个CALL又把我们NOP掉的代码给CALL了回来!!!  嘿!好哇,谁怕谁呀,以为我不敢我把你这个CALL也给NOP掉!!

     再CTRL+F12,将00401037-0040104A全给NOP掉,F9运行,哈,哈哈,NAG没了!!!
     --------不要忘了保存哦,不然又要NOP半天(右键--复制到可执行文件--所有修改/全部复制>在弹出的窗口里单击右键,选保存文件,覆盖原文件)

       注:1.其实在00401037处也可以直接JMP到0040104F,省得NOP半天。
           2.仅仅如此的话,程序按下Check退出时会报错。(00401449处的CALL crackme.004015B3引起,要把这个CALL也给NOP掉才行,至于具体原因我也没搞太清楚 ,还望高手指点迷津)
**********************************************************************
                        *>>>PART    2<<<*

        大多是文字,代码就那么点,今天的主角倒好像是那个Nag了?所以我不担心你被一大篇满满的代码吓着了 或者,,,,是我废话太多?讲究一下喽~~~~

       改掉上面几个地方之后,我们分析它的算法:
       输入用户名和密码,这里我输入的是:Perforce/123456;
            Check!
               没反应~~~~~

       由于按CHECK没反应,我们下函数断点(断点详细信息请参考CCDebuger的 OllyDBG入门教程):我们在反汇编窗口击右键-->查找-->当前模块中的名称(标签),我们找到GetWindowTextA(此函数用来取我们输入文本框里的用户名和密码),双击进入反汇编窗口,前后看看,哦,下面还有一个长像差不多的GetWindowTextLengthA,从名字猜一下它的用途?

       对,它用来计算我们所输入内容的长度,两个函数中间的是此看不懂的东西不用去管了,我们就在GetWindowTextLengthA函数的00401290处按F2切换断点。
       好了,CTRL+F12,F9运行,输入Perforce/123456,Check!

       程序断在了我们设断的00401290,F8一下,注意EAX的值(为什么是8??还记不记得GetWindowTextLengthA是干什么用的?)

00401290   .  FF15 683C4000 call    [403C68]             ;  <jmp.&user32.GetWindowTextLengthA>
00401296   .  83F8 05       cmp     eax, 5           ;将用户名长度与5比较
00401299   .  0F8C 43010000 jl      004013E2         ;小于5跳走
0040129F   .  83F8 08       cmp     eax, 8           ;大于等于8跳走
004012A2   .  0F8D 3A010000 jge     004013E2         ;我第一次输入的Perforce是8位,从这儿跳走了,导致失败
004012A8   .  8BC8          mov     ecx, eax         ;用户名长度赋给计数器
004012AA   .  890D 543C4000 mov     [403C54], ecx
004012B0   .  33DB          xor     ebx, ebx
004012B2   .  8D35 54304000 lea     esi, [403054]    ;Perforc的地址给ESI
004012B8   .  8D3D 54324000 lea     edi, [403254]    ;一个内存地址@1给EDI
004012BE   >  8A4431 FF     mov     al, [ecx+esi-1]  ;取esi处的数据(逆向,即依次为:c-r-o-f-r-e-P)
004012C2   .  80F9 04       cmp     cl, 4            
004012C5   .  74 13         je      short 004012DA   ;循环到CL==4时,将对应位赋值为-后,直接进入下次循环
004012C7   .  3C 4D         cmp     al, 4D           
004012C9   .  7C 04         jl      short 004012CF   ;所输入字符ASCII码值小于4D时,跳到加15处
004012CB   .  2C 11         sub     al, 11           ;不小于4D就减11
004012CD   .  EB 02         jmp     short 004012D1
004012CF   >  04 15         add     al, 15
004012D1   >  32C1          xor     al, cl           ;al与cl异或后,所得值放入al
004012D3   .  34 02         xor     al, 2            ;将上述al值与2异或后,放入al
004012D5   .  88043B        mov     [ebx+edi], al    ;al送至另一内存地址@1(所送数据为WeY-'T<)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
004012D8   . /EB 04         jmp     short 004012DE
004012DA   > |C6043B 2D     mov     byte ptr [ebx+edi], 2>
004012DE   > \43            inc     ebx
004012DF   .^ E0 DD         loopdne short 004012BE    ;循环ecx次
004012E1   .  8D35 54324000 lea     esi, [403254]     ;将地址@1送esi
004012E7   .  8D3D 54344000 lea     edi, [403454]     ;将另一地址@2送edi
004012ED   .  8B0D 543C4000 mov     ecx, [403C54]     ;循环次数送入ecx
004012F3   .  33DB          xor     ebx, ebx




00401328   >  80F9 04       cmp     cl, 4             ;同上
0040132B   .  74 17         je      short 00401344
0040132D   .  8A4431 FF     mov     al, [ecx+esi-1]   ;将@1处得到的新数据逆向分别送入al(依次为<T'-YeW)
00401331   .  3C 4D         cmp     al, 4D            ;以下重复上面操作
00401333   .  7C 04         jl      short 00401339
00401335   .  2C 11         sub     al, 11
00401337   .  EB 02         jmp     short 0040133B
00401339   >  04 15         add     al, 15
0040133B   >  32C1          xor     al, cl
0040133D   .  34 02         xor     al, 2
0040133F   .  88043B        mov     [ebx+edi], al     ;将得到的新数据送入@2(所送数据为TGH-ITE)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00401342   . /EB 04          jmp     short 00401348
00401344   > |C6043B 2D      mov     byte ptr [ebx+edi], 2D
00401348   > \43             inc     ebx
00401349   .^ E0 DD          loopdne short 00401328
0040134B   .  C705 603C4000 >mov     dword ptr [403C60], <jmp.&user>
00401355   .  832D 603C4000 >sub     dword ptr [403C60], 7
***********************************
0040135C   .  68 54324000    push    00403254                       ;  ASCII "WeY-`T<"---第一次循环得到的数据
00401361   .  68 54344000    push    00403454                       ;  ASCII "TGH-ITE"---第二次循环得到的数据
00401366   .  8305 5C3C4000 >add     dword ptr [403C5C], 2
0040136D   .  FF15 5C3C4000  call    [403C5C]                       ;  <jmp.&kernel32.lstrcatA>---连接字符串,得到注册码。

*********************************************************************

第一次我输入的Perforce是8位,从0040129F处跳走了;
既然用户名长度应是5-7位,我只好把名字给割了尾巴:Perforc,密码还是123456。

  上面已经写得很清楚,大体上就是

        A:先将所输入的5至7位的用户名(按逆向)各位所对应的ASCII值进行:若小于4D则加15,否则减去11-->与ecx异或(ecx的值由7至1递减)-->与2异或-->将循环得到的字符串(WeY-`T<)送入地址@1。

        B:然后将@1处得到的新字串代替上步中的用户名,执行相同操作后,将新字串(TGH-ITE)送入@2处。

        C:将A、B所得字串连接(@2字串在@1字串前面),即为注册码

**********************************************************************
注册机:

C学得很烂,可能显得冗余混乱:)

main()
{
int i,j,b=1;char a,user[100]={0};
input:printf("Please input username:");
      scanf("%s",user);
/*      scanf("%c",&a);*/
        i=strlen(user);
        if(i<5||i>=8)
         { printf("The len of username must between 5 and 8!\n");
           goto input;}
        printf("The username is:%s\n",user);

        for(j=0;j<i/2;j++)
          { a=user[j];
            user[j]=user[i-j-1];
            user[i-j-1]=a;
          }
        /*printf("user=%s",user);*/
loop:        for(j=0;j<=i-1;j++)
          if   (user[j]<77) user[j]=user[j]+21;
          else  user[j]=user[j]-17;
        for(j=0;j<i;j++)
         {if(j!=i-4){user[j]=user[j]^(i-j);
                   user[j]=user[j]^2;
                   }
          else user[j]=45;
         }
/*        printf("nnnn:%s\t",user);*/
        for(j=0;j<i;j++)
        user[j+i*(b+1)]=user[j];
        if(b==1)
         {for(j=0;j<i/2;j++)
          { a=user[j];
           user[j]=user[i-j-1];
           user[i-j-1]=a;
          }b=b-1;goto loop;
         }
        if(b==0)
         printf("The serial is:%s\n",user+i);
/*         printf("Press ENTER to quit...");
         scanf("%c",&a);*/

***到这里我总算懂得了以前前辈们写专门供给我们这些菜鸟看的破文时有多辛苦了***

        另:连接之后生成的可执行文件输入用户名之后看不清注册码的就马上退出了,有什么办法让它停下吗?我不是学计算机专业的,才刚开始自学,所以可能许多比较基础的知识都不懂


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (40)
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
2
很不错了,继续下去有成绩的
2006-11-9 22:25
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
3
非常之详细!!建议大家都自己试试!

写文章不错哦,希望能再看到你的文章。

刚开始学就这么厉害。有前途!!
2006-11-10 07:22
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
最初由 KAN 发布
很不错了,继续下去有成绩的

最初由 binbinbin 发布
非常之详细!!建议大家都自己试试!

写文章不错哦,希望能再看到你的文章。

刚开始学就这么厉害。有前途!!


    虽说这是第一次,可其实这也是四五天前的了,因为当时还有点疑惑,没有敢拿出来拽~~~~不过,既然在论坛成长,总不能光吃你们这些前辈们的而不干点什么,就写了篇这么菜的,不要笑话哟
    呵呵,给我长了信心,多谢多谢;
    继续学习,继续吃老鸟,继续奉献
2006-11-10 09:31
0
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
最初由 易leww 发布
虽说这是第一次,可其实这也是四五天前的了,因为当时还有点疑惑,没有敢拿出来拽~~~~不过,既然在论坛成长,总不能光吃你们这些前辈们的而不干点什么,就写了篇这么菜的,不要笑话哟
呵呵,给我长了信心,多谢多谢;
继续学习,继续吃老鸟,继续奉献


文章不错,希望大家都像 易leww 那样参与进来,这样有个气氛,学习起来的效果也更好。
2006-11-10 09:45
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
6
最初由 kanxue 发布
文章不错,希望大家都像 易leww 那样参与进来,这样有个气氛,学习起来的效果也更好。


老大英名~~嘻嘻
2006-11-10 10:17
0
雪    币: 191
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
能把crackme.rar附上吗,我下载不了
2006-11-10 11:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你的功力很高啊。你怎么学的,我学了好几个月了还是入门
2006-11-10 13:01
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
最初由 happyboygd 发布
能把crackme.rar附上吗,我下载不了

已经上传,开始时没有权限(其实这帖子也就骗了个上传权限)

最初由 wangjinlei 发布
你的功力很高啊。你怎么学的,我学了好几个月了还是入门


虽说这是前几天的第一次上手,可我也学了近两个月的时间了。

基本我是按看雪老大的解密基础知识入门(http://bbs.pediy.com/showthread.php?s=&threadid=31840)一文中所述 学的。

我们上学期刚学了C语言,自己也马马虎虎的看过点汇编,不过后来发现差太多,就又看了中山大学的汇编教学课程。期间也反复看了CCDebuger的    OllyDBG入门教程。 如看雪老大所说“为了水平提高的更快些,建议再掌握Win32编程……”,多学点打好了基础才能进步快,所以又开始学罗云彬的那本 Win32环境下汇编语言程序设计 。我觉得如果不知如何去学,大可在这里找到方向后 自己再去努力。
2006-11-10 14:59
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
最初由 易leww 发布
已经上传,开始时没有权限(其实这帖子也就骗了个上传权限)
2006-11-10 15:00
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jxm
11
你在学习上很有钻研精神。中山的教程,我还没看完……
2006-11-10 15:37
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
强..刚学就能这么有思路.支持.
2006-11-11 18:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
收藏了学习中,好东西。长见识了

2006-11-11 20:27
0
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习中...........
2006-11-12 09:37
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
我学习破解1年多了,以前主要是玩玩,现在因工作需要,要认真学习了。你的帖子很不错啊,向你致敬,共同提高啊
2006-11-12 23:48
0
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习哦,最近太忙,过些日子再回来看看
2006-11-13 09:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
正在学习,支持一下z
2006-11-13 09:57
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18

楼主强~~我学习快半年了可对算法还是一窍不通~
2006-11-13 11:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
学习中……
感谢分享,收藏!!
2006-11-13 14:23
0
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
生成了注册码停不住啊。简单简单

输入exit();

代码的最后一行,然后编译运行就会生成注册码后要求按下任意键退出了。

如果编译错误,在文件头加上。

#include <studio.h>
2006-11-13 15:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
学习中...........
2006-11-13 15:51
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
这样的文章正适合我,谢谢楼主了
2006-11-14 22:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
学习一下!
2006-11-14 22:49
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
学习一下,很不错

2006-11-15 10:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
好文章,新手也能出文章佩服!
2006-11-16 10:58
0
游客
登录 | 注册 方可回帖
返回
//