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

软件的主页是:http://www.jcrystal.com/

程序没有加壳,用PEid查显示为:Microsoft Visual Basic 5.0 / 6.0
由于是来分析算法,所以我还用PEid的插件来分析了一下程序所用的算法是:

CRC32 [poly] :: 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:[ebp+14]
ALt+F9返回:

004B8DBD         . /0F84 BD000000      je wincnt.004B8E80
004B8DC3         . |8B45 08            mov eax,dword ptr ss:[ebp+8]
004B8DC6         . |8D95 FCFEFFFF      lea edx,dword ptr ss:[ebp-104]
004B8DCC         . |52                 push edx
004B8DCD         . |8B55 E8            mov edx,dword ptr ss:[ebp-18]
004B8DD0         . |8B08               mov ecx,dword ptr ds:[eax]
004B8DD2         . |52                 push edx
004B8DD3         . |50                 push eax
004B8DD4         . |FF91 38090000      call dword ptr ds:[ecx+938]                    ;  这里就是第一个关键CALL了,F7跟进
004B8DDA         . |8B45 E8            mov eax,dword ptr ss:[ebp-18]
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:[ebp-104],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:[ebp-B0]
004B8E07         . |8D4D B0            lea ecx,dword ptr ss:[ebp-50]
004B8E0A         . |8975 98            mov dword ptr ss:[ebp-68],esi
004B8E0D         . |895D 90            mov dword ptr ss:[ebp-70],ebx
004B8E10         . |8975 A8            mov dword ptr ss:[ebp-58],esi
004B8E13         . |895D A0            mov dword ptr ss:[ebp-60],ebx
004B8E16         . |C785 58FFFFFF 4050>mov dword ptr ss:[ebp-A8],wincnt.00415040      ;  UNICODE "Registration failed!"
004B8E20         . |C785 50FFFFFF 0800>mov dword ptr ss:[ebp-B0],8
004B8E2A         . |FFD7               call edi                                       ;  <&MSVBVM60.__vbaVarDup>
004B8E2C         . |8D95 60FFFFFF      lea edx,dword ptr ss:[ebp-A0]
004B8E32         . |8D4D C0            lea ecx,dword ptr ss:[ebp-40]
004B8E35         . |C785 68FFFFFF 2450>mov dword ptr ss:[ebp-98],wincnt.00415024      ;  UNICODE "Invalid Key"
004B8E3F         . |C785 60FFFFFF 0800>mov dword ptr ss:[ebp-A0],8
004B8E49         . |FFD7               call edi                                       ;  <&MSVBVM60.__vbaVarDup>
004B8E4B         . |8D45 90            lea eax,dword ptr ss:[ebp-70]
004B8E4E         . |8D4D A0            lea ecx,dword ptr ss:[ebp-60]
004B8E51         . |50                 push eax
004B8E52         . |8D55 B0            lea edx,dword ptr ss:[ebp-50]
004B8E55         . |51                 push ecx
004B8E56         . |52                 push edx
004B8E57         . |8D45 C0            lea eax,dword ptr ss:[ebp-40]
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:[ebp-70]


跟进上面的那个关键,很快就来到这里:

004CBEC9         .  52                 push edx
004CBECA         .  894D C4            mov dword ptr ss:[ebp-3C],ecx
004CBECD         .  C745 BC 08400000   mov dword ptr ss:[ebp-44],4008
004CBED4         .  FFD7               call edi                             ;  <&MSVBVM60.__vbaLenBstr>
004CBED6         .  83E8 09            sub eax,9                            ;  取用户输入的注册长度,与9比较
004CBED9         .  8D4D CC            lea ecx,dword ptr ss:[ebp-34]
004CBEDC         .  0F80 C5000000      jo wincnt.004CBFA7                   ;  小于9则出错返回
    //0012F7F8  001DAA84  UNICODE "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:[ebp-34]        ;  取出左边4个字符
    //0012F7E8  0021B104  UNICODE "AAA-"


一路单步吧:

004CBF14         .  52                 push edx
004CBF15         .  8D55 EC            lea edx,dword ptr ss:[ebp-14]
004CBF18         .  8B08               mov ecx,dword ptr ds:[eax]
004CBF1A         .  52                 push edx
004CBF1B         .  50                 push eax
004CBF1C         .  FF91 34090000      call dword ptr ds:[ecx+934]          ;  关键CALL,F7跟进



//=========================================================
004CBBED         .  52                 push edx                                         ; /Arg2
004CBBEE         .  50                 push eax                                         ; |Arg1
004CBBEF         .  C785 5CFFFFFF A74D>mov dword ptr ss:[ebp-A4],4DA7                   ; |
004CBBF9         .  C785 54FFFFFF 0200>mov dword ptr ss:[ebp-AC],2                      ; |
004CBC03         .  FF15 E0114000      call dword ptr ds:[<&MSVBVM60.#520>]             ; \将4DA7转换为10格式字符串,即:19879

由此可见,这里的19879是固定的,我们在做注册机时,就可以直接写上了,不用管他的转换!


004CBC3A         .  8D95 44FFFFFF      lea edx,dword ptr ss:[ebp-BC]
004CBC40         .  8D85 34FFFFFF      lea eax,dword ptr ss:[ebp-CC]
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:[ebp-20],esi
004CBD28         .  C745 C4 08000000   mov dword ptr ss:[ebp-3C],8                    ;  将主程序名转成小写
004CBD2F         .  FF15 44114000      call dword ptr ds:[<&MSVBVM60.#518>]           ;  MSVBVM60.rtcLowerCaseVar
004CBD35         .  8B4D E4            mov ecx,dword ptr ss:[ebp-1C]                  ;  //UNICODE "wincnt"
……………………
004CBD4B         .  50                 push eax
004CBD4C         .  51                 push ecx
004CBD4D         .  C785 24FFFFFF 0800>mov dword ptr ss:[ebp-DC],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:[ebp-24]
004CBD71         .  8B10               mov edx,dword ptr ds:[eax]
004CBD73         .  51                 push ecx
004CBD74         .  8B4D 0C            mov ecx,dword ptr ss:[ebp+C]
004CBD77         .  51                 push ecx
004CBD78         .  50                 push eax
004CBD79         .  FF92 44090000      call dword ptr ds:[edx+944]                    ;  关键CALL,继续F7跟进

上面大部分都是字符串的连接操作,我们跟过就明白了,我们继续跟入下面的一个关键CALL吧


//=======================================
004CC8D5         .  C745 C0 65F95900   mov dword ptr ss:[ebp-40],59F965               ; |
004CC8DC         .  C745 B8 03000000   mov dword ptr ss:[ebp-48],3                    ; |
004CC8E3         .  FF15 E0114000      call dword ptr ds:[<&MSVBVM60.#520>]           ; \rtcTrimVar
004CC8E9         .  8B5D 0C            mov ebx,dword ptr ss:[ebp+C]                   ;  又得一字符串: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:[ebp-AC]
004CC92E         .  8D4D 88            lea ecx,dword ptr ss:[ebp-78]
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:[ecx+28]                     ;  关键CALL,继续F7跟进


继续跟进:

//===============================================================
0053DCB1         > /8B4D E8            mov ecx,dword ptr ss:[ebp-18]
0053DCB4         . |8B45 A4            mov eax,dword ptr ss:[ebp-5C]
0053DCB7         . |3BC8               cmp ecx,eax
0053DCB9         . |0F8F B1000000      jg wincnt.0053DD70
0053DCBF         . |8B55 0C            mov edx,dword ptr ss:[ebp+C]
0053DCC2         . |8B02               mov eax,dword ptr ds:[edx]
0053DCC4         . |3BC7               cmp eax,edi
0053DCC6         . |74 20              je short wincnt.0053DCE8
0053DCC8         . |66:8338 01         cmp word ptr ds:[eax],1
0053DCCC         . |75 1A              jnz short wincnt.0053DCE8
0053DCCE         . |8B50 14            mov edx,dword ptr ds:[eax+14]
0053DCD1         . |8BF9               mov edi,ecx
0053DCD3         . |8B48 10            mov ecx,dword ptr ds:[eax+10]
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:[ebp+C]
0053DCF1         . |8B11               mov edx,dword ptr ds:[ecx]
0053DCF3         . |8B4A 0C            mov ecx,dword ptr ds:[edx+C]
0053DCF6         . |33D2               xor edx,edx
0053DCF8         . |8A1401             mov dl,byte ptr ds:[ecx+eax]
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:[ebx+34]
0053DD20         . |3BC7               cmp eax,edi
0053DD22         . |74 23              je short wincnt.0053DD47
0053DD24         . |66:8338 01         cmp word ptr ds:[eax],1
0053DD28         . |75 1D              jnz short wincnt.0053DD47
0053DD2A         . |2B48 14            sub ecx,dword ptr ds:[eax+14]
0053DD2D         . |8BF9               mov edi,ecx
0053DD2F         . |8B48 10            mov ecx,dword ptr ds:[eax+10]
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:[edi*4]
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:[ebx+34]
0053DD50         . |8B51 0C            mov edx,dword ptr ds:[ecx+C]
0053DD53         . |8B0C02             mov ecx,dword ptr ds:[edx+eax]
0053DD56         . |B8 01000000        mov eax,1
0053DD5B         . |33F1               xor esi,ecx
0053DD5D         . |8B4D E8            mov ecx,dword ptr ss:[ebp-18]
0053DD60         . |03C1               add eax,ecx
0053DD62         . |0F80 CC000000      jo wincnt.0053DE34
0053DD68         . |8945 E8            mov dword ptr ss:[ebp-18],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:[ebp-30]
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:[ebp-38],eax                  ;  得:"00000000795102726"
0053DD95         .  8D45 C0            lea eax,dword ptr ss:[ebp-40]
0053DD98         .  6A 08              push 8
0053DD9A         .  8D4D B0            lea ecx,dword ptr ss:[ebp-50]
0053DD9D         .  50                 push eax
0053DD9E         .  51                 push ecx
0053DD9F         .  C745 C0 08000000   mov dword ptr ss:[ebp-40],8
0053DDA6         .  FF15 18144000      call dword ptr ds:[<&MSVBVM60.#619>]           ;  取得到的字符串右8位:"95102726"


从这个CALL返回后,我就没做记录了,后面只是简单的将我们输入的假码前4位当做用户名,与我们上面一路过来所得到的值,用“_”相连!
这里的结果是“AAA-_95102726”

下面是我用C++写的KeyGen:

#include
using namespace std;

unsigned long Crc32Table[256];
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[i] = Crc;
    }
}

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

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

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


编译并运行: