首页
社区
课程
招聘
一个适合初学者的crackme算法分析
发表于: 2007-1-16 01:26 6359

一个适合初学者的crackme算法分析

2007-1-16 01:26
6359

【文章标题】: 一个适合初学者的crackme算法分析
【文章作者】: 红尘岁月
【作者邮箱】: butter9999@21cn.com
【软件名称】: lafarge-crackme2
【软件大小】: 60.0 KB
【下载地址】: http://bbs.pediy.com/showthread.php?s=&threadid=37891
【加壳方式】: 无
【保护方式】: 无
【使用工具】: OD
【操作平台】: Win9x/NT/2000/XP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  0040112F    PUSH 200                                 ; /Count = 200 (512.)
  00401134    PUSH lafarge2.00406349                   ; |Buffer = lafarge2.00406349
  00401139    PUSH 3EA                                 ; |ControlID = 3EA (1002.)
  0040113E    PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
  00401141    CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA
  00401146    CMP EAX,3
  00401149    JA SHORT lafarge2.00401163               ;  用户名长度大于3
  0040114B    PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  0040114D    PUSH lafarge2.00406306                   ; |Title = "Bad boy..."
  00401152    PUSH lafarge2.0040620A                   ; |Text = "Username must have at least 4 chars..."
  00401157    PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
  0040115A    CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA
  0040115F    LEAVE
  00401160    RETN 10
  00401163    LEA EDX,DWORD PTR DS:[406349]            ;  用户名地址
  00401169    PUSH EDX                                 ; /String => ""
  0040116A    CALL <JMP.&kernel32.lstrlenA>            ; \lstrlenA
  0040116F    MOV EBP,EAX                              ;  用户长度nlen
  00401171    MOV ECX,5
  00401176    XOR ESI,ESI                              ;  i=0
  00401178    XOR EAX,EAX                              ;  m=0,mone=0
  0040117A    MOV CL,BYTE PTR DS:[ESI+EDX]             ;  第一个循环计算,用户名第二位开始与内存406328处前5个的数据temp做xor运算
  0040117D    MOV BL,CL                                ;  四次循环以及后面的处理都只从第二位开始
  0040117F    XOR BL,BYTE PTR DS:[EAX+406328]          ;  mone=name[i+1]^temp[m]
  00401185    INC EAX                                  ;  m++
  00401186    CMP EAX,5
  00401189    MOV BYTE PTR DS:[EDX+ESI],BL             ;  longtemp[i]=mone
  0040118C    MOV BYTE PTR DS:[EAX+406327],CL          ;  temp[m]=nametemp[i+1]
  00401192    JNZ SHORT lafarge2.00401196
  00401194    XOR EAX,EAX                              ;  if(m==5)m=0
  00401196    INC ESI
  00401197    CMP ESI,EBP
  00401199    JB SHORT lafarge2.0040117A               ;  i<nlen,循环次数为nlen次,以下四个循环次数相同
  0040119B    XOR EDI,EDI                              ;  第一个循环结束后,用户名地址处得到新的数据longtemp
  0040119D    XOR ECX,ECX
  0040119F    TEST EBP,EBP
  004011A1    JBE SHORT lafarge2.004011C9
  004011A3    MOV BL,BYTE PTR DS:[EDI+40632D]          ;  第二个循环计算,longtemp最高位开始与内存40632d处前5个的数据temp2做xor运算
  004011A9    MOV ESI,EBP
  004011AB    SUB ESI,ECX
  004011AD    DEC ESI
  004011AE    MOV AL,BYTE PTR DS:[EDX+ESI]
  004011B1    XOR BL,AL
  004011B3    INC EDI
  004011B4    MOV BYTE PTR DS:[EDX+ESI],BL
  004011B7    MOV BYTE PTR DS:[EDI+40632C],AL
  004011BD    CMP EDI,5
  004011C0    JNZ SHORT lafarge2.004011C4
  004011C2    XOR EDI,EDI
  004011C4    INC ECX
  004011C5    CMP ECX,EBP
  004011C7    JB SHORT lafarge2.004011A3               ;  第二个循环与第一个相似,只是从高位开始,改变longtemp中的数据
  004011C9    XOR ESI,ESI
  004011CB    XOR EDI,EDI
  004011CD    TEST EBP,EBP
  004011CF    JBE SHORT lafarge2.004011F2
  004011D1    MOV AL,BYTE PTR DS:[EDX+EDI]             ;  第三个循环与第一个完全相似,只是longtemp xor temp3
  004011D4    MOV CL,BYTE PTR DS:[ESI+406332]
  004011DA    XOR CL,AL
  004011DC    INC ESI
  004011DD    MOV BYTE PTR DS:[EDX+EDI],CL
  004011E0    MOV BYTE PTR DS:[ESI+406331],AL
  004011E6    CMP ESI,5
  004011E9    JNZ SHORT lafarge2.004011ED
  004011EB    XOR ESI,ESI
  004011ED    INC EDI
  004011EE    CMP EDI,EBP
  004011F0    JB SHORT lafarge2.004011D1               ;  第三个循环
  004011F2    XOR EDI,EDI
  004011F4    XOR ECX,ECX
  004011F6    TEST EBP,EBP
  004011F8    JBE SHORT lafarge2.00401220
  004011FA    MOV BL,BYTE PTR DS:[EDI+406337]          ;  第四个循环与第二个完全相似,longtemp xor temp4
  00401200    MOV ESI,EBP
  00401202    SUB ESI,ECX
  00401204    DEC ESI
  00401205    MOV AL,BYTE PTR DS:[EDX+ESI]
  00401208    XOR BL,AL
  0040120A    INC EDI
  0040120B    MOV BYTE PTR DS:[EDX+ESI],BL
  0040120E    MOV BYTE PTR DS:[EDI+406336],AL
  00401214    CMP EDI,5
  00401217    JNZ SHORT lafarge2.0040121B
  00401219    XOR EDI,EDI
  0040121B    INC ECX
  0040121C    CMP ECX,EBP
  0040121E    JB SHORT lafarge2.004011FA               ;  第四个循环
  00401220    LEA EDI,DWORD PTR DS:[406345]            ;  下面4行语句,清空406345处4字节32位的内存空间
  00401226    XOR EAX,EAX                              ;  i=0
  00401228    TEST EBP,EBP
  0040122A    MOV DWORD PTR DS:[406345],0              ;  unsigned char longtemp2[4]={0}
  00401234    JBE SHORT lafarge2.0040124D              ;  第五个循环,把templong中数据相加产生一个新的数据longtemp2
  00401236    MOV ECX,EAX                              ;  m=i
  00401238    AND ECX,3                                ;  if(m==4)m=0
  0040123B    MOV BL,BYTE PTR DS:[EDI+ECX]             ;  longtemp2[m]
  0040123E    LEA ESI,DWORD PTR DS:[EDI+ECX]
  00401241    MOV CL,BYTE PTR DS:[EDX+EAX]             ;  longtemp[i+1]
  00401244    ADD BL,CL
  00401246    INC EAX
  00401247    CMP EAX,EBP
  00401249    MOV BYTE PTR DS:[ESI],BL                 ;  longtemp2[m]=longtemp2[m]+longtemp[i+1]
  0040124B    JB SHORT lafarge2.00401236               ;  i<nlen
  0040124D    POP EBP                                  ;  第五次循环结束
  0040124E    MOV ECX,0A                               ;  下面的语句把longtemp2(低低高高)从十六进制变成十进制数字
  00401253    MOV EAX,DWORD PTR DS:[406345]
  00401258    XOR EBX,EBX
  0040125A    XOR EDX,EDX
  0040125C    DIV ECX
  0040125E    ADD DL,30                                ;  把求模结果ascii码+0x30变成数字
  00401261    MOV BYTE PTR DS:[EBX+406549],DL
  00401267    INC EBX
  00401268    TEST EAX,EAX
  0040126A    JNZ SHORT lafarge2.0040125A
  0040126C    PUSH lafarge2.00406549                   ; /String = ""
  00401271    CALL <JMP.&kernel32.lstrlenA>            ; \lstrlenA
  00401276    XOR EBX,EBX
  00401278    MOV CL,BYTE PTR DS:[EAX+406548]          ;  字符串倒换strrev(字符串)得到注册码
  0040127E    MOV BYTE PTR DS:[EBX+406749],CL
  00401284    INC EBX
  00401285    DEC EAX
  00401286    JNZ SHORT lafarge2.00401278
  00401288    PUSH lafarge2.00406749                   ; /String2 = ""
  0040128D    PUSH lafarge2.00406549                   ; |String1 = lafarge2.00406549
  00401292    CALL <JMP.&kernel32.lstrcpyA>            ; \lstrcpyA
  00401297    PUSH 200                                 ; /Count = 200 (512.)
  0040129C    PUSH lafarge2.00406949                   ; |Buffer = lafarge2.00406949
  004012A1    PUSH 64                                  ; |ControlID = 64 (100.)
  004012A3    PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
  004012A6    CALL <JMP.&user32.GetDlgItemTextA>       ; \GetDlgItemTextA
  004012AB    PUSH lafarge2.00406549                   ; /String2 = ""
  004012B0    PUSH lafarge2.00406949                   ; |String1 = ""
  004012B5    CALL <JMP.&kernel32.lstrcmpA>            ; \lstrcmpA
  004012BA    OR EAX,EAX
  004012BC    JNZ SHORT lafarge2.004012D4
  004012BE    PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004012C0    PUSH lafarge2.004062DB                   ; |Title = "Good boy..."
  004012C5    PUSH lafarge2.004062AC                   ; |Text = "Yep, thats the right code!
  
  Go write a keygen!"
  004012CA    PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
  004012CD    CALL <JMP.&user32.MessageBoxA>           ; \MessageBoxA
  
    /////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////
   
    算法总结:
   
    1) 用户名必须大于3 (为了方便在注册码中我假设用户名小于20位)
   
    2) 用户名第二位开始,与内存中的数据做xor运算,共4次,每次循环次数为nlen次
   
    3) 把生成的数据用加位计算成一个32位的数据
   
    4) 把生成的数据先变成十进制,再换位
   
    /////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////

  代码如下:
  
  void CMyDlg::OnOK()
  {
          // TODO: Add extra validation here
  //得到用户名
          char name[20];                      //假设用户名不超过20位,实际上这个注册机假设用户名要小于20位
          int  len;
        len=GetDlgItemText(IDC_EDIT1,name,21);        //假设用户名不超过20位,所以只取前20位字符
        if(len<4||len>19)                  //此注册机假设用户名小于20位,一般就受上行GetDlgItemText中21的限制取前20位
        {
                MessageBox("用户名大于3个字符,小于20位!");
                return;
        }
  
          char key[20]="";                  //假设注册码不超过20位
          char nametemp[21]="";
          unsigned char longtemp[21];
          unsigned char longtemp2[4]={0};

  //四个内存区间数据       
          unsigned char temp[5]={0xAA,0x89,0xC4,0xFE,0x46};
          unsigned char temp2[5]={0x78,0xF0,0xD0,0x03,0xE7};
          unsigned char temp3[5]={0xF7,0xFD,0xF4,0xE7,0xB9};
          unsigned char temp4[5]={0xB5,0x1B,0xC9,0x50,0x73};
  
          int i,m,nlen;
          unsigned char mone=0;
          nlen=strlen(name);
          m=0;
          strcpy(nametemp,name);
          nametemp[nlen]='\0';
          longtemp[0]=name[0];
  
  //第一次循环
          for(i=1;i<nlen+1;i++)
          {
                  mone=nametemp[i]^temp[m];
                  temp[m]=nametemp[i];
                  longtemp[i]=mone;
                  m++;
                  if(m==5)m=0;
          }
  //第二次循环
          m=0;
          for(i=nlen;i>0;i--)
          {
                  mone=longtemp[i]^temp2[m];
                  temp2[m]=longtemp[i];
                  longtemp[i]=mone;
                  m++;
                  if(m==5)m=0;
          }
  //第三次循环与第一次相同
          m=0;
          for(i=1;i<nlen+1;i++)
          {
                  mone=longtemp[i]^temp3[m];
                  temp3[m]=longtemp[i];
                  longtemp[i]=mone;
                  m++;
                  if(m==5)m=0;
          }
  //第四次循环与第二次相同
          m=0;
          for(i=nlen;i>0;i--)
          {
                  mone=longtemp[i]^temp4[m];
                  temp4[m]=longtemp[i];
                  longtemp[i]=mone;
                  m++;
                  if(m==5)m=0;
          }
  
  //第五个循环
          m=0;
          for(i=0;i<nlen;i++)
          {
                  longtemp2[m]=longtemp2[m]+longtemp[i+1];
                  m++;
                  if(m==4)m=0;
          }
  
  //十六进制变成十进制
          unsigned long longone=longtemp2[3]*pow(2,24)+longtemp2[2]*pow(2,16)+longtemp2[1]*pow(2,8)+longtemp2[0];
          char strtwo[20];
          for(i=0;longone>=1;i++)
          {
           strtwo[i]=longone%0xa+0x30;
           longone=longone/0xa;
          }
      strtwo[i]='\0';
  
  //转换数据
          strrev(strtwo);
  //得到注册码
          strcpy(key,strtwo);
  //返回注册码
          SetDlgItemText(IDC_EDIT2,key);
  
  }
  
  例如:
  用户名:ccbhcsy
  注册码:703728050
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年01月16日 1:24:31


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

收藏
免费 7
支持
分享
最新回复 (5)
雪    币: 2319
活跃值: (565)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
2
很用心,支持
2007-1-16 07:50
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
3
支持下。
我看中了那个注册机码
2007-1-16 08:50
0
雪    币: 82
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
贴一下ida的分析结果,顺便学一下如何使用ida。
push        eax
push        ebx
push        Len
push        200h                ; nMaxCount
push        offset Name        ; lpString
push        3EAh                ; nIDDlgItem
push        [Len+hDlg]        ; hDlg
call        GetDlgItemTextA
cmp        eax, 3
ja        short NameLenMustGreater3
push        10h                ; uType
push        offset Caption        ; "Bad boy..."
push        offset Text        ; "Username must have at least 4 chars..."
push        [Len+hDlg]        ; hWnd
call        MessageBoxA
leave
retn        10h

NameLenMustGreater3:
lea        Name, Name
push        Name                ; lpString
call        lstrlenA
mov        Len, eax
mov        ecx, 5
xor        esi, esi
xor        eax, eax

Loop1:
mov        cl, [esi+Name]
mov        bl, cl
xor        bl, temp[eax]
inc        eax
cmp        eax, 5
mov        [Name+esi], bl
mov        temp[eax-1], cl
jnz        short easIsNot5
xor        eax, eax

easIsNot5:
inc        esi
cmp        esi, Len
jb        short Loop1
xor        edi, edi
xor        ecx, ecx
test        Len, Len
jbe        short loc_4011C9

loop2:
mov        bl, temp2[edi]
mov        esi, Len        ; Step -1
sub        esi, ecx
dec        esi
mov        al, [Name+esi]
xor        bl, al
inc        edi
mov        [Name+esi], bl
mov        temp2[edi-1], al
cmp        edi, 5
jnz        short ediIsNot5
xor        edi, edi

ediIsNot5:
inc        ecx
cmp        ecx, Len
jb        short loop2

loc_4011C9:
xor        esi, esi
xor        edi, edi
test        Len, Len
jbe        short loc_4011F2

loop3:
mov        al, [Name+edi]
mov        cl, temp3[esi]
xor        cl, al
inc        esi
mov        [Name+edi], cl
mov        temp3[esi-1], al
cmp        esi, 5
jnz        short esiIsNot5
xor        esi, esi

esiIsNot5:
inc        edi
cmp        edi, Len
jb        short loop3

loc_4011F2:
xor        edi, edi
xor        ecx, ecx
test        Len, Len
jbe        short loc_401220

loop4:
mov        bl, temp4[edi]
mov        esi, Len
sub        esi, ecx
dec        esi
mov        al, [Name+esi]
xor        bl, al
inc        edi
mov        [Name+esi], bl
mov        temp4[edi-1], al
cmp        edi, 5
jnz        short _esiIsNot5
xor        edi, edi

_esiIsNot5:
inc        ecx
cmp        ecx, Len
jb        short loop4

loc_401220:
lea        edi, longone
xor        eax, eax
test        Len, Len
mov        longone, 0
jbe        short loc_40124D

loop6:
mov        ecx, eax
and        ecx, 3
mov        bl, [edi+ecx]
lea        esi, [edi+ecx]
mov        cl, [Name+eax]
add        bl, cl
inc        eax
cmp        eax, Len
mov        [esi], bl
jb        short loop6

loc_40124D:
pop        Len
mov        ecx, 0Ah
mov        eax, longone
xor        ebx, ebx

loop5:
xor        Name, Name
div        ecx
add        dl, 30h
mov        StrTwo[ebx], dl
inc        ebx
test        eax, eax
jnz        short loop5
push        offset StrTwo        ; lpString
call        lstrlenA
xor        ebx, ebx

loop7:
mov        cl, StrTwo[eax-1]
mov        String2[ebx], cl
inc        ebx
dec        eax
jnz        short loop7
push        offset String2        ; lpString2
push        offset StrTwo        ; lpString1
call        lstrcpyA
push        200h                ; nMaxCount
push        offset Key        ; lpString
push        64h                ; nIDDlgItem
push        [Len+hDlg]        ; hDlg
call        GetDlgItemTextA
push        offset StrTwo        ; lpString2
push        offset Key        ; lpString1
call        lstrcmpA
or        eax, eax
jnz        short KeyIsNotCorrect
push        40h                ; uType
push        offset aGoodBoy___ ; "Good boy..."
push        offset aYepThatsTheRig ; "Yep, thats the right code!\n\rGo write a "...
push        [Len+hDlg]        ; hWnd
call        MessageBoxA
2007-1-17 11:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我有一个问题,为什么这个cm永peid什么也看不到,应该怎么处理
2007-3-26 11:03
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不错,很详细
2007-3-26 12:50
0
游客
登录 | 注册 方可回帖
返回
//