首页
社区
课程
招聘
[原创]一个CrackMe的算法分析
发表于: 2010-10-4 15:04 5906

[原创]一个CrackMe的算法分析

2010-10-4 15:04
5906
【CrackMe下载】http://bbs.pediy.com/showthread.php?t=121606
【使用工具】ollydbg
【作者】ddsoft
【声明】我是初学者,报着请教的心愿,希望各位前辈不吝赐教!!!
自己写的CrackMe自己慢慢分析,我在OD中下断bp GetWindowTextW 总是断到很奇怪的位置,让我没法分析。后来在输入表中下断,就找到关键点了。。。
004015FC   .  51            push    ecx
004015FD   .  8D4E 78       lea     ecx, dword ptr [esi+78]
00401600   .  C68424 980000>mov     byte ptr [esp+98], 1
00401608   .  E8 8B860000   call    CWnd::GetWindowTextW
0040160D   .  8D5424 18     lea     edx, dword ptr [esp+18]
00401611   .  52            push    edx
00401612   .  8D8E CC000000 lea     ecx, dword ptr [esi+CC]
00401618   .  E8 7B860000   call    CWnd::GetWindowTextW
0040161D   .  8B7424 18     mov     esi, dword ptr [esp+18]          ;  注册码的指针给esi
00401621   .  8B4E F4       mov     ecx, dword ptr [esi-C]           ;  ecx=注册码长度
00401624   .  8B7C24 14     mov     edi, dword ptr [esp+14]          ;  用户名的指针给edi
00401628   .  8B47 F4       mov     eax, dword ptr [edi-C]           ;  eax=用户名长度
0040162B   .  33D2          xor     edx, edx                         ;  edx=0
0040162D   .  83F9 08       cmp     ecx, 8                           ;  注册码长度要大于8
00401630   .  0F9CC2        setl    dl                               ;  小于8,置dl为1
00401633   .  33C9          xor     ecx, ecx                         ;  ecx=0
00401635   .  83F8 0A       cmp     eax, 0A                          ;  用户名长度要小于10位
00401638   .  0F9FC1        setg    cl                               ;  大于10位则置cl=1
0040163B   .  0BD1          or      edx, ecx
0040163D   .  33C9          xor     ecx, ecx
0040163F   .  83F8 05       cmp     eax, 5                           ;  用户名长度要大于5位
00401642   .  0F9CC1        setl    cl                               ;  小于5位,则置cl=1
00401645   .  0BD1          or      edx, ecx
00401647   .  74 14         je      short 0040165D                   ;  必须跳,如果dl或cl被置1,就不会跳走了。
00401649   .  889C24 940000>mov     byte ptr [esp+94], bl
00401650   .  8D46 F0       lea     eax, dword ptr [esi-10]
00401653   .  B9 FFFFFFFF   mov     ecx, -1
00401658   .  E9 ED000000   jmp     0040174A
0040165D   >  8B15 848F4300 mov     edx, dword ptr [438F84]          ;  常量字符串"33vc.com"指针放入edx
00401663   .  A1 888F4300   mov     eax, dword ptr [438F88]          ;  eax="vc"
00401668   .  8B0D 808F4300 mov     ecx, dword ptr [438F80]          ;  ecx="33"
0040166E   .  6A 52         push    52                               ; /n = 52 (82.)
00401670   .  894424 30     mov     dword ptr [esp+30], eax          ; |
00401674   .  894C24 28     mov     dword ptr [esp+28], ecx          ; |
00401678   .  8B0D 8C8F4300 mov     ecx, dword ptr [438F8C]          ; |
0040167E   .  895424 2C     mov     dword ptr [esp+2C], edx          ; |
00401682   .  66:8B15 908F4>mov     dx, word ptr [438F90]            ; |
00401689   .  8D4424 3A     lea     eax, dword ptr [esp+3A]          ; |
0040168D   .  53            push    ebx                              ; |c
0040168E   .  50            push    eax                              ; |s
0040168F   .  894C24 3C     mov     dword ptr [esp+3C], ecx          ; |
00401693   .  66:895424 40  mov     word ptr [esp+40], dx            ; |
00401698   .  E8 23E00100   call    memset                           ; \memset
0040169D   .  8D6C24 34     lea     ebp, dword ptr [esp+34]          ;  "vc.com"指针放入ebp
004016A1   .  83C4 0C       add     esp, 0C                          ;  平衡堆栈
004016A4   .  33F6          xor     esi, esi
004016A6   .  33C0          xor     eax, eax                         ;  i=0 ,用来循环
004016A8   .  895C24 1C     mov     dword ptr [esp+1C], ebx
004016AC   .  8BCF          mov     ecx, edi                         ;  ecx=用户名的指针
004016AE   .  2BEF          sub     ebp, edi
004016B0   .  EB 04         jmp     short 004016B6
004016B2   >  8B7C24 14     mov     edi, dword ptr [esp+14]
004016B6   >  85C0          test    eax, eax
004016B8   .  0F8C F2000000 jl      004017B0                         ;  跳向失败
004016BE   .  8B5F F4       mov     ebx, dword ptr [edi-C]           ;  ebx=用户名长度
004016C1   .  3BF3          cmp     esi, ebx
004016C3   .  0F8F E7000000 jg      004017B0                         ;  跳向失败
004016C9   .  0FB711        movzx   edx, word ptr [ecx]              ;  循环取用户名的字符,ecx在递增
004016CC   .  0FB71C29      movzx   ebx, word ptr [ecx+ebp]          ;  循环取"vc.com"的字符,ecx在递增
004016D0   .  0FB7FA        movzx   edi, dx
004016D3   .  0FB7FF        movzx   edi, di
004016D6   .  0FAFDF        imul    ebx, edi                         ;  两字符相乘,结果放ebx
004016D9   .  0FB7D2        movzx   edx, dx
004016DC   .  0FB7D2        movzx   edx, dx
004016DF   .  03D8          add     ebx, eax                         ;  sum=sum+user[i]*szBuf[i]+5*i
004016E1   .  03D3          add     edx, ebx                         ;  sum=sum+user[i]
004016E3   .  015424 1C     add     dword ptr [esp+1C], edx          
004016E7   .  83C0 05       add     eax, 5                           ;  每次加5
004016EA   .  46            inc     esi
004016EB   .  83C1 02       add     ecx, 2                           ;  ecx加2,所以每次取下一字符
004016EE   .  83F8 1E       cmp     eax, 1E                          ;  eax<30,所以循环6次
004016F1   .^ 7C BF         jl      short 004016B2                   ;  for 循环结束
004016F3   .  8B4424 1C     mov     eax, dword ptr [esp+1C]          ;  eax=sum
004016F7   .  8B4C24 14     mov     ecx, dword ptr [esp+14]          ;  用户名的指针
004016FB   .  50            push    eax                              ; /<%d>
004016FC   .  51            push    ecx                              ; |<%s>
004016FD   .  8D5424 2C     lea     edx, dword ptr [esp+2C]          ; |33vc.com的字符指针,为[esp+2C]
00401701   .  68 948F4300   push    00438F94                         ; |Format="%s%dddsoft"
00401706   .  52            push    edx                              ; |转换后的注册码存放地址,实际上就是"33vc.com"的指针地址
00401707   .  FF15 84344300 call    dword ptr [<&USER32.wsprintfW>]  ; \wsprintfW
0040170D   .  8B4424 28     mov     eax, dword ptr [esp+28]
00401711   .  83C4 10       add     esp, 10                          ;  平衡堆栈,esp+16
00401714   .  50            push    eax                              ; /输入的假注册码
00401715   .  8D4C24 28     lea     ecx, dword ptr [esp+28]          ; |push 4次,esp又加了16,所以注册码地址变为了[esp+28]
00401719   .  51            push    ecx                              ; |注册码地址入栈,此时明码出现
0040171A   .  FF15 A8324300 call    dword ptr [<&KERNEL32.lstrcmpW>] ; \lstrcmpW
00401720   .  85C0          test    eax, eax
00401722   .  75 14         jnz     short 00401738                   ;  跳过注册,爆破地方!!!
00401724   .  8B4C24 20     mov     ecx, dword ptr [esp+20]
00401728   .  50            push    eax
00401729   .  68 AC8F4300   push    00438FAC
0040172E   .  68 B88F4300   push    00438FB8
00401733   .  E8 BD610000   call    CWnd::MessageBoxW                ;  注册成功的对话框
00401738   >  C68424 940000>mov     byte ptr [esp+94], 0


对照源码看看
void CCrackMeDlg::OnBnClickedRegbtn()
{
    // TODO: 在此添加控件通知处理程序代码
   CString user;
   CString key;
   m_user.GetWindowText(user);
   m_key.GetWindowText(key);
   if ((user.GetLength()<5 )| (user.GetLength()>10 )| (key.GetLength()<8))
  {
      return;
  } 
  else
  {
     TCHAR szBuf[50]=TEXT("33vc.com");
      unsigned int sum=0;
      for (int i=0;i<6;i++)
      {
         sum+=user[i]*szBuf[i+2];
         sum+=user[i]+i*5;
      }
      wsprintf(szBuf,TEXT("%s")TEXT("%dddsoft"),user,sum);
      if (lstrcmp(szBuf,key)==0)
      {
          MessageBox(TEXT("感谢你的注册!"),TEXT("注册成功"),0);
      }
      return ;
  }
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 3144
活跃值: (2744)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
收藏学习了。
2010-10-4 21:18
0
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
怎么回事,我的OD,下了GetWindowTextA(W),GetDlgItemTextA(W)都没有断下来。搞得最后我还下了消息断点,为什么还是不行呢。再怎么搞也不行
2010-11-3 18:29
0
雪    币: 421
活跃值: (60)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
GetWindowTextA(W), 可以断下。我试了一下,而且原贴也写了。
2010-11-3 20:26
0
雪    币: 379
活跃值: (152)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
5
在IAT对GetWindowTextW下断点,注意满足条件,下面是我写的注册机,算法简单,如下:
#include <stdio.h>
#include <string.h>

char username[16];
char term[6]="vc.com";

int main()
{
     
  int userlen;
  int i,j;
  unsigned short int num1,num2;
  char szbuf[255];

  printf("please input username:\n");
  scanf("%s",username);
  userlen=strlen(username);

  if (userlen<10)
  {
    printf("username length is not less 10!\n");
        return -1;
  }
  
num1=0;
num2=0;

for (i=0,j=0;i<6;i++)
{
   num1=username[i]*term[i]; //两个ACII值相乘
   num1+=j;
   num1=num1+username[i];
   num2=num2+num1;
   j+=5;

}

sprintf(szbuf,"%s%dddsoft",username,num2);

printf("this sn:%s\n",szbuf);

return 0;

}
谢谢ddsoft提供crackMe练手程序,
2010-12-13 17:42
0
雪    币: 379
活跃值: (152)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
6
我解释一下为什么要在IAT下断点,因为GetWindowTextW这个函数不仅被主程序调用,也会被其主程序加载的dll调用,比如:comxxx.dll,但是你会发现其call GetWindowTextW有所不同,因为只有主程序体是通过IAT来方便找到GetWindowTextW这个函数的。所以,现在你应该明白这个为什么哪,
2010-12-13 17:46
0
雪    币: 9
活跃值: (67)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这是个不错的学习教材
2010-12-15 08:31
0
游客
登录 | 注册 方可回帖
返回