一个国外程序的算法分析[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 鸦哥叫我摸摸行不 :handshake向楼主学习算法 学习学习!!!!!! 用户名位数多会产生点错误,偶来个VC++6的源码 看的一头雾水,理解能力有限,楼主辛苦了 真的没看明白 还看不懂,谢谢LZ分享:( 向楼主学习算法
页:
[1]