首页
社区
课程
招聘
[原创]一个非常简单的有提示的crackMe
发表于: 2010-3-30 16:47 6312

[原创]一个非常简单的有提示的crackMe

2010-3-30 16:47
6312
【文章标题】: 一个非常简单的有提示的crackMe
【文章作者】: shaochem
【作者邮箱】: xiaoqing325@gmail.com
【软件名称】: NBS-#1 CrackMe
【软件大小】: 44k
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 无
【编写语言】: vc++
【使用工具】: PEiD,OD
【操作平台】: Win9x/NT/2000/XP
【软件介绍】: 随便下的一个CrackMe,算法比较简单,适合初学者
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  用peid查了下,无壳,vc++编写。
  打开程序,点击Register,直接点“ok”,弹出“please enter u name and key.. ”,还好,基本上都有检测并给有提示。
  直接OD载入,直接“查找”--“所有字符串参考”,下断点,F9运行,输入:
  name:asdfg
  key:01234567890
  下一步,被段下后,我们先来看看代码:
  00401B7E   .  C2 1000       retn    10
  00401B81   >  8B3D A8704000 mov     edi, dword ptr [<&KERNEL32.lstrl>;  kernel32.lstrlenA
  00401B87   .  8D9424 1C0200>lea     edx, dword ptr [esp+21C]
  00401B8E   .  52            push    edx                              ; /String
  00401B8F   .  FFD7          call    edi                              ; \lstrlenA
  00401B91   .  83F8 03       cmp     eax, 3
  00401B94   .  7D 29         jge     short 00401BBF
  00401B96   >  8B8424 200600>mov     eax, dword ptr [esp+620]
  00401B9D   .  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  00401B9F   .  68 80824000   push    00408280                         ; |Title = "Error"
  00401BA4   .  68 88894000   push    00408988                         ; |Text = "Invalid name/key, please try again."
  00401BA9   .  50            push    eax                              ; |hOwner
  00401BAA   .  FF15 F0704000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  00401BB0   .  5F            pop     edi
  00401BB1   .  5E            pop     esi
  00401BB2   .  5D            pop     ebp
  00401BB3   .  33C0          xor     eax, eax
  00401BB5   .  5B            pop     ebx
  00401BB6   .  81C4 0C060000 add     esp, 60C
  00401BBC   .  C2 1000       retn    10
  00401BBF   >  8D8C24 1C0400>lea     ecx, dword ptr [esp+41C]
  00401BC6   .  51            push    ecx
  00401BC7   .  FFD7          call    edi
  00401BC9   .  83F8 22       cmp     eax, 22                          ;  比较你输入的key与34的大小
  00401BCC   .  74 29         je      short 00401BF7                   ;  等于就跳,否则就完蛋
  00401BCE   >  8B9424 200600>mov     edx, dword ptr [esp+620]
  00401BD5   .  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  00401BD7   .  68 80824000   push    00408280                         ; |Title = "Error"
  00401BDC   .  68 88894000   push    00408988                         ; |Text = "Invalid name/key, please try again."
  00401BE1   .  52            push    edx                              ; |hOwner
  00401BE2   .  FF15 F0704000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  它首先取用户名和3比较,不能小于3,小于3就完蛋了,然后取key的长度,并判断key的位数是否为34,否则就完蛋,那我们明白了,我输入的key有问题。
  继续,重新载入程序,运行输入:
  name:asdfg
  key:0123456789012345678900123456789001234
  继续下一步,我们还是先来看看代码:
  00401BF7   > \8D8424 1C0400>lea     eax, dword ptr [esp+41C]
  00401BFE   .  33ED          xor     ebp, ebp
  00401C00   .  50            push    eax
  00401C01   .  32DB          xor     bl, bl
  00401C03   .  896C24 1C     mov     dword ptr [esp+1C], ebp
  00401C07   .  FFD7          call    edi                              ;  取key的长度
  00401C09   .  85C0          test    eax, eax
  00401C0B   .  7E 45         jle     short 00401C52
  00401C0D   .  33F6          xor     esi, esi
  00401C0F   >  8A8434 1C0400>mov     al, byte ptr [esp+esi+41C]       ;  取第一位
  00401C16   .  FEC3          inc     bl                               ;  应该是个计数器
  00401C18   .  3C 2D         cmp     al, 2D                           ;  每一位和-号比较
  00401C1A   .  74 1D         je      short 00401C39                   ;  相同则跳
  00401C1C   .  0FBF4C24 18   movsx   ecx, word ptr [esp+18]
  00401C21   .  50            push    eax
  00401C22   .  88440C 20     mov     byte ptr [esp+ecx+20], al        ;  不等就往后移位,存在后面
  00401C26   .  E8 E5080000   call    00402510
  00401C2B   .  84C0          test    al, al
  00401C2D   .^ 0F85 63FFFFFF jnz     00401B96
  00401C33   .  FF4424 18     inc     dword ptr [esp+18]               ;  取下一位
  00401C37   .  EB 07         jmp     short 00401C40                   ;  直接跳走
  00401C39   >  80FB 05       cmp     bl, 5                            ;  然后把"-"号的位置与5比较
  00401C3C   .  75 2A         jnz     short 00401C68                   ;  不等就跳,这里跳走就完蛋
  00401C3E   .  32DB          xor     bl, bl                           ;  bl清零
  00401C40   >  8D9424 1C0400>lea     edx, dword ptr [esp+41C]
  00401C47   .  45            inc     ebp
  00401C48   .  52            push    edx
  00401C49   .  0FBFF5        movsx   esi, bp
  00401C4C   .  FFD7          call    edi
  00401C4E   .  3BF0          cmp     esi, eax                         ;  这里应该是循环的条件
  00401C50   .^ 7C BD         jl      short 00401C0F                   ;  小于继续循环,大则继续执行
  00401C52   > \0FBF5424 18   movsx   edx, word ptr [esp+18]
  00401C57   .  8D4424 1C     lea     eax, dword ptr [esp+1C]          ;这里取出除掉“-”号的key
  00401C5B   .  50            push    eax
  00401C5C   .  C64414 20 00  mov     byte ptr [esp+edx+20], 0
  00401C61   .  FFD7          call    edi
  00401C63   .  83F8 1C       cmp     eax, 1C                          ;  这里判断key里是否有6个“-”号
  00401C66   .  74 29         je      short 00401C91                   ;  有就跳走,没有就完蛋
  00401C68   >  8B8C24 200600>mov     ecx, dword ptr [esp+620]
  00401C6F   .  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  00401C71   .  68 80824000   push    00408280                         ; |Title = "Error"
  00401C76   .  68 88894000   push    00408988                         ; |Text = "Invalid name/key, please try again."
  00401C7B   .  51            push    ecx                              ; |hOwner
  00401C7C   .  FF15 F0704000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  
  
  它首先一个循环取每一位key来判断key里是否存在“-”号,如果存在“-”号就把“-”号的位置与5比较,不等就完蛋了,不存在就把该位后移保存,继续取下一位,直到key取完,取完后取出去掉“-”号的key,
  判断它的长度是否为28,也就是里面是否有6个“-”号,没有就完蛋了,有就继续,这说明我的key还是有问题的。继续。
  我们先继续看代码:
  00401C95   .  6A 03         push    3                                ; /n = 3
  00401C97   .  8D4424 14     lea     eax, dword ptr [esp+14]          ; |
  00401C9B   .  52            push    edx                              ; |String2
  00401C9C   .  50            push    eax                              ; |String1
  00401C9D   .  FF15 30704000 call    dword ptr [<&KERNEL32.lstrcpynA>>; \lstrcpynA
  00401CA3   .  8D4C24 10     lea     ecx, dword ptr [esp+10]          ;  取前2个字符
  00401CA7   .  51            push    ecx
  00401CA8   .  E8 56090000   call    00402603
  00401CAD   .  8BF8          mov     edi, eax                         ;  把字符变数字
  00401CAF   .  83C4 04       add     esp, 4
  00401CB2   .  33D2          xor     edx, edx
  00401CB4   .  66:83FF 0C    cmp     di, 0C                           ;  把该数字与12比较
  00401CB8   .  0F9FC2        setg    dl                               ;  大则置1
  00401CBB   .  33C0          xor     eax, eax
  00401CBD   .  66:83FF 02    cmp     di, 2                            ;  把该数和2比较
  00401CC1   .  0F9CC0        setl    al                               ;  小则置1
  00401CC4   .  0BD0          or      edx, eax                         ;  把结果与0或运算
  00401CC6   .^ 75 A0         jnz     short 00401C68                   ;  不=0则跳,跳走就完蛋
  
  这里又是一个判断,取你注册码key里面的前2位并转换为数字,并判断它必须大于2小于12,否则就完蛋,到这里对输入的验证基本上算是完毕了,好累啊。
  好,我们继续看代码:
  00401CC8   .  8B35 34704000 mov     esi, dword ptr [<&KERNEL32.lstrc>;  kernel32.lstrcpyA
  00401CCE   .  8D5424 10     lea     edx, dword ptr [esp+10]
  00401CD2   .  68 E4924000   push    004092E4                         ; /String2 = ""
  00401CD7   .  52            push    edx                              ; |String1
  00401CD8   .  FFD6          call    esi                              ; \lstrcpyA
  00401CDA   .  8D4424 16     lea     eax, dword ptr [esp+16]
  00401CDE   .  68 E4924000   push    004092E4                         ; /String2 = ""
  00401CE3   .  50            push    eax                              ; |String1
  00401CE4   .  FFD6          call    esi                              ; \lstrcpyA
  00401CE6   .  0FBFF7        movsx   esi, di                          ;  注意这个长度就是你注册码的前2位数字,用于控制后面取字符
  00401CE9   .  0FBE8424 1C02>movsx   eax, byte ptr [esp+21C]          ;  取用户名第一个字母
  00401CF1   .  8A4C34 1C     mov     cl, byte ptr [esp+esi+1C]        ;  取注册码的前2位长度的字符
  00401CF5   .  8A5434 1D     mov     dl, byte ptr [esp+esi+1D]        ;  接着后面的字符
  00401CF9   .  8B3D 08714000 mov     edi, dword ptr [<&USER32.wsprint>;  USER32.wsprintfA
  00401CFF   .  884C24 10     mov     byte ptr [esp+10], cl
  00401D03   .  50            push    eax                              ; /<%X>
  00401D04   .  8D4C24 1A     lea     ecx, dword ptr [esp+1A]          ; |这里开始构造字符串了
  00401D08   .  32DB          xor     bl, bl                           ; |
  00401D0A   .  68 84894000   push    00408984                         ; |Format = "%X"
  00401D0F   .  51            push    ecx                              ; |s
  00401D10   .  885424 1D     mov     byte ptr [esp+1D], dl            ; |
  00401D14   .  885C24 1E     mov     byte ptr [esp+1E], bl            ; |
  00401D18   .  FFD7          call    edi                              ; \wsprintfA
  00401D1A   .  8B2D 2C704000 mov     ebp, dword ptr [<&KERNEL32.lstrc>;  kernel32.lstrcmpA
  00401D20   .  83C4 0C       add     esp, 0C
  00401D23   .  8D5424 16     lea     edx, dword ptr [esp+16]          ;  用户名的第一位字符
  00401D27   .  8D4424 10     lea     eax, dword ptr [esp+10]          ;  刚才取的2位字符
  00401D2B   .  52            push    edx                              ; /string2=61
  00401D2C   .  50            push    eax                              ; |String1
  00401D2D   .  FFD5          call    ebp                              ; \lstrcmpA
  00401D2F   .  85C0          test    eax, eax
  00401D31   .  75 02         jnz     short 00401D35                   ;  比较,不同则跳,跳走就完蛋
  00401D33   .  B3 01         mov     bl, 1                            ;  这里应该是个计数的标志位
  00401D35   >  0FBE8424 1D02>movsx   eax, byte ptr [esp+21D]          ;  用户名的第二位
  00401D3D   .  8A4C74 1C     mov     cl, byte ptr [esp+esi*2+1C]      ;  又要开始截取2位进行比较了
  00401D41   .  8A5474 1D     mov     dl, byte ptr [esp+esi*2+1D]
  00401D45   .  884C24 10     mov     byte ptr [esp+10], cl
  00401D49   .  50            push    eax
  00401D4A   .  8D4C24 1A     lea     ecx, dword ptr [esp+1A]
  00401D4E   .  68 84894000   push    00408984                         ;  ASCII "%X"
  00401D53   .  51            push    ecx
  00401D54   .  885424 1D     mov     byte ptr [esp+1D], dl
  00401D58   .  C64424 1E 00  mov     byte ptr [esp+1E], 0
  00401D5D   .  FFD7          call    edi
  00401D5F   .  83C4 0C       add     esp, 0C
  00401D62   .  8D5424 16     lea     edx, dword ptr [esp+16]          ;  用户名的第二位
  00401D66   .  8D4424 10     lea     eax, dword ptr [esp+10]          ;  截取的2位注册码
  00401D6A   .  52            push    edx
  00401D6B   .  50            push    eax
  00401D6C   .  FFD5          call    ebp                              ;  开始比较了
  00401D6E   .  85C0          test    eax, eax
  00401D70   .  75 02         jnz     short 00401D74                   ;  不等就跳了,这里跳走就完蛋
  00401D72   .  FEC3          inc     bl                               ;  相等,计数器就+1
  00401D74   >  8B35 A8704000 mov     esi, dword ptr [<&KERNEL32.lstrl>;  kernel32.lstrlenA
  00401D7A   .  8D4C24 1C     lea     ecx, dword ptr [esp+1C]
  00401D7E   .  51            push    ecx                              ; /String
  00401D7F   .  FFD6          call    esi                              ; \lstrlenA
  00401D81   .  0FBFD0        movsx   edx, ax
  00401D84   .  8A4C14 1A     mov     cl, byte ptr [esp+edx+1A]        ;  cl取倒数第2位
  00401D88   .  C64424 12 00  mov     byte ptr [esp+12], 0
  00401D8D   .  8D4414 1C     lea     eax, dword ptr [esp+edx+1C]
  00401D91   .  884C24 10     mov     byte ptr [esp+10], cl
  00401D95   .  8A50 FF       mov     dl, byte ptr [eax-1]             ;  取注册码倒数第一位
  00401D98   .  8D8424 1C0200>lea     eax, dword ptr [esp+21C]
  00401D9F   .  50            push    eax                              ; /String
  00401DA0   .  885424 15     mov     byte ptr [esp+15], dl            ; |
  00401DA4   .  FFD6          call    esi                              ; \lstrlenA
  00401DA6   .  0FBFC8        movsx   ecx, ax
  00401DA9   .  8D4424 16     lea     eax, dword ptr [esp+16]
  00401DAD   .  0FBE940C 1B02>movsx   edx, byte ptr [esp+ecx+21B]
  00401DB5   .  52            push    edx                              ;  又开始构造字符了
  00401DB6   .  68 84894000   push    00408984                         ;  ASCII "%X"
  00401DBB   .  50            push    eax
  00401DBC   .  FFD7          call    edi
  00401DBE   .  83C4 0C       add     esp, 0C
  00401DC1   .  8D4C24 16     lea     ecx, dword ptr [esp+16]          ;  用户名的最后一位
  00401DC5   .  8D5424 10     lea     edx, dword ptr [esp+10]          ;  最后取的2位注册码
  00401DC9   .  51            push    ecx
  00401DCA   .  52            push    edx
  00401DCB   .  FFD5          call    ebp                              ;  比较
  00401DCD   .  85C0          test    eax, eax
  00401DCF   .  75 02         jnz     short 00401DD3                   ;  不等就跳,跳走就完蛋的
  00401DD1   .  FEC3          inc     bl                               ;  相等计数器就+1
  00401DD3   >  80FB 03       cmp     bl, 3                            ;  判断你是否经过3次比较
  00401DD6   .^ 0F85 F2FDFFFF jnz     00401BCE                         ;  不是就挂了
  00401DDC   .  8BAC24 200600>mov     ebp, dword ptr [esp+620]
  00401DE3   .  8B1D F0704000 mov     ebx, dword ptr [<&USER32.Message>;  USER32.MessageBoxA
  00401DE9   .  6A 30         push    30                               ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  00401DEB   .  68 78894000   push    00408978                         ; |Title = "Key valid!"
  00401DF0   .  68 34894000   push    00408934                         ; |Text = "Thank you for your purchase, the software is now fully functional."
  00401DF5   .  55            push    ebp                              ; |hOwner
  00401DF6   .  FFD3          call    ebx                              ; \MessageBoxA
  00401DF8   .  6A 30         push    30                               ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  00401DFA   .  68 28894000   push    00408928                         ; |Title = "Excellent!"
  00401DFF   .  68 04894000   push    00408904                         ; |Text = "CONGRATULATIONS! You have made it!"
  00401E04   .  55            push    ebp                              ; |hOwner
  00401E05   .  FFD3          call    ebx                              ; \MessageBoxA
  
  它在这里,首先取你输入的用户名,再取key前面的前2位数字作为长度,在key里面截取那个长度的后2位字符并拼接起来,来把它和用户名第一位做比较。不等就完蛋。
  然后取用户名的第二位,与key里面再取两位字符拼接起来做比较,要相等,最后取用户名的最后一位和key的最后2位做比较,不等就完蛋。

  大概的算法就是这样了。本人第一次写文章,分析crackme。不对之处还请大家指出!
  
--------------------------------------------------------------------------------
【经验总结】
  整个过程就是首先判断你输入的数据是否合符要求,符合要求后再取用户名的一位,然后在key里取2位拼接为字符串来比较
  。这个crackme很简单,算法也很清晰,非常适合新手朋友,来学习练习。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2010年03月30日 下午 04:43:19

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (16)
雪    币: 148
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
老大来给个邀请码啊
2010-3-30 17:30
0
雪    币: 148
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
里面附带源码,有兴趣的朋友可以根据你分析出来的注册码,来得到打开源码密码的小提示哦
2010-3-31 09:47
0
雪    币: 116
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习,帮你顶以下。

另外下面那句我有点不太明白,希望给小弟讲解一下,这里的al到底存到什么地方了啊?

00401C22   .  88440C 20     mov     byte ptr [esp+ecx+20], al        ;  不等就往后移位,存在后面
2010-3-31 11:20
0
雪    币: 16
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
没邀请码  舍不得下  早日转正
2010-3-31 11:38
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
6
这个立意非常好
2010-3-31 12:09
0
雪    币: 66
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
学习了,通过注册码得源码,很好的创意哈!
2010-3-31 12:34
0
雪    币: 148
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
[QUOTE=olxdf;783884]学习,帮你顶以下。

另外下面那句我有点不太明白,希望给小弟讲解一下,这里的al到底存到什么地方了啊?

00401C22   .  88440C 20     mov     byte ptr [esp+ecx+20], al        ;  不等就往后移位,存在后面[/QUOTE]

注意哦,这里的ecx其实是循环变量,他在和“-”号比较的时候,不等就把al放在后面,当ecx=0的时候就是byte ptr【esp+20】,然后ecx+1,然后继续。
2010-3-31 15:09
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
9
注册机
/*可生成一个可用的serial,假设了一个比较简单的状况*/
/*指令很奇怪*/

#include	"stdafx.h"
#include	<string.h>
int main(int argc, char* argv[])
{
	char serial[35]="1000-0000-00%X-0000-0000-%X00-00%X";
	char name[10];
	printf("Plz input your name:\n");
	scanf("%s",name);
	sprintf(serial,serial,name[0],name[1],name[strlen(name)-1]);
	printf("This is a valid serial:%s\n",serial);
	return 0;
}
2010-4-2 11:21
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
诶,等到转正了再下载吧,现在我可舍不得
2010-4-2 11:42
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
11
http://www.22shared.com/c014e560b9.htm
帮你个忙,够意思吧
2010-4-2 11:45
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
12
0241-4166-6666-6666-6666-6666-6641
英语不好,google了半天才搞明白事什么意思
2010-4-2 12:03
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
写出注册机那就完美了
2010-4-2 12:40
0
雪    币: 148
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
我当初也看了半天
2010-4-2 19:40
0
雪    币: 2908
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
偶是新手 有些还不太懂 先慢慢学习学习吧
2010-4-2 19:51
0
雪    币: 316
活跃值: (326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
试试参考下
2010-4-2 20:03
0
雪    币: 521
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
等转正了在下载吧先支持着
2010-4-2 23:29
0
游客
登录 | 注册 方可回帖
返回
//