renwoxiao 发表于 2009-10-14 19:21:17

一个kegenMe的简要分析与kegen

一:去掉烦人的音乐
这个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位有关
00401359push eax                                 ; eax为用户名的第一位,即name
0040135Axor eax,dword ptr ds:      ; dword ptr ds: 是根据edx的值到一张固定的表table1中取取值,把值取出来后eax异或
00401361push eax                               
00401362and eax,0FFFF                              ;取出eax的后16位
00401367mov ebx,eax
00401369pop eax
0040136Aand eax,FFFF0000                             ;取出eax的前16位
0040136Fimul eax,ebx                                     ;eax的前16位与后16相乘
00401372xor eax,ebx                                     ;上面相乘的结果和eax的后16位相加
00401374mov dword ptr ds:,eax               ; 把上面的结果放入一张空表table2中(table2为一个二维表)
00401376add edi,4
00401379add edx,4
0040137Cpop eax
0040137Dloopd short 1.00401359                     ;根据ecx来判断循环是否要继续(共循环6次)

00401380   push edi
00401381   call 0040152B               ;这是一个算法call
进入这个call后来到:
0040153Fmov al,byte ptr ds:       把表table2中的数据取出来(00401374处存入的数据)
00401541cmp al,0
00401543je short 1.0040155D         判断al是否为0,如果为0就跳出循环 相当于一个break;         
00401545div bx                        al的值对bx=2求余
00401548or dx,dx         
0040154Bjnz short 1.0040155A          判断余数是否为0,如果为0就进行下一次循环 相当于continue
0040154Dinc ecx
0040154Einc esi
0040154Fpush ecx
00401550push dword ptr ss:                        
00401553call 1.00401562                ;这是一个算法call
00401558jmp short 1.0040153F
0040155Ainc esi
0040155Bjmp short 1.0040153F
进入call 00401562后来到
0040156Emov al,byte ptr ds:   ;把表table2中的数据取出来给al
00401570xor al,10                  ;al与16作异或
00401572mov byte ptr ds:,al   ;把异或后的结果存入表table2中
00401574inc esi
00401575loopd short 1.0040156E   ;循环
后面有5处是上面的重复
只不过eax不再是name,而分别是name,name,name,name,name
上面的table2表分别换成table2,table2,table2,table2,table2
004013DDpush eax
0040141Dpush eax
0040145Dpush eax
0040149Dpush eax
004014DDpush 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={0};
for(i=0;i<6;i++)
{
   for(j=0;j<6;j++,k++)
   {
        temp=name^table1;
        temp1=temp&0x0FFFF;
        temp2=temp&0x0FFFF0000;
        temp2=temp1*temp2;
        temp2=temp2+temp1;
        table2=temp2;
   }
        change1((char *)&table2);               
               
}
其中:
void change1(char* table)
{
int j=1;
for(int i=0;i<24;i++)
{
   if(table==0) break;
   if(table%2!=0) continue;
   j++;
   change2(table,j);
}
}
等同于算法中的call 0040152B
其中:
void change2(char* table,int n)
{
for (int i=0;i<n;i++)
    {
        table^=0x10;
    }
}
等同于call 00401562

00401595inc edx
00401596add esi,10
00401599add eax,dword ptr ds:                     
0040159Badd esi,4                                       
0040159Eloopd short 1.00401599    ;
把上面的表table2(i=0,1,2,3,4,5)中的值分别累计求和
得到sum(i=0,1,2,3,4,5)
                  
004015A0mov ecx,6                                       
004015A5push eax                                          
004015A6mov dword ptr ds:,eax                        
004015A8add ebx,4                                       
004015ABxor eax,eax                                       
004015ADcmp edx,5                                       
004015B0jnz short 1.00401595                              
004015B2push 1.004068A9                                    
004015B7push 1.0040686D                                 
004015BCcall <jmp.&user32.wsprintfA>;      
把 sum(i=0,1,2,3,4,5) 以16进制的形式格式输出
如:name为:f3k0eibj0对应的
sum=0X0B9A93087,sum=0X0AA5CEF63,sum=0X0EBCEC057
sum=0X,sum=0X0F7E943A7,sum=0X44BF762B,sum=0X0CD913F5F
结果就是:CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087
这个结果就是我们的unlock Key
00401269push 1.0040686D                                    ;ASCII "CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087"
0040126Epush 1.004066B1                                    ;ASCII "CD913F5F44BF762BF7E943A7EBCEC057AA5CEF63B9A93087"
00401273call 1.00401634
00401278test eax,eax
0040127Aje short 1.004012CF
把你填入的unlock Key码和真码比较,看是否相等
**********************************************************************************
三 active Key的分析
004012B8push eax                  
004012B9push edi
004012BApush esi
004012BBcall 0040165F   //一个算法call
004012C0add esi,28
004012C3add edi,28
004012C6add eax,2
004012C9loopd short 1.004012B8 //循环5次
进入上面的call后
00401675mov ax,word ptr ds:   //取出上面table2中的值(i=0,1,2,3,4)
00401678mov bx,word ptr ds:   //取出上面table2中的值
0040167Bcall 00401690                    //一个算法call
00401680add word ptr ds:,ax//和ax相加,相加的结果放入表tablek中即
00401683add esi,2
00401686add edi,2
00401689loopd short 00401675   //循环24次
进入call 00401690
00401690cmp ax,bx
00401693jb short 1.00401697
00401695xchg ax,bx //看ax和bx哪个大,大的给bx,小的给ax

00401697sub bx,ax //大数减去小数
0040169Ajnz short 1.00401690
上面用c++实现就是:
for(i=0;i<5;i++)
{
    gettable((WORD *)table2,(WORD *)table2,i);
    if(i==3) scpy(table2,(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,table2);
   }
   tablek=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

004016C4xor eax,7D079EB1
004016C9mov edx,4ADFA541
004016CExor eax,edx
004016D0sub eax,3F4D1
004016D5imul eax,eax,33
004016D8loopd short 1.004016C4                           
004016DAcmp eax,CE337A1C
004016DFjnz 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:                     
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的每一位只能是数字或大写字母

00401746mov al,byte ptr ds:               
00401748call 00401690
//unl key的i位和active Key的i位作一运算,这个运算就是前面提到的int sub(int a,int b)

00401752   mov dx,word ptr ds:      ;取出中的值给dx,就相当于在talbleK中取值
00401755   xor dx,word ptr ds:      ;异或运算
00401759   add dx,word ptr ds:      ;加法运算
0040175D   sub dx,word ptr ds:      ;减法运算
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有点问题,有时候点产生,不出来信息
多点几次就可以了

dh0807 发表于 2009-10-15 08:35:08

“无字天书”高深/:L

chadd 发表于 2009-10-20 14:52:26

看一下这个软件的声音

yanhuohua999 发表于 2009-10-20 15:14:57

我OD一载入就异常啊!!!直接退出不知道怎么回事!

火凤凰 发表于 2009-10-20 23:33:16

真够详细的,要慢慢看

kostlzp 发表于 2009-10-21 10:06:10

写得很详细,学习了!

mrhz 发表于 2009-10-21 14:33:39

不懂,不懂还不懂啊

猪猪CHK 发表于 2009-10-27 14:50:19

keyule 发表于 2009-10-27 21:03:44

谢谢 :loveliness: :loveliness:

as3852711 发表于 2009-11-3 07:32:49

出来冒个泡先!/:good /:good /:good
页: [1]
查看完整版本: 一个kegenMe的简要分析与kegen