小强 发表于 2014-10-2 15:41

crc32crackme程序分析

本帖最后由 小强 于 2014-10-2 16:00 编辑

作 者: obabydbg
时 间: 2014-09-20,00:44:35
链 接: http://bbs.pediy.com/showthread.php?t=192472

crc32crackme.exe这个程序下到电脑有一段时间了,一直没有时间分析。晚上有时间就简单分析了一下。大牛略过http://bbs.pediy.com/images/smilies/tongue.gif。图片传送失败,直接上代码吧。
程序无壳,直接拖入OD分析。
在模块之间调用对GetWindowTextA、MessageBoxA下断,F9让程序跑起来。在弹出的对话框中输入。
Name:obabydbg
Code:123456789
点击CheckMe。
断在这里。
004042F4|.50            PUSH EAX                                 ; |Buffer
004042F5|.A1 28654000   MOV EAX,DWORD PTR DS:            ; |
004042FA|.50            PUSH EAX                                 ; |hWnd => 00030272 (class='Edit',parent=0033004C)
004042FB|.E8 DCF9FFFF   CALL <JMP.&user32.GetWindowTextA>      ; \GetWindowTextA
00404300|.83FE 05       CMP ESI,5                              ;输入用户名大于5
00404303|.0F8C B1000000 JL crc32cra.004043BA
00404309|.8D45 FC       LEA EAX,DWORD PTR SS:
0040430C|.8B4D FC       MOV ECX,DWORD PTR SS:
0040430F|.BA F8434000   MOV EDX,crc32cra.004043F8                ;ASCII "DiKeN"
00404314|.E8 03ECFFFF   CALL crc32cra.00402F1C                   ;DiKeN和obabydbg连接
00404319|.8B45 FC       MOV EAX,DWORD PTR SS:
0040431C|.E8 AFEBFFFF   CALL crc32cra.00402ED0
00404321|.8BD0          MOV EDX,EAX
00404323|.8D45 FC       LEA EAX,DWORD PTR SS:
00404326|.E8 C5FAFFFF   CALL crc32cra.00403DF0                   ;用户名算法

输入的Name要大于5,然后会跟字符串DiKeN连接成DiKeNobabydbg。进入00404326这个CALL中。
00403DF0   $51            PUSH ECX
00403DF1   .53            PUSH EBX
00403DF2   .56            PUSH ESI
00403DF3   .57            PUSH EDI
00403DF4   .BF 1A3E4000   MOV EDI,crc32cra.00403E1A
00403DF9   .8B30          MOV ESI,DWORD PTR DS:
00403DFB   .83C8 FF       OR EAX,FFFFFFFF
00403DFE   .31C9          XOR ECX,ECX
00403E00   >3206          XOR AL,BYTE PTR DS:               ;把用户名做运算,生成一个32位的数值
00403E02   .50            PUSH EAX
00403E03   .25 FF000000   AND EAX,0FF
00403E08   .8B1C87      MOV EBX,DWORD PTR DS:
00403E0B   .58            POP EAX
00403E0C   .C1E8 08       SHR EAX,8
00403E0F   .31D8          XOR EAX,EBX
00403E11   .46            INC ESI
00403E12   .4A            DEC EDX
00403E13   .^ 75 EB         JNZ SHORT crc32cra.00403E00

这里实际上是把用户名做运算,得到一个32位的数值。DiKeNobabydbg我这里得出来的数值为:0xfb000411。其实也模仿上面的代码写程序得出这个值。
F8继续运行程序,断在这里。
00404356|> \6A 20         PUSH 20
00404358|.8B45 F8       MOV EAX,DWORD PTR SS:
0040435B|.E8 40ECFFFF   CALL crc32cra.00402FA0
00404360|.50            PUSH EAX                                 ; |Buffer
00404361|.A1 2C654000   MOV EAX,DWORD PTR DS:            ; |
00404366|.50            PUSH EAX                                 ; |hWnd => 00030270 (class='Edit',parent=0033004C)
00404367|.E8 70F9FFFF   CALL <JMP.&user32.GetWindowTextA>      ; \GetWindowTextA
0040436C|.8D45 F8       LEA EAX,DWORD PTR SS:
0040436F|.8B4D F8       MOV ECX,DWORD PTR SS:
00404372|.BA 08444000   MOV EDX,crc32cra.00404408
00404377|.E8 A0EBFFFF   CALL crc32cra.00402F1C
0040437C|.8B45 F8       MOV EAX,DWORD PTR SS:
0040437F|.E8 A0FEFFFF   CALL crc32cra.00404224                   ;注册码的算法
00404384|.33F0          XOR ESI,EAX                              ;用户名生成的数值跟注册码生成的数值异域
进行0040437F这个CALL中。
00404261|.B8 01000000   MOV EAX,1
00404266|>03D2          /ADD EDX,EDX                           ;主要是在这里生成的
00404268|.8D1492      |LEA EDX,DWORD PTR DS:
0040426B|.8B5D F8       |MOV EBX,DWORD PTR SS:
0040426E|.0FB65C03 FF   |MOVZX EBX,BYTE PTR DS:
00404273|.03D3          |ADD EDX,EBX
00404275|.83EA 30       |SUB EDX,30
00404278|.40            |INC EAX
00404279|.3BC8          |CMP ECX,EAX
0040427B|.^ 75 E9         \JNZ SHORT crc32cra.00404266
这里是主要算法。
然后把Name运算得出的数值跟Code字符串通过算法得出来的值做异或,如果为0就正确。
0xfb000411这个值是通过Name得出来的,如果异或要为0的话,那么通过Code得出的值也必须是0xfb000411。这样的话异或运算才得为0。
通过对代码的分析,把0123456789这个字符串运算成要异或的值。既然有正确的值了,那么就通过0xfb000411这个值把字符串逆算出来。
以下为逆算的代码,代码还可以优化,有兴趣的朋友可以修改。
#include <stdio.h>
#include <stdlib.h>


int main()
{
unsigned int crc32=0xfb000411;
unsigned int buffer;
char value;
int i=0;
int j=0;
int temp=0;
while(1)
{
    if(crc32>=0 && crc32<=0x4a)
      break;
    crc32/=5;
    crc32/=2;
    buffer = crc32;
    i++;
}
i-=2;
temp = crc32;
temp+=0x30;
value=(char )temp;
j+=1;
while(i>=0)
{
    crc32*=2;
    crc32*=5;
    temp = buffer;
    temp-=crc32;
    temp+=0x30;
    value=temp;
    crc32 = buffer;
    i--;
    j++;
}
crc32*=2;
crc32*=5;
temp = 0xfb000411 - crc32;
temp+=0x30;
value = temp;
value='\0';
printf("%s\n",value);
return 0;
}
我这里得出来的字符串为:Z11082257
注册正确http://bbs.pediy.com/images/smilies/biggrin.gif
文字编辑看起来有点乱,大家就将就着看看吧。

Shark恒 发表于 2014-10-2 15:53

没有附件啊,亲~

小强 发表于 2014-10-2 16:01

Shark恒 发表于 2014-10-2 15:53
没有附件啊,亲~

{:5_117:}已上传了。

Leo 发表于 2014-10-2 16:09

厉害

LvMax 发表于 2014-10-3 16:40

crcxi效验吗

Dean 发表于 2014-10-11 15:01

感谢分享,逆算的代码不知道是怎么一步一步分析来的

520Kelly 发表于 2014-11-19 21:08

话说我还是不知道跟crc的关系

Cloudraker 发表于 2015-11-4 22:45

感觉高深,还在学习中,谢谢分享

雷神来了 发表于 2022-4-30 15:28


[快捷回复]-软件反汇编逆向分析,软件安全必不可少!

zg2600 发表于 2022-5-23 00:36

[吾爱汇编论坛52HB.COM]-Thanks~向楼主致敬!nice,谢谢,给力非常感谢逆向思路
页: [1] 2
查看完整版本: crc32crackme程序分析