首页
社区
课程
招聘
[原创]分析论坛中一个简单的crackme
发表于: 2012-5-2 01:04 2345

[原创]分析论坛中一个简单的crackme

2012-5-2 01:04
2345
【文章标题】: 分析一个crackme
【文章作者】: zjw023
【软件名称】: ncrackme.exe
【下载地址】: http://bbs.pediy.com/upload/files/1084801702.zip
【作者声明】: 感谢riijj提供的crackme教学贴,自己分析了好久,做出来还是很兴奋的。

直接到算法部分进行分析

00401230     /$  8B0D BC564000 mov ecx,dword ptr ds:[4056BC]
00401236     |.  83EC 30       sub esp,30
00401239     |.  8D4424 00     lea eax,dword ptr ss:[esp]
0040123D     |.  53            push ebx
0040123E     |.  56            push esi
0040123F     |.  8B35 94404000 mov esi,dword ptr ds:[<&USER32.GetD>;  USER32.GetDlgItemTextA
00401245     |.  6A 10         push 10                             ; /Count = 10 (16.)
00401247     |.  50            push eax                            ; |Buffer
00401248     |.  68 E8030000   push 3E8                            ; |ControlID = 3E8 (1000.)
0040124D     |.  51            push ecx                            ; |hWnd => 001404AC (class='#32770',parent=00150494)
0040124E     |.  33DB          xor ebx,ebx                         ; |
00401250     |.  FFD6          call esi                            ; \GetDlgItemTextA
00401252     |.  83F8 03       cmp eax,3
00401255     |.  73 0B         jnb short ncrackme.00401262
00401257     |.  5E            pop esi
00401258     |.  B8 01000000   mov eax,1
0040125D     |.  5B            pop ebx
0040125E     |.  83C4 30       add esp,30
00401261     |.  C3            retn
00401262     |>  A1 BC564000   mov eax,dword ptr ds:[4056BC]
00401267     |.  8D5424 28     lea edx,dword ptr ss:[esp+28]
0040126B     |.  6A 10         push 10
0040126D     |.  52            push edx
0040126E     |.  68 E9030000   push 3E9
00401273     |.  50            push eax
00401274     |.  FFD6          call esi
00401276     |.  0FBE4424 08   movsx eax,byte ptr ss:[esp+8]       ;  eax=name[0]
0040127B     |.  0FBE4C24 09   movsx ecx,byte ptr ss:[esp+9]       ;  ecx=name[1]
00401280     |.  99            cdq                                 ;  edx:eax 此时dx置0了
00401281     |.  F7F9          idiv ecx                            ;  (edx:eax)/=ecx
00401283     |.  8BCA          mov ecx,edx                         ;  ecx存放余数
00401285     |.  83C8 FF       or eax,FFFFFFFF                     ;  eax全位置1
00401288     |.  0FBE5424 0A   movsx edx,byte ptr ss:[esp+A]       ;  edx=name[2]
0040128D     |.  0FAFCA        imul ecx,edx                        ;  ecx*=edx
00401290     |.  41            inc ecx                             ;  ecx++
00401291     |.  33D2          xor edx,edx                         ;  edx=0;
00401293     |.  F7F1          div ecx                             ;  (edx:eax)/=ecx
00401295     |.  50            push eax                            ;  商入栈
00401296     |.  E8 A5000000   call ncrackme.00401340              ;  转存内容到【4050AC】
0040129B     |.  83C4 04       add esp,4                           ;  esp=esp+4
0040129E     |.  33F6          xor esi,esi                         ;  esi=0;
004012A0     |>  E8 A5000000   /call ncrackme.0040134A             ;  循环开始处
004012A5     |.  99            |cdq
004012A6     |.  B9 1A000000   |mov ecx,1A                         ;  ecx=1a 中间常量
004012AB     |.  F7F9          |idiv ecx                           ;  eax/=ecx,余数在dx里
004012AD     |.  80C2 41       |add dl,41                          ;  dl+=41
004012B0     |.  885434 18     |mov byte ptr ss:[esp+esi+18],dl    ;  每次循环dl的值存入key[esi]
004012B4     |.  46            |inc esi                            ;  esi++
004012B5     |.  83FE 0F       |cmp esi,0F                         ;  esi<0f
004012B8     |.^ 72 E6         \jb short ncrackme.004012A0         ;  小于的话就循环
004012BA     |.  57            push edi
004012BB     |.  8D7C24 0C     lea edi,dword ptr ss:[esp+C]        ;  edi=name[]
004012BF     |.  83C9 FF       or ecx,FFFFFFFF                     ;  ecx全位置1
004012C2     |.  33C0          xor eax,eax                         ;  eax=0
004012C4     |.  33F6          xor esi,esi                         ;  esi=0
004012C6     |.  F2:AE         repne scas byte ptr es:[edi]
004012C8     |.  F7D1          not ecx                             ;  ecx取反
004012CA     |.  49            dec ecx                             ;  ecx--;此时得到len
004012CB     |.  74 59         je short ncrackme.00401326          ;  {-------大循环开始
004012CD     |>  8A4434 0C     /mov al,byte ptr ss:[esp+esi+C]     ;  al=【esp+c+变量esi】,即name[esi]
004012D1     |.  C0F8 05       |sar al,5                           ;  al算数右移5
004012D4     |.  0FBEC0        |movsx eax,al                       ;  eax高位置0
004012D7     |.  8D1480        |lea edx,dword ptr ds:[eax+eax*4]   ;  edx=eax*5;
004012DA     |.  8D04D0        |lea eax,dword ptr ds:[eax+edx*8]   ;  eax=(eax+edx*8)*3
004012DD     |.  8D0440        |lea eax,dword ptr ds:[eax+eax*2]
004012E0     |.  85C0          |test eax,eax                       ;  eax是否为0
004012E2     |.  7E 0A         |jle short ncrackme.004012EE        ;  不为0不跳,此时没跳
004012E4     |.  8BF8          |mov edi,eax                        ;  edi=eax
004012E6     |>  E8 5F000000   |/call ncrackme.0040134A            ;  小循环 {  对【4050AC】地址进行重存放,并改变eax
004012EB     |.  4F            ||dec edi                           ;  edi--
004012EC     |.^ 75 F8         |\jnz short ncrackme.004012E6       ;  小循环 }  //edi为循环次数
004012EE     |>  E8 57000000   |call ncrackme.0040134A             ;  循环结束后再进行一次重存放
004012F3     |.  99            |cdq                                ;  edx置为0
004012F4     |.  B9 1A000000   |mov ecx,1A                         ;  ecx=1a
004012F9     |.  8D7C24 0C     |lea edi,dword ptr ss:[esp+C]       ;  edi=name[]
004012FD     |.  F7F9          |idiv ecx                           ;  (edx:eax)/=ecx
004012FF     |.  0FBE4C34 2C   |movsx ecx,byte ptr ss:[esp+esi+2C] ;  ecx=psw[esi]
00401304     |.  80C2 41       |add dl,41                          ;  余数dl+=41
00401307     |.  0FBEC2        |movsx eax,dl                       ;  eax=dl
0040130A     |.  2BC1          |sub eax,ecx                        ;  eax-=ecx  为使后面eax为0,则此处eax要等于ecx
0040130C     |.  885434 1C     |mov byte ptr ss:[esp+esi+1C],dl    ;  key[esi]=dl
00401310     |.  99            |cdq                                ;  若eax最高位为1,则edx全位为1,否则全位为0
00401311     |.  33C2          |xor eax,edx                        ;  eax异或edx 取绝对值
00401313     |.  83C9 FF       |or ecx,FFFFFFFF                    ;  ecx全位置1
00401316     |.  2BC2          |sub eax,edx                        ;  eax-=edx
00401318     |.  03D8          |add ebx,eax                        ;  ebx+=eax 要使后面sum为0,则eax==edx
0040131A     |.  33C0          |xor eax,eax                        ;  eax=0
0040131C     |.  46            |inc esi                            ;  esi++
0040131D     |.  F2:AE         |repne scas byte ptr es:[edi]
0040131F     |.  F7D1          |not ecx                            ;  ecx取反
00401321     |.  49            |dec ecx                            ;  ecx--
00401322     |.  3BF1          |cmp esi,ecx                        ;  while(esi<ecx) 继续大循环
00401324     |.^ 72 A7         \jb short ncrackme.004012CD
00401326     |>  5F            pop edi                             ;  }-------大循环结束
00401327     |.  8BC3          mov eax,ebx
00401329     |.  5E            pop esi
0040132A     |.  5B            pop ebx
0040132B     |.  83C4 30       add esp,30
0040132E     \.  C3            retn                                ;  此时这边eax要为0才行,即上面的sum要为0

分析了一下之后,发现算法并不容易。由下面的那段测试段可以看出,通过测试的函数后若eax为0则过,否则报错。但函数中的运算并没有直接得到,eax由一堆运算得出。

00401064                   .  E8 C7010000   call ncrackme.00401230              ;  进行比较测试的函数
00401069                   .  85C0          test eax,eax                        ;  若eax为0则对
0040106B                   .  6A 00         push 0                              ; /Style = MB_OK|MB_APPLMODAL
0040106D                   .  68 80504000   push ncrackme.00405080              ; |Title = "ncrackme"
00401072                   .  75 1B         jnz short ncrackme.0040108F         ; |跳了就错
00401074                   .  A1 B8564000   mov eax,dword ptr ds:[4056B8]       ; |
00401079                   .  68 64504000   push ncrackme.00405064              ; |Text = "Registration successful."
0040107E                   .  50            push eax                            ; |hOwner => 000A0494 ('Newbie smallsize crackme - v1',class='myWindowClass')
0040107F                   .  FF15 C0404000 call dword ptr ds:[<&USER32.Message>; \MessageBoxA
00401085                   .  E8 A6020000   call ncrackme.00401330
0040108A                   .  33C0          xor eax,eax
0040108C                   .  C2 1000       retn 10
0040108F                   >  8B0D B8564000 mov ecx,dword ptr ds:[4056B8]       ; |
00401095                   .  68 50504000   push ncrackme.00405050              ; |Text = "Registration fail."
0040109A                   .  51            push ecx                            ; |hOwner => 000A0494 ('Newbie smallsize crackme - v1',class='myWindowClass')
0040109B                   .  FF15 C0404000 call dword ptr ds:[<&USER32.Message>; \MessageBoxA
004010A1                   .  33C0          xor eax,eax
004010A3                   .  C2 1000       retn 10

虽然是个比较简单的才crackme,若直接爆破直接在关键跳jnz short ncrackme.0040108F处改jnz为jz就行。

但算法部分不好研究,就像文章中每个字都认识,但连在一起就不知道讲什么一样。

还需要对算法继续进行分析。待会继续。

---------------------------------------------------------------------------------

弄了好久,把这汇编代码重新写成c语言代码,发现单纯的写没办法解决问题,前面还想说是不是要用蛮力法找结果。

后面经过认真分析,发现ebx这个被我当成sum的东西没什么用,虽然最后确实是要让sum为0才能解决问题,但是问题完全可以避免处理sum。

要使sum为0,则前面一点点额eax要等于edx。要让eax==edx,注意到00401310处cdq指令,eax全为1或者全为0,edx才会跟eax相等,即eax要为0。

要使eax为0,看前面0040130A处eax-=ecx,则eax==ecx,前面三行提示ecx此时存放的就是key,只要这每个key跟eax相等后面条件即成立。

下断点记录每个值。OK...

----------------------------------------------------------------------------------

大气那个喘啊,不是明文的算法分析了好久。

把分析出来的c语言代码稍微改下,权当注册机用了。

#include<stdio.h>
main()
{
int i,j,k,len;
char name[20],psw[20],key[20];

long ax,cx,sum,dx,loc;

printf("name:");
scanf("%s",name);

sum=0;
ax=name[0];
cx=name[1];
cx=ax%cx;
loc=0x002266f0;
ax|=0xffffffff;
cx=cx*name[2]+1;

for(i=0;i<0x0f;i++)
{
  ax=loc;
  ax=ax*0x343FD;
  ax+=0x269EC3;
  loc=ax;
  ax>>=0x10;
  ax&=0x7fff;
  key[i]=ax%0x1a+0x41;
}

len=strlen(name);

for(i=0;i<len;i++)
{
  ax=name[i];
  ax>>=5;
  ax&=0x0ff;
  dx=ax*5;
  ax=(ax+dx*8)*3;
  if(ax==0)break;
  
  k=ax;
  for(j=0;j<=k;j++)
  {
   ax=loc;
   ax=ax*0x343FD;
   ax+=0x269EC3;
   loc=ax;
   ax>>=0x10;
   ax&=0x7fff;
  }
  dx=ax%0x1a+0x41;
  printf("%c",dx);//计算每位码值
  ax=dx-psw[i];
  key[i]=dx;
  sum+=ax;
  
}
printf("\n");
getchar();

}

1084801702.zip

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

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//