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!