www.pudn.com > QQ_Sniffer.rar > mycrypt.cpp
/*
* qq decrypt functions, Tencent never modify it since 2001
* original code from pure(วเายกซ shadow in silence)'s post at
* Crack@bbs.tsinghua.edu.cn
* Copyright (c) 2001 Shellcode@sina.com.cn
* edited by doublelee@etang.com
*/
#include "stdafx.h"
#include "mycrypt.h"
unsigned int swapu32(unsigned int n)
{
// In fact htonl() return it!
return(((n & 0xff000000) >> 24) | ((n & 0x000000ff) << 24) |
((n & 0x00ff0000) >> 8) | ((n & 0x0000ff00) << 8));
}
unsigned short swapu16(unsigned short n)
{
// In fact swab() return it!
return(((n & 0x00ff) << 8) | ((n & 0xff00) >> 8));
}
// added by doublelee;
void decrypt_tea_16(unsigned long *in, unsigned long *key, unsigned long *out)
{
// Their is some difference between it and the original TEA routine
// code by David Wheeler and Roger Needham, which can be found on
// http://www.ftp.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html
unsigned long code[4];
register unsigned long n=16, sum, y, z, delta = 0x9E3779B9;
sum = delta << 4;
y = swapu32(in[0]);
z = swapu32(in[1]);
code[0] = swapu32(key[0]); code[1] = swapu32(key[1]);
code[2] = swapu32(key[2]); code[3] = swapu32(key[3]);
while(n-->0)
{
z -= ((y>>5)+code[3])^((y<<4)+code[2])^(sum+y);
y -= ((z>>5)+code[1])^((z<<4)+code[0])^(sum+z);
sum -= delta;
}
out[0] = swapu32(y);
out[1] = swapu32(z);
}
void decrypt_qword(unsigned long *in, unsigned long *key, unsigned long *out)
{
decrypt_tea_16(in, key, out);
// following are pure's code, it is exactly a 16-round TEA
/*
unsigned long code[4];
register unsigned long i=16, j=0xe3779B90, m, n;
m = swapu32(in[0]);
n = swapu32(in[1]);
code[0] = swapu32(key[0]); code[1] = swapu32(key[1]);
code[2] = swapu32(key[2]); code[3] = swapu32(key[3]);
while(i-- >0)
{
n -= ((m>>5)+code[3])^((m<<4)+code[2])^(j+m);
m -= ((n>>5)+code[1])^((n<<4)+code[0])^(j+n);
j += 0x61C88647;
}
out[0] = swapu32(m);
out[1] = swapu32(n);
*/
}
int decrypt_msg(unsigned char *in, int inlen, unsigned long *key,
unsigned char *out, unsigned long *outlen)
{
unsigned char q[8], mkey[8], *q1, *q2, *outp;
register int count, i, j, p;
if (inlen%8 || inlen<16) return 0;
/* get basic information of the packet */
decrypt_qword((unsigned long *)in, key, (unsigned long *)q);
j = q[0]&0x7;
count = inlen - j - 10;
// if (*outlen < count || count < 0) return 0; //?????*outlen
if (count < 0) return 0;
*outlen = count;
memset(mkey, 0, 8);
q2 = mkey;
i = 8; p = 1;
q1 = in+8;
j ++;
while (p <= 2) { //0x004576af
if (j < 8) { //0x00457648
j ++;
p ++;
} else if (j == 8) {
q2 = in;
for (j = 0; j < 8; j ++ ) {
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_qword((unsigned long *)q, key, (unsigned long *)q);
i += 8;
q1 += 8;
j = 0;
}
}
outp = out;
while(count !=0) {
if (j < 8) {
outp[0] = q2[j] ^ q[j];
outp ++;
count --;
j ++;
} else if (j == 8) {
q2 = q1-8;
for (j = 0; j < 8; j ++ ) {
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_qword((unsigned long *)q, key, (unsigned long *)q);
i += 8;
q1 += 8;
j = 0;
}
}
for (p = 1; p < 8; p ++) {
if (j < 8) {
if (q2[j]^q[j])
return 0;
j ++;
} else if (j == 8 ) {
q2 = q1;
for (j = 0; j < 8; j ++ ) {
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_qword((unsigned long *)q, key, (unsigned long *) q);
i += 8;
q1 += 8;
j = 0;
}
}
return 1;
}
int simple_decrypt(unsigned char *in, unsigned long *key)
{
// code following comes from qq.asm and pure's code
// do a quick decryption for HH key checking, for efficiency of
// bruteforce cracking
// assume *in has a length of 16, we try to decrypt it with the key 'key'
unsigned char out[20];
unsigned char q[8], mkey[8], *q1, *q2, *outp;
register int count, i, j, p;
int inlen = 16;
/* get basic information of the packet */
decrypt_tea_16((unsigned long *)in, key, (unsigned long *)q);
j = q[0]&0x7;
count = inlen - j - 10;
if (count) return 0;
//mostly it will return here, so make it quick when cracking than decrypt_msg().
memset(mkey, 0, 8);
q2 = mkey;
i = 8; p = 1;
q1 = in+8;
j ++;
while (p <= 2)
{
if (j < 8)
{
j ++;
p ++;
}
else if (j == 8)
{
q2 = in;
for (j = 0; j < 8; j ++ )
{
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_tea_16((unsigned long *)q, key, (unsigned long *) q);
i += 8;
q1 += 8;
j = 0;
}
}
outp = out;
while(count !=0)
{
if (j < 8)
{
outp[0] = q2[j] ^ q[j];
outp ++;
count --;
j ++;
}
else if (j == 8)
{
q2 = q1-8;
for (j = 0; j < 8; j ++ )
{
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_tea_16((unsigned long *)q, key, (unsigned long *) q);
i += 8;
q1 += 8;
j = 0;
}
}
for (p = 1; p < 8; p ++)
{
if (j < 8)
{
if (q2[j]^q[j]) return 0;
j ++;
}
else if (j == 8 )
{
q2 = q1;
for (j = 0; j < 8; j ++ )
{
if (i + j >= inlen) return 0;
q[j] ^= q1[j];
}
decrypt_tea_16((unsigned long *)q, key, (unsigned long *) q);
i += 8;
q1 += 8;
j = 0;
}
}
return 1;
}
// encryption code omitted. we just never use it!