文章标题:QQKAV算法分析
软件名称:QQKAV
使用工具:od
软件大小:486K
作者声明:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
软件下载地址:http://www.jsing.net/soft/qqkav.exe

注册机源码下载

QQKAV之算法分析。
软件的壳脱了,接下来自己就是对其进行破解了。用PEID一查Borland Delphi 6.0 - 7.0,壳已经脱去,好了,看下软件是否用了一些网络上有名的算法,二话不说,直接先用PEID自带的KANAL插件扫描了下,呵呵,惊喜的发现了,软件果然用了TEA算法
 
用OD加载来到004C211A处,下面我直接给出代码,注释在里面。

004C1EFA   .^\EB E8         JMP SHORT dump_1.004C1EE4
004C1EFC   .  8D85 D4FDFFFF LEA EAX,DWORD PTR SS:[EBP-22C]
004C1F02   .  E8 99FDFFFF   CALL dump_1.004C1CA0
004C1F07   .  8B95 D4FDFFFF MOV EDX,DWORD PTR SS:[EBP-22C]
004C1F0D   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004C1F10   .  8B80 70030000 MOV EAX,DWORD PTR DS:[EAX+370]
004C1F16   .  E8 8507F8FF   CALL dump_1.004426A0
004C1F1B   .  8D95 D0FDFFFF LEA EDX,DWORD PTR SS:[EBP-230]
004C1F21   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004C1F24   .  8B80 70030000 MOV EAX,DWORD PTR DS:[EAX+370]
004C1F2A   .  E8 4107F8FF   CALL dump_1.00442670
004C1F2F   .  83BD D0FDFFFF>CMP DWORD PTR SS:[EBP-230],0
004C1F36   .  75 13         JNZ SHORT dump_1.004C1F4B                ;  程序之前调用GetUserNameA得到当前登入的用户名
004C1F38   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]             ;  有兴趣的可以下个断
004C1F3B   .  8B80 70030000 MOV EAX,DWORD PTR DS:[EAX+370]           ;  得到用户失败则默认的用户名为QQKav
004C1F41   .  BA B42F4C00   MOV EDX,dump_1.004C2FB4                  ;  ASCII "QQKav"
004C1F46   .  E8 5507F8FF   CALL dump_1.004426A0
004C1F4B   >  8D95 CCFDFFFF LEA EDX,DWORD PTR SS:[EBP-234]
004C1F51   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004C1F54   .  8B80 70030000 MOV EAX,DWORD PTR DS:[EAX+370]
004C1F5A   .  E8 1107F8FF   CALL dump_1.00442670
004C1F5F   .  83BD CCFDFFFF>CMP DWORD PTR SS:[EBP-234],0
004C1F66   .  0F84 F3000000 JE dump_1.004C205F
004C1F6C   .  8D55 F4       LEA EDX,DWORD PTR SS:[EBP-C]
004C1F6F   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004C1F72   .  8B80 70030000 MOV EAX,DWORD PTR DS:[EAX+370]
004C1F78   .  E8 F306F8FF   CALL dump_1.00442670
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。省略。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
004C20F8   .  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]             ;  说下用户名处理
004C20FB   .  0FB64402 FF   MOVZX EAX,BYTE PTR DS:[EDX+EAX-1]        ;  TEA输入端是8个字节
004C2100   .  03F0          ADD ESI,EAX                              ;  用户名不足八个字节,作者在用户名补上"请Cracker手下留情"直到8个字节为止
004C2102   .  C1E6 08       SHL ESI,8                                ;  举个例子吧
004C2105   .  4B            DEC EBX                                  ;  我的机器的用户名是user,不够吧,呵呵,此时就被他补成了"user请Cr"
004C2106   .  80FB 05       CMP BL,5
004C2109   .^ 75 E9         JNZ SHORT dump_1.004C20F4
004C210B   .  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
004C210E   .  0FB640 04     MOVZX EAX,BYTE PTR DS:[EAX+4]            ;  ECX中保存了用户名前四个字节(这里的用户名是处理成8个字节的用户名了)
004C2112   .  03F0          ADD ESI,EAX                              ;  ESI中保存了用户名的后4个字节
004C2114   .  33FF          XOR EDI,EDI
004C2116   .  B3 20         MOV BL,20                                ;  32轮迭代
004C2118   >  81C7 B979379E ADD EDI,9E3779B9                         ;  9E3779B9黄金分割率,至此已经完全确认使用了,TEA算法
004C211E   .  8BC6          MOV EAX,ESI
004C2120   .  C1E0 04       SHL EAX,4
004C2123   .  03C8          ADD ECX,EAX                              ;  16字节key,这个软件作者有趣,key采用"You are the big dog."
004C2125   .  8B45 B4       MOV EAX,DWORD PTR SS:[EBP-4C]            ;  指向key
004C2128   .  33C6          XOR EAX,ESI
004C212A   .  03C8          ADD ECX,EAX
004C212C   .  8BC6          MOV EAX,ESI
004C212E   .  C1E8 05       SHR EAX,5
004C2131   .  33C7          XOR EAX,EDI
004C2133   .  03C8          ADD ECX,EAX
004C2135   .  034D B8       ADD ECX,DWORD PTR SS:[EBP-48]            ;  key
004C2138   .  8BC1          MOV EAX,ECX
004C213A   .  C1E0 04       SHL EAX,4
004C213D   .  03F0          ADD ESI,EAX
004C213F   .  8B45 BC       MOV EAX,DWORD PTR SS:[EBP-44]            ;  key
004C2142   .  33C1          XOR EAX,ECX
004C2144   .  03F0          ADD ESI,EAX
004C2146   .  8BC1          MOV EAX,ECX
004C2148   .  C1E8 05       SHR EAX,5
004C214B   .  33C7          XOR EAX,EDI
004C214D   .  03F0          ADD ESI,EAX
004C214F   .  0375 C0       ADD ESI,DWORD PTR SS:[EBP-40]            ;  key
004C2152   .  FECB          DEC BL
004C2154   .^ 75 C2         JNZ SHORT dump_1.004C2118
004C2156   .  8BC1          MOV EAX,ECX                              ;  TEA输出端的前四个字节在ECX
004C2158   .  25 FFFFFF3F   AND EAX,3FFFFFFF                         ;  后四个字节没用到
004C215D   .  83C0 02       ADD EAX,2
004C2160   .  33D2          XOR EDX,EDX
004C2162   .  8945 E8       MOV DWORD PTR SS:[EBP-18],EAX            ;  简单的与运行和加运算,暂时保存起来。
004C2165   .  8955 EC       MOV DWORD PTR SS:[EBP-14],EDX
004C2168   .  8BC1          MOV EAX,ECX                              ;  记住程序注册码分两个部份,刚才的输出端的前四个字节经过简单的处理后,又做为计算第二个注册码的e
004C216A   .  C1E8 1E       SHR EAX,1E                               ;  移位
004C216D   .  05 5000F824   ADD EAX,24F80050                         ;  呵呵,这就不说了
004C2172   .  83C0 02       ADD EAX,2
004C2175   .  33D2          XOR EDX,EDX
004C2177   .  8945 E0       MOV DWORD PTR SS:[EBP-20],EAX
004C217A   .  8955 E4       MOV DWORD PTR SS:[EBP-1C],EDX
004C217D   .  FF75 EC       PUSH DWORD PTR SS:[EBP-14]               ; /中间插入了三个push 0,为了防止,算法的特征码被发现
004C2180   .  FF75 E8       PUSH DWORD PTR SS:[EBP-18]               ; |经过TEA处理后的中间码,即e
004C2183   .  6A 00         PUSH 0                                   ; |Arg4 = 00000000
004C2185   .  68 F9862C00   PUSH 2C86F9                              ; |RSA公钥
004C218A   .  6A 00         PUSH 0                                   ; |
004C218C   .  68 E3A0AA69   PUSH 69AAA0E3                            ; |n
004C2191   .  E8 5ACFFFFF   CALL dump_1.004BF0F0                     ; \有兴趣可以跟进m^e Mod n
004C2196   .  8945 E8       MOV DWORD PTR SS:[EBP-18],EAX
004C2199   .  8955 EC       MOV DWORD PTR SS:[EBP-14],EDX
004C219C   .  8B45 E8       MOV EAX,DWORD PTR SS:[EBP-18]
004C219F   .  8B55 EC       MOV EDX,DWORD PTR SS:[EBP-14]
004C21A2   .  0345 E0       ADD EAX,DWORD PTR SS:[EBP-20]
004C21A5   .  1355 E4       ADC EDX,DWORD PTR SS:[EBP-1C]
004C21A8   .  52            PUSH EDX                                 ; /同理
004C21A9   .  50            PUSH EAX                                 ; |第二次简单处理后的e
004C21AA   .  6A 00         PUSH 0                                   ; |Arg4 = 00000000
004C21AC   .  68 F9862C00   PUSH 2C86F9                              ; |Arg3 = 002C86F9
004C21B1   .  6A 00         PUSH 0                                   ; |Arg2 = 00000000
004C21B3   .  68 E3A0AA69   PUSH 69AAA0E3                            ; |Arg1 = 69AAA0E3
004C21B8   .  E8 33CFFFFF   CALL dump_1.004BF0F0                     ; \dump_1.004BF0F0

至此算法分析完闭,开始写注册机了,下面直接给出我VC写的注册机源码(由于程序中用到了RSA所以我用到了大数库):
//TEA算法:
void tiny_encrypt(unsigned long *const v, unsigned long *const w,
const unsigned long *const k)
{
register unsigned long
y = v[0],
z = v[1],
a = k[0],
b = k[1],
c = k[2],
d = k[3],
n = TEA_ROUNDS,
sum = 0,
delta = TEA_DELTA;


while (n-- > 0) {

sum += delta;
y += (z << 4);
y +=a ^ z ;
y +=sum ^ (z >> 5);
y += b;
z += (y << 4);
z += c ^ y ;
z += sum ^ (y >> 5);
z += d;

}

w[0] = y;
w[1] = z;
}

void CQQKavKeyGenGUIDlg::OnCalc() 
{
  CString temp;
  // TODO: Add your control notification handler code here
    unsigned char *v;
  CString a,b,c;
  CBigInt m,e,n,KeyL,KeyR;
  unsigned char k[17]="You are big pig.";//key
  unsigned long w[2];
  this->UpdateData();
  temp=m_UserName;
  if(m_UserName.GetLength()<8)
  {
    if(m_UserName.GetLength()==0)
    {
      m_UserName.Insert(0,"QQKav");
      temp="QQKav";
    }
  m_UserName.Insert(m_UserName.GetLength(),"请Cracker手下留情");
  }

  v=(unsigned char *)m_UserName.GetBuffer(m_UserName.GetLength());
  
    tiny_encrypt((unsigned long *const)v,w,(unsigned long *const)k);
  w[1]=w[0];//由于软件并没用到输出端的后四个字节,所以我这里就用来保存前四个字节,等到下面计算注册码后部份要用到
    w[0]=w[0] & 0x3FFFFFFF;
    w[0]+=2;
  w[1]=w[1]>>0x1E;//保存的前四个字节
  w[1]=w[1]+0x24F80052;//简单的运算后,参与rsa解密,算出注册码后半部份
  a.Format("%d",w[0]);
  m.Get(a,DEC);
  e.Get(CString("2C86F9"));
  n.Get(CString("69AAA0E3"));
  KeyL=m.RsaTrans(e,n);
  KeyL.Put(m_KeyL);
    KeyR=KeyL.Add(w[1]);
  KeyR.Put(m_KeyR);
    KeyR=KeyR.RsaTrans(e,n);
  KeyR.Put(m_KeyR);
  m_UserName=temp;
    this->UpdateData(FALSE);
}

搞定,收工。谢谢大家观看!!!