逆向一个非常简单的crackme(3)

来看一个crackme

这个crackme的代码很简单,主要来看它的算法


首先打开程序

wpsC54D.tmp

看不出啥,直接od载入

发现是要求keyfile

来看这段(为了代码整齐度隐藏了机器码)

00401061  call    <jmp.&KERNEL32.ReadFile>  ; \ReadFile

00401066  cmp     dword ptr [4021A0], 12 ;  key必须是18byte

0040106D  jnz     short 00401037

0040106F  push    00402008

00401074  call    <对key进行变换>

00401079  xor     dword ptr [4020F9], 12345678  ;   ans^=12345678

00401083  add     esp, 4

00401086  push    00402008

0040108B  call    0040133C       ;ret=a[17]*(16**6)+a[16]*(16**4)+a[15]*(16**2)+a[14]

00401090  add     esp, 4

00401093  cmp     eax, dword ptr [4020F9] ;ret==ans?

00401099  sete    al

0040109C  push    eax

0040109D  test    al, al

0040109F  je      short 00401037 ;不相等则失败

004010A1  push    0040210E                   ;  ASCII “CrackMe v3.0 ”

004010A6  call    00401346

004010AB  add     esp, 4

004010AE  push    0                             ; /Title = NULL

004010B0  push    00402128                  ; |Class = “No need to disasm the code!”

004010B5  call    <jmp.&USER32.FindWindowA>   ; \FindWindowA

004010BA  or      eax, eax

004010BC  je      short 004010BF

004010BE  retn

其中的关键函数,我都标注了标签。

重点是这个函数00401074  call    <对key进行变换>

如下:

00401311 >xor     ecx, ecx

00401313  xor     eax, eax

00401315  mov     esi, dword ptr [esp+4]

00401319  mov     bl, 41                        ;  b[j]={‘A’,'B’,'C’,……}

0040131B  /mov     al, byte ptr [esi]

0040131D  |xor     al, bl

0040131F  |mov     byte ptr [esi], al           ;  a[i]^=b[j]

00401321  |inc     esi                          ;  i++

00401322  |inc     bl                           ;  j++

00401324  |add     dword ptr [4020F9], eax      ;  ans+=a[i]

0040132A  |cmp     al, 0                        ;  key结束?

0040132C  |je      short 00401335

0040132E  |inc     cl                           ;  cnt++

00401330  |cmp     bl, 4F                       ;  j==15?

00401333  \jnz     short 0040131B

00401335  mov     dword ptr [402149], ecx

0040133B  retn                                  ;

整个验证过程相当于如下代码:

 

#include<stdio.h>
#include<string.h>
char key[110];
int ans,ret;
int pow(int p,int k)
{
    int ans=1;
    for(int i=1;i<=k;i++) ans*=p;
    return ans;
}
bool judge(char key[])
{
    int i,j;
    int len=strlen(key);
    if(len!=18) return 0;
    for(i=0;i<=13;i++)
    {
        key[i]^=('A'+i);
        ans+=key[i];
    }
    ans^=12345678;
    ret=key[17]*pow(16,6)+key[16]*pow(16,4)+key[15]*pow(16,2)+key[14];
    if(ans==ret) return 1;
    return 0;

}
int main()
{
    scanf("%s",key);
    ans=0;
    if(judge(key)) printf("invalid key\n");
    else printf("right key!\n");
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>