iawen 发表于 2009-3-25 16:32

一个国外程序的算法分析[CRC32算法]

本帖最后由 iawen 于 2009-3-25 17:27 编辑

程序的地址是:http://www.jcrystal.com/

程序没有加壳,用PEid查显示为:Microsoft Visual Basic 5.0 / 6.0
由于是来分析算法,所以我还用PEid的插件来分析了一下程序所用的算法是:
CRC32 :: 0013D96F :: 0053D96F
        The reference is above.
心里有个数了,其他的也就不多说了,直接用OD载入吧,F9运行起来,然后找到注册位置,随意输入注册码,不急着确定,先下:bp rtcMsgBox,然后确定,断在:
73502096 MSVBVM>55                   push ebp
73502097          8BEC               mov ebp,esp
73502099          83EC 4C            sub esp,4C
7350209C          8B4D 14            mov ecx,dword ptr ss:
ALt+F9返回:
004B8DBD         . /0F84 BD000000      je wincnt.004B8E80
004B8DC3         . |8B45 08            mov eax,dword ptr ss:
004B8DC6         . |8D95 FCFEFFFF      lea edx,dword ptr ss:
004B8DCC         . |52               push edx
004B8DCD         . |8B55 E8            mov edx,dword ptr ss:
004B8DD0         . |8B08               mov ecx,dword ptr ds:
004B8DD2         . |52               push edx
004B8DD3         . |50               push eax
004B8DD4         . |FF91 38090000      call dword ptr ds:                  ;这里就是第一个关键CALL了,F7跟进
004B8DDA         . |8B45 E8            mov eax,dword ptr ss:
004B8DDD         . |50               push eax
004B8DDE         . |FFD6               call esi                                       ;<&MSVBVM60.__vbaLenBstr>
004B8DE0         . |33C9               xor ecx,ecx
004B8DE2         . |83F8 0D            cmp eax,0D
004B8DE5         . |0F9DC1             setge cl
004B8DE8         . |33D2               xor edx,edx
004B8DEA         . |66:3995 FCFEFFFF   cmp word ptr ss:,dx
004B8DF1         . |0F95C2             setne dl
004B8DF4         . |85CA               test edx,ecx
004B8DF6         . |0F85 3D010000      jnz wincnt.004B8F39
004B8DFC         . |BE 04000280      mov esi,80020004
004B8E01         . |8D95 50FFFFFF      lea edx,dword ptr ss:
004B8E07         . |8D4D B0            lea ecx,dword ptr ss:
004B8E0A         . |8975 98            mov dword ptr ss:,esi
004B8E0D         . |895D 90            mov dword ptr ss:,ebx
004B8E10         . |8975 A8            mov dword ptr ss:,esi
004B8E13         . |895D A0            mov dword ptr ss:,ebx
004B8E16         . |C785 58FFFFFF 4050>mov dword ptr ss:,wincnt.00415040      ;UNICODE "Registration failed!"
004B8E20         . |C785 50FFFFFF 0800>mov dword ptr ss:,8
004B8E2A         . |FFD7               call edi                                       ;<&MSVBVM60.__vbaVarDup>
004B8E2C         . |8D95 60FFFFFF      lea edx,dword ptr ss:
004B8E32         . |8D4D C0            lea ecx,dword ptr ss:
004B8E35         . |C785 68FFFFFF 2450>mov dword ptr ss:,wincnt.00415024      ;UNICODE "Invalid Key"
004B8E3F         . |C785 60FFFFFF 0800>mov dword ptr ss:,8
004B8E49         . |FFD7               call edi                                       ;<&MSVBVM60.__vbaVarDup>
004B8E4B         . |8D45 90            lea eax,dword ptr ss:
004B8E4E         . |8D4D A0            lea ecx,dword ptr ss:
004B8E51         . |50               push eax
004B8E52         . |8D55 B0            lea edx,dword ptr ss:
004B8E55         . |51               push ecx
004B8E56         . |52               push edx
004B8E57         . |8D45 C0            lea eax,dword ptr ss:
004B8E5A         . |6A 30            push 30
004B8E5C         . |50               push eax
004B8E5D         . |FF15 B8114000      call dword ptr ds:[<&MSVBVM60.#595>]         ;MSVBVM60.rtcMsgBox
004B8E63         . |8D4D 90            lea ecx,dword ptr ss:跟进上面的那个关键,很快就来到这里:
004CBEC9         .52               push edx
004CBECA         .894D C4            mov dword ptr ss:,ecx
004CBECD         .C745 BC 08400000   mov dword ptr ss:,4008
004CBED4         .FFD7               call edi                           ;<&MSVBVM60.__vbaLenBstr>
004CBED6         .83E8 09            sub eax,9                            ;取用户输入的注册长度,与9比较
004CBED9         .8D4D CC            lea ecx,dword ptr ss:
004CBEDC         .0F80 C5000000      jo wincnt.004CBFA7                   ;小于9则出错返回
                //0012F7F8001DAA84UNICODE "AAA-_12345678"继续单步,来到这里:
004CBEE6         .50               push eax
004CBEE7         .51               push ecx
004CBEE8         .FF15 F8134000      call dword ptr ds:[<&MSVBVM60.#617>] ;MSVBVM60.rtcLeftCharVar
004CBEEE         .8D55 CC            lea edx,dword ptr ss:      ;取出左边4个字符
                //0012F7E80021B104UNICODE "AAA-"一路单步吧:
004CBF14         .52               push edx
004CBF15         .8D55 EC            lea edx,dword ptr ss:
004CBF18         .8B08               mov ecx,dword ptr ds:
004CBF1A         .52               push edx
004CBF1B         .50               push eax
004CBF1C         .FF91 34090000      call dword ptr ds:          ;关键CALL,F7跟进
//=========================================================
004CBBED         .52               push edx                                       ; /Arg2
004CBBEE         .50               push eax                                       ; |Arg1
004CBBEF         .C785 5CFFFFFF A74D>mov dword ptr ss:,4DA7                   ; |
004CBBF9         .C785 54FFFFFF 0200>mov dword ptr ss:,2                      ; |
004CBC03         .FF15 E0114000      call dword ptr ds:[<&MSVBVM60.#520>]             ; \将4DA7转换为10格式字符串,即:19879由此可见,这里的19879是固定的,我们在做注册机时,就可以直接写上了,不用管他的转换!
004CBC3A         .8D95 44FFFFFF      lea edx,dword ptr ss:
004CBC40         .8D85 34FFFFFF      lea eax,dword ptr ss:
004CBC46         .52               push edx
004CBC47         .50               push eax
004CBC48         .FFD7               call edi                                       ;将^LTB与上面得到字符串连接; <&MSVBVM60.__vbaVarCat>
004CBC4A         .50               push eax                                       ; /得到:UNICODE "^LTB19879"上面是一连串的字符串连接操作,这里不一一作说明了,其实都是固定下来的,得到的结果就是:^LTB19879
004CBD23         .52               push edx
004CBD24         .50               push eax
004CBD25         .8975 E0            mov dword ptr ss:,esi
004CBD28         .C745 C4 08000000   mov dword ptr ss:,8                  ;将主程序名转成小写
004CBD2F         .FF15 44114000      call dword ptr ds:[<&MSVBVM60.#518>]         ;MSVBVM60.rtcLowerCaseVar
004CBD35         .8B4D E4            mov ecx,dword ptr ss:                  ;//UNICODE "wincnt"
……………………
004CBD4B         .50               push eax
004CBD4C         .51               push ecx
004CBD4D         .C785 24FFFFFF 0800>mov dword ptr ss:,8
004CBD57         .FFD7               call edi                                       ;接上上面的字符串得:"wincnt^LTB19879"
004CBD59         .50               push eax                                       ; /Arg1 = 0012F74C
……………………
004CBD6D         .51               push ecx
004CBD6E         .8D4D DC            lea ecx,dword ptr ss:
004CBD71         .8B10               mov edx,dword ptr ds:
004CBD73         .51               push ecx
004CBD74         .8B4D 0C            mov ecx,dword ptr ss:
004CBD77         .51               push ecx
004CBD78         .50               push eax
004CBD79         .FF92 44090000      call dword ptr ds:                  ;关键CALL,继续F7跟进上面大部分都是字符串的连接操作,我们跟过就明白了,我们继续跟入下面的一个关键CALL吧
//=======================================
004CC8D5         .C745 C0 65F95900   mov dword ptr ss:,59F965               ; |
004CC8DC         .C745 B8 03000000   mov dword ptr ss:,3                  ; |
004CC8E3         .FF15 E0114000      call dword ptr ds:[<&MSVBVM60.#520>]         ; \rtcTrimVar
004CC8E9         .8B5D 0C            mov ebx,dword ptr ss:                   ;又得一字符串:5896549
……………………
004CC923         .51               push ecx
004CC924         .52               push edx
004CC925         .FFD7               call edi                                       ;继续连接字符串; <&MSVBVM60.__vbaVarCat>
004CC927         .50               push eax                                       ;得:"5896549AAA-"
004CC928         .8D85 54FFFFFF      lea eax,dword ptr ss:
004CC92E         .8D4D 88            lea ecx,dword ptr ss:
004CC931         .50               push eax
004CC932         .51               push ecx
004CC933         .FFD7               call edi                                       ;<&MSVBVM60.__vbaVarCat>
004CC935         .8BD0               mov edx,eax                                    ;得:"5896549AAA-wincnt^LTB19879"
……………………
004CC995         .52               push edx
004CC996         .50               push eax
004CC997         .8BF8               mov edi,eax
004CC999         .FF51 28            call dword ptr ds:                     ;关键CALL,继续F7跟进继续跟进:
//===============================================================
0053DCB1         > /8B4D E8            mov ecx,dword ptr ss:
0053DCB4         . |8B45 A4            mov eax,dword ptr ss:
0053DCB7         . |3BC8               cmp ecx,eax
0053DCB9         . |0F8F B1000000      jg wincnt.0053DD70
0053DCBF         . |8B55 0C            mov edx,dword ptr ss:
0053DCC2         . |8B02               mov eax,dword ptr ds:
0053DCC4         . |3BC7               cmp eax,edi
0053DCC6         . |74 20            je short wincnt.0053DCE8
0053DCC8         . |66:8338 01         cmp word ptr ds:,1
0053DCCC         . |75 1A            jnz short wincnt.0053DCE8
0053DCCE         . |8B50 14            mov edx,dword ptr ds:
0053DCD1         . |8BF9               mov edi,ecx
0053DCD3         . |8B48 10            mov ecx,dword ptr ds:
0053DCD6         . |2BFA               sub edi,edx
0053DCD8         . |3BF9               cmp edi,ecx
0053DCDA         . |72 06            jb short wincnt.0053DCE2
0053DCDC         . |FF15 38124000      call dword ptr ds:[<&MSVBVM60.__vbaGenerateBou>;MSVBVM60.__vbaGenerateBoundsError
0053DCE2         > |8BC7               mov eax,edi
0053DCE4         . |33FF               xor edi,edi
0053DCE6         . |EB 06            jmp short wincnt.0053DCEE
0053DCE8         > |FF15 38124000      call dword ptr ds:[<&MSVBVM60.__vbaGenerateBou>;MSVBVM60.__vbaGenerateBoundsError
0053DCEE         > |8B4D 0C            mov ecx,dword ptr ss:
0053DCF1         . |8B11               mov edx,dword ptr ds:
0053DCF3         . |8B4A 0C            mov ecx,dword ptr ds:
0053DCF6         . |33D2               xor edx,edx
0053DCF8         . |8A1401             mov dl,byte ptr ds:
0053DCFB         . |8BC6               mov eax,esi
0053DCFD         . |8BCA               mov ecx,edx
0053DCFF         . |25 FF000000      and eax,0FF
0053DD04         . |33C8               xor ecx,eax
0053DD06         . |8BC6               mov eax,esi
0053DD08         . |24 00            and al,0
0053DD0A         . |99               cdq
0053DD0B         . |81E2 FF000000      and edx,0FF
0053DD11         . |03C2               add eax,edx
0053DD13         . |C1F8 08            sar eax,8
0053DD16         . |25 FFFFFF00      and eax,0FFFFFF
0053DD1B         . |8BF0               mov esi,eax
0053DD1D         . |8B43 34            mov eax,dword ptr ds:
0053DD20         . |3BC7               cmp eax,edi
0053DD22         . |74 23            je short wincnt.0053DD47
0053DD24         . |66:8338 01         cmp word ptr ds:,1
0053DD28         . |75 1D            jnz short wincnt.0053DD47
0053DD2A         . |2B48 14            sub ecx,dword ptr ds:
0053DD2D         . |8BF9               mov edi,ecx
0053DD2F         . |8B48 10            mov ecx,dword ptr ds:
0053DD32         . |3BF9               cmp edi,ecx
0053DD34         . |72 06            jb short wincnt.0053DD3C
0053DD36         . |FF15 38124000      call dword ptr ds:[<&MSVBVM60.__vbaGenerateBou>;MSVBVM60.__vbaGenerateBoundsError
0053DD3C         > |8D04BD 00000000    lea eax,dword ptr ds:
0053DD43         . |33FF               xor edi,edi
0053DD45         . |EB 06            jmp short wincnt.0053DD4D
0053DD47         > |FF15 38124000      call dword ptr ds:[<&MSVBVM60.__vbaGenerateBou>;MSVBVM60.__vbaGenerateBoundsError
0053DD4D         > |8B4B 34            mov ecx,dword ptr ds:
0053DD50         . |8B51 0C            mov edx,dword ptr ds:
0053DD53         . |8B0C02             mov ecx,dword ptr ds:
0053DD56         . |B8 01000000      mov eax,1
0053DD5B         . |33F1               xor esi,ecx
0053DD5D         . |8B4D E8            mov ecx,dword ptr ss:
0053DD60         . |03C1               add eax,ecx
0053DD62         . |0F80 CC000000      jo wincnt.0053DE34
0053DD68         . |8945 E8            mov dword ptr ss:,eax
0053DD6B         .^\E9 41FFFFFF      jmp wincnt.0053DCB1//上面的一个大循环就是CRC32计算了
对UNICODE格式的字符串"5896549AAA-wincnt^LTB19879"进行CRC32计算:
0053DD70         > \F7D6               not esi                                        ;对取得CRC32值取反得10进制数:"795102726"
0053DD72         .68 B4434200      push wincnt.004243B4                           ;UNICODE "00000000"
0053DD77         .56               push esi
0053DD78         .FF15 EC104000      call dword ptr ds:[<&MSVBVM60.__vbaStrI4>]   ;MSVBVM60.__vbaStrI4
0053DD7E         .8B35 08144000      mov esi,dword ptr ds:[<&MSVBVM60.__vbaStrMove>>;MSVBVM60.__vbaStrMove
0053DD84         .8BD0               mov edx,eax
0053DD86         .8D4D D0            lea ecx,dword ptr ss:
0053DD89         .FFD6               call esi                                       ;<&MSVBVM60.__vbaStrMove>
0053DD8B         .50               push eax
0053DD8C         .FF15 58114000      call dword ptr ds:[<&MSVBVM60.__vbaStrCat>]    ;将结果与00000000相连
0053DD92         .8945 C8            mov dword ptr ss:,eax                  ;得:"00000000795102726"
0053DD95         .8D45 C0            lea eax,dword ptr ss:
0053DD98         .6A 08            push 8
0053DD9A         .8D4D B0            lea ecx,dword ptr ss:
0053DD9D         .50               push eax
0053DD9E         .51               push ecx
0053DD9F         .C745 C0 08000000   mov dword ptr ss:,8
0053DDA6         .FF15 18144000      call dword ptr ds:[<&MSVBVM60.#619>]         ;取得到的字符串右8位:"95102726"
从这个CALL返回后,我就没做记录了,后面只是简单的将我们输入的假码前4位当做用户名,与我们上面一路过来所得到的值,用“_”相连!
这里的结果是“AAA-_95102726”

下面是我用C++写的KeyGen:
#include<iostream>
using namespace std;

unsigned long Crc32Table;
void GetCRC32Table(){
   int i,j;
   unsigned long Crc;
   for (i = 0; i < 256; i++){
      Crc = i;
      for (j = 0; j < 8; j++){
            if (Crc & 1)
                Crc = (Crc >> 1) ^ 0xEDB88320;
            else
                Crc >>= 1;
      }
      Crc32Table = Crc;
    }
}

//获取字符串CRC32校验值
unsigned int GetCrc32(char* InStr,int len){
    GetCRC32Table();
    unsigned int crc=0xffffffff;

    for(int i=0; i<len; i++){
            unsigned int tmp=InStr;
      crc = (crc >> 8) ^ Crc32Table[(crc & 0xFF) ^ tmp];
    }   
           return crc;
}

int main(){
        cout<<"请输入你的用户名(4位长字符):\t";
        char name;
        cin>>name;
       
        char str={0};
        sprintf(str,"5896549%swincnt^LTB19879",name);
       
        //下面是手工将ASCII转成UNICODE的,呵呵
        char ch={0};
        int len=strlen(str);
        int j=0;
        for(int i=0;i<len;i++){
                ch=str;
                j++;
                ch=0;
                j++;
        }
       
        unsigned int crc32=GetCrc32(ch,j);//得到上面字符串的CRC32值
        crc32 = crc32 ^ 0xFFFFFFFF; //对取得的CRC32值取反
       
        char tmp={0};       
        sprintf(tmp,"%d",crc32);//格式化成字符串
       
        char regCode={0};
        sprintf(regCode,"%s_%s",name,&tmp);                //生成并打印出来
        cout<<"Your RegCode Is: "<<regCode<<endl;
        return 0;
}


链接:http://www.iawen.com/read.php/240.htm

M0nster 发表于 2009-3-25 16:43

鸦哥叫我摸摸行不

wgz001 发表于 2009-3-25 16:53

:handshake向楼主学习算法

manbug 发表于 2009-3-25 19:11

学习学习!!!!!!

A-new 发表于 2009-3-25 19:23

用户名位数多会产生点错误,偶来个VC++6的源码

ciik 发表于 2009-3-27 22:51

看的一头雾水,理解能力有限,楼主辛苦了

wunai2006 发表于 2010-7-27 20:28

真的没看明白

libmifan 发表于 2013-10-17 09:22

还看不懂,谢谢LZ分享:(

ztxyzu 发表于 2013-10-18 15:57

向楼主学习算法
页: [1]
查看完整版本: 一个国外程序的算法分析[CRC32算法]