首页
社区
课程
招聘
[原创]一个kegenMe的简要分析与kegen
发表于: 2009-10-13 22:07 3692

[原创]一个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运行
来到:
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直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回