-
-
[原创]一个kegenMe的简要分析与kegen
-
发表于: 2009-10-13 22:07 3692
-
一:去掉烦人的音乐
这个kegenme比较吵,
Ctrl+N,看看调用了那些与音乐相关的函数
winmm.waveOutClose
winmm.waveOutGetPosition
winmm.waveOutOpen
winmm.waveOutPrepareHeader
winmm.waveOutReset
winmm.waveOutUnprepareHeader
winmm.waveOutWrite
显示,从函数的名称可以看出waveOutOpen是音乐的开启函数
在它上面右键->在每个参考上设置断点,F9运行
来到:
Alt+F9
来到:
****************************************************************************
二:unlock key分析
现在开干正事:
0040123D cmp eax,6 ; 注册名的长度必须大于6
这个keygenme的unlock Key和active Key都只跟用户名的前6位有关
进入这个call后来到:
进入call 00401562后来到
后面有5处是上面的重复
只不过eax不再是name[0],而分别是name[1],name[2],name[3],name[4],name[5]
上面的table2[0]表分别换成table2[1],table2[2],table2[3],table2[4],table2[5]
004013DD push eax
0040141D push eax
0040145D push eax
0040149D push eax
004014DD push eax
上面的程序用c++实现就是:
把 sum[i](i=0,1,2,3,4,5) 以16进制的形式格式输出
如:name为:f3k0eibj0对应的
sum[0]=0X0B9A93087,sum[1]=0X0AA5CEF63,sum[2]=0X0EBCEC057
sum[3]=0X,sum[2]=0X0F7E943A7,sum[2]=0X44BF762B,sum[2]=0X0CD913F5F
结果就是:CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087
这个结果就是我们的unlock Key
把你填入的unlock Key码和真码比较,看是否相等
**********************************************************************************
三 active Key的分析
进入上面的call后
进入call 00401690
上面用c++实现就是:
//注册码的长度必须为48位,可以写一个小程序穷举出来
大功告成
给一组:
Unlock key: ADBA3DEB9CDDA6071EC143A7C75DFEEF38CBDF4B631D20AF
User name: r668o6y8
Activation key:010011001010001001001100000001001200101011000100
********************************************
注:原程序和keygen的源码在附近里面
这个程序的用户名有限制是我后来才知道的,所以我的keygen有点问题,有时候点产生,不出来信息
多点几次就可以了
这个kegenme比较吵,
Ctrl+N,看看调用了那些与音乐相关的函数
winmm.waveOutClose
winmm.waveOutGetPosition
winmm.waveOutOpen
winmm.waveOutPrepareHeader
winmm.waveOutReset
winmm.waveOutUnprepareHeader
winmm.waveOutWrite
显示,从函数的名称可以看出waveOutOpen是音乐的开启函数
在它上面右键->在每个参考上设置断点,F9运行
来到:
00403FAA $- FF25 9C504000 jmp dword ptr ds:[<&winmm.waveOutOpen>] ; WINMM.waveOutOpen
Alt+F9
来到:
00040192F E8 76260000 call <jmp.&winmm.waveOutOpen> 00401934 |. 85C0 test eax,eax 把call <jmp.&winmm.waveOutOpen> nop掉,保存,然后启动改后的程序,世界清静了 ^_^
****************************************************************************
二:unlock key分析
现在开干正事:
0040123D cmp eax,6 ; 注册名的长度必须大于6
这个keygenme的unlock Key和active Key都只跟用户名的前6位有关
00401359 push eax ; eax为用户名的第一位,即name[0] 0040135A xor eax,dword ptr ds:[edx*4+406000] ; dword ptr ds:[edx*4+406000] 是根据edx的值到一张固定的表table1中取取值,把值取出来后eax异或 00401361 push eax 00401362 and eax,0FFFF ;取出eax的后16位 00401367 mov ebx,eax 00401369 pop eax 0040136A and eax,FFFF0000 ;取出eax的前16位 0040136F imul eax,ebx ;eax的前16位与后16相乘 00401372 xor eax,ebx ;上面相乘的结果和eax的后16位相加 00401374 mov dword ptr ds:[edi],eax ; 把上面的结果放入一张空表table2[0]中(table2为一个二维表) 00401376 add edi,4 00401379 add edx,4 0040137C pop eax 0040137D loopd short 1.00401359 ;根据ecx来判断循环是否要继续(共循环6次)
00401380 push edi 00401381 call 0040152B ;这是一个算法call
进入这个call后来到:
0040153F mov al,byte ptr ds:[esi] 把表table2[0]中的数据取出来(00401374处存入的数据) 00401541 cmp al,0 00401543 je short 1.0040155D 判断al是否为0,如果为0就跳出循环 相当于一个break; 00401545 div bx al的值对bx=2求余 00401548 or dx,dx 0040154B jnz short 1.0040155A 判断余数是否为0,如果为0就进行下一次循环 相当于continue 0040154D inc ecx 0040154E inc esi 0040154F push ecx 00401550 push dword ptr ss:[ebp+8] 00401553 call 1.00401562 ;这是一个算法call 00401558 jmp short 1.0040153F 0040155A inc esi 0040155B jmp short 1.0040153F
进入call 00401562后来到
0040156E mov al,byte ptr ds:[esi] ;把表table2[0]中的数据取出来给al 00401570 xor al,10 ;al与16作异或 00401572 mov byte ptr ds:[esi],al ;把异或后的结果存入表table2[0]中 00401574 inc esi 00401575 loopd short 1.0040156E ;循环
后面有5处是上面的重复
只不过eax不再是name[0],而分别是name[1],name[2],name[3],name[4],name[5]
上面的table2[0]表分别换成table2[1],table2[2],table2[3],table2[4],table2[5]
004013DD push eax
0040141D push eax
0040145D push eax
0040149D push eax
004014DD push eax
上面的程序用c++实现就是:
UINT table1[]={0x77073096,0x706AF48F,0x79DCB8A4,0x7EB17CBD,0x6AB020F2,0x6DDDE4EB, 0x646BA8C0,0x63066CD9,0x4C69105E,0x4B04D447,0x42B2986C,0x45DF5C75, 0x51DE003A,0x56B3C423,0x5F058808,0x58684C11,0x01DB7106,0x06B6B51F, 0x0F00F934,0x086D3D2D,0x1C6C6162,0x1B01A57B,0x12B7E950,0x15DA2D49, 0x3AB551CE,0x3DD895D7,0x346ED9FC,0x33031DE5,0x270241AA,0x206F85B3, 0x29D9C998,0x2EB40D81,0x9ABFB3B6,0x9DD277AF,0x94643B84,0x9309FF9D}; UINT table2[7][10]={0}; for(i=0;i<6;i++) { for(j=0;j<6;j++,k++) { temp=name[i]^table1[k]; temp1=temp&0x0FFFF; temp2=temp&0x0FFFF0000; temp2=temp1*temp2; temp2=temp2+temp1; table2[i][j]=temp2; } change1((char *)&table2[i][0]); } 其中: void change1(char* table) { int j=1; for(int i=0;i<24;i++) { if(table[i]==0) break; if(table[i]%2!=0) continue; j++; change2(table,j); } } 等同于算法中的call 0040152B 其中: void change2(char* table,int n) { for (int i=0;i<n;i++) { table[i]^=0x10; } } 等同于call 00401562
00401595 inc edx 00401596 add esi,10 00401599 add eax,dword ptr ds:[esi] 0040159B add esi,4 0040159E loopd short 1.00401599 ; 把上面的表table2[i](i=0,1,2,3,4,5)中的值分别累计求和 得到sum[i](i=0,1,2,3,4,5)
004015A0 mov ecx,6 004015A5 push eax 004015A6 mov dword ptr ds:[ebx],eax 004015A8 add ebx,4 004015AB xor eax,eax 004015AD cmp edx,5 004015B0 jnz short 1.00401595 004015B2 push 1.004068A9 004015B7 push 1.0040686D 004015BC call <jmp.&user32.wsprintfA> ;
把 sum[i](i=0,1,2,3,4,5) 以16进制的形式格式输出
如:name为:f3k0eibj0对应的
sum[0]=0X0B9A93087,sum[1]=0X0AA5CEF63,sum[2]=0X0EBCEC057
sum[3]=0X,sum[2]=0X0F7E943A7,sum[2]=0X44BF762B,sum[2]=0X0CD913F5F
结果就是:CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087
这个结果就是我们的unlock Key
00401269 push 1.0040686D ; ASCII "CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087" 0040126E push 1.004066B1 ; ASCII "CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087" 00401273 call 1.00401634 00401278 test eax,eax 0040127A je short 1.004012CF
把你填入的unlock Key码和真码比较,看是否相等
**********************************************************************************
三 active Key的分析
004012B8 push eax 004012B9 push edi 004012BA push esi 004012BB call 0040165F //一个算法call 004012C0 add esi,28 004012C3 add edi,28 004012C6 add eax,2 004012C9 loopd short 1.004012B8 //循环5次
进入上面的call后
00401675 mov ax,word ptr ds:[esi] //取出上面table2[i]中的值(i=0,1,2,3,4) 00401678 mov bx,word ptr ds:[edi] //取出上面table2[i+1]中的值 0040167B call 00401690 //一个算法call 00401680 add word ptr ds:[edx],ax //[edx]和ax相加,相加的结果放入表tablek中即[edx] 00401683 add esi,2 00401686 add edi,2 00401689 loopd short 00401675 //循环24次
进入call 00401690
00401690 cmp ax,bx 00401693 jb short 1.00401697 00401695 xchg ax,bx //看ax和bx哪个大,大的给bx,小的给ax 00401697 sub bx,ax //大数减去小数 0040169A jnz short 1.00401690
上面用c++实现就是:
for(i=0;i<5;i++) { gettable((WORD *)table2[i],(WORD *)table2[i+1],i); if(i==3) scpy(table2[6],(UINT*)tablek); } 其中: void gettable(WORD* table1,WORD* table2,int index) { int i=0; int temp=0; for (i=0;i<0x18;i++) { temp+=sub(table1[i],table2[i]); } tablek[index]=temp; } 相当于call 0040165F 其中: int sub(int a,int b) { int max=a>b?a:b; int min=a<b?a:b; int temp=0; for(;;) { max=max-min; if(max<min) { temp=max; max=min; min=temp; } if(min==0) break; } return max; } 相当于:call 00401690
004016C4 xor eax,7D079EB1 004016C9 mov edx,4ADFA541 004016CE xor eax,edx 004016D0 sub eax,3F4D1 004016D5 imul eax,eax,33 004016D8 loopd short 1.004016C4 004016DA cmp eax,CE337A1C 004016DF jnz short 1.004016EA
//注册码的长度必须为48位,可以写一个小程序穷举出来
int main(int argc, char* argv[]) { int i=0; int j=0; unsigned int temp=0; for(i=1;;i++) { temp=i; for(j=0;j<6;j++) { temp^=0x7D079EB1; temp^=0x4ADFA541; temp-=0x3F4D1; temp=(temp*0x33)&0xFFFFFFFF; } if(temp==0x0CE337A1C) break; } printf("这个数是:%d",i); return 0; }
00401723 mov bl,byte ptr ds:[edi] 00401725 cmp bl,30 00401728 jb short 1.00401733 0040172A cmp bl,39 0040172D ja short 1.00401733 0040172F jmp short 1.00401746 00401731 jmp short 1.00401746 00401733 cmp bl,41 00401736 jb short 1.00401741 00401738 cmp bl,5A 0040173B ja short 1.00401741 0040173D jmp short 1.00401746 0040173F jmp short 1.00401746 00401741 jmp 1.00401827 // active Key的每一位只能是数字或大写字母
00401746 mov al,byte ptr ds:[esi] 00401748 call 00401690 //unl key的i位和active Key的i位作一运算,这个运算就是前面提到的int sub(int a,int b)
00401752 mov dx,word ptr ds:[ebx] ;取出[ebx]中的值给dx,就相当于在talbleK中取值 00401755 xor dx,word ptr ds:[ebx+4] ;异或运算 00401759 add dx,word ptr ds:[ebx+8] ;加法运算 0040175D sub dx,word ptr ds:[ebx+B] ;减法运算 00401761 imul eax,edx ;乘法运算 00401764 xor edx,edx 00401766 push eax 00401767 call 1.004016F3 //对eax的值开方取整
004017F1 div cx 上面的eax对cx求余 004017F4 or dx,dx 004017F7 pop ecx 0040180F jnz 00401602上面求余的结果必须为0
大功告成
给一组:
Unlock key: ADBA3DEB9CDDA6071EC143A7C75DFEEF38CBDF4B631D20AF
User name: r668o6y8
Activation key:010011001010001001001100000001001200101011000100
********************************************
注:原程序和keygen的源码在附近里面
这个程序的用户名有限制是我后来才知道的,所以我的keygen有点问题,有时候点产生,不出来信息
多点几次就可以了
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
赞赏
雪币:
留言: