QQ数据包解密

Windows版qq数据包格式:

android版qq数据包格式:

密钥:16个0

算法:tea_crypt算法

pc版qq 0825数据包解密源码:

cpp 复制代码
#include "qq.h"
#include "qqcrypt.h"
#include <WinSock2.h>
#include "../public.h"
#include "../ProtocolParser.h"
#include "../ResultFile.h"
#include "../fileOper.h"
#include <windows.h>


int QQ::isQQ(const char * data, int len, DATALISTHEADER hdr) {
	if (hdr.sock.protocol == 0x11 )
	{
		if ( hdr.sock.dstport == 8000)
		{
			int firstsize = hdr.sizelist->size;
			if (hdr.datalist->data[0] == 0x02 && hdr.datalist->data[firstsize-1] == 0x03 )
			{
				return TRUE;
			}
		}
	}
	return FALSE;
}




int QQ::processQQ(LPDATABLOCKLIST list, LPPACKSIZELIST sizelist, DATALISTHEADER hdr) {
	int ret = 0;

	char lpbuf [0x1000];
	int offset = 0;
	while (list && sizelist)
	{
		int len = DataBlockList::getNextPacket(list, offset, sizelist, (char*)lpbuf);
		if (len > 0)
		{
			QQHEADER * qqhdr = (QQHEADER*)(lpbuf + 1);
			if (qqhdr->cmd == 0x2508)
			{
				int pad = sizeof(QQHEADER) ;
				if (memcmp(lpbuf + 1 + pad, "\x03\x00\x00\x00", 4) == 0)//010101
				{
					pad += 15;
				}else if (memcmp(lpbuf + 1 + pad,"\x00\x00\x00",3) == 0)
				{
					pad += 15;
				}
				char * offset = lpbuf + 1 + pad;
				int size = len - 1 - pad - 1 ;

				unsigned char *key = (unsigned char*)offset;

				int decodelen = size + 1024;
				unsigned char *decodebuf = new unsigned char[size + 1024];

				int ret = qq_decrypt((unsigned char*)offset + 16, size - 16, key, decodebuf, &decodelen);
				if (ret > 0)
				{
					Public::WriteDataFile("qq.dat", (const char*)decodebuf, decodelen);
				}

				delete decodebuf;

				char szqq[16];
				sprintf(szqq, "%u", ntohl(qqhdr->qq));
				ResultFile::writeRecord(hdr, "qq", "on", szqq);
			}
// 			else if (qqhdr->cmd == 0x3608)
// 			{
// 				char szqq[16];
// 				sprintf(szqq, "%u", ntohl(qqhdr->qq));
// 				ResultFile::writeRecord(hdr, "qq", "on", szqq);
// 			}
		}
		else {

// 			string fn = ProtocolParser::formatfn(hdr, "qq_error");
// 			ret = ProtocolParser::writeBlocks(list, fn);
 			break;
		}
	}
	
	return 0;
}


/*
POST /qbrowser HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0) QQBrowser/9.0
Host: update.browser.qq.com
Content-Length: 345
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: uin_cookie=2210853762; euin_cookie=53DFE9A7024225C8649F40745723E578AC136F6862ECF843

{
"COS": "10.0.17763",
"CSoftID": 22,
"CVer": "1.6.6699.999",
"Cmd": 1,
"ExeVer": "1.0.1118.400",
"GUID": "9308ec3d7b7602d10f39e90f88399236",
"InstallTimeStamp": 1557478990,
"QID": 16785570,
"QQVer": "9.1.3.25332",
"SupplyID": 0,
"TriggerMode": 1,
"UIN": 0,
"bPatch": 0,
"osDigit": 64
}
HTTP/1.1 200
Date: Sun, 11 Aug 2019 03:14:20 GMT
Content-Length: 450
Connection: keep-alive

{ "CSoftID": 22, "CommandLine": "", "Desp": "\u0031\u002e\u0030\u002e\u0031\u0031\u0036\u0030\u002e\u0034\u0030", "DownloadUrl": "http://dl_dir.qq.com/invc/tt/minibrowser11.zip", "ErrCode": 0, "File": "minibrowser11.zip", "Flags": 1, "Hash": "b1309eb4312bd83d154a4b2b1b66547b", "InstallType": 0, "NewVer": "1.0.1160.400", "PatchFile": "QBDeltaUpdate.exe", "PatchHash": "b1309eb4312bd83d154a4b2b1b66547b", "Sign": "", "Size": 36003449, "VerType": "" }
*/

Android版qq解密代码:

c 复制代码
#include "mobileQQ.h"
#include "winsock2.h"
#include "qqcrypt.h"
#include "../public.h"
#include "../ProtocolParser.h"
#include "../ResultFile.h"
#include "../fileOper.h"
#include "../SearchData.h"


int parseHeartbeat(const char * data, int len) {
	const char * pos = SearchData::getstring("Heartbeat.Alive", lstrlenA("Heartbeat.Alive"), data, len);
	if (pos)
	{
		pos = pos - lstrlenA("Heartbeat.Alive") - 2;
		int len = ntohl(*(short*)pos);
		pos += len;

		len = ntohs(*(short*)pos);
		pos += len;

		len = ntohs(*(short*)pos);
		string imei = string(pos + 2, len - 2);
		pos += len;

		len = ntohs(*(short*)pos);
		pos += len;

		len = ntohs(*(short*)(pos -2));
		if (*pos == '|')
		{
			string imsi = string(pos, len - 2);
			imsi = imsi.substr(1);
			int dot = imsi.find("|");
			if (dot > 0)
			{
				imsi = imsi.substr(0, dot);
			}
		}		
	}

	return 0;
}

int MobileQQ::parsePacket(const char * data, int &len,int dport,int sport,DATALISTHEADER hdr) {

	const char * qqdata = data;

	LPMOBILEQQ_PACK_HDR qqhdr = (LPMOBILEQQ_PACK_HDR)qqdata;
	int offset = ntohl(qqhdr->offset);
	if (offset >= 0x80 || offset < 0)
	{
		offset = 4;
	}

	qqdata = qqdata + sizeof(MOBILEQQ_PACK_HDR) + offset;

	string qqno = "";
	char qqnolen = *qqdata - sizeof(int);
	if (qqnolen >= 5 && qqnolen <= 10)
	{
		qqdata++;
		qqno = string(qqdata, qqnolen);
	}
	else {
		printf("error qq no len\r\n");
		return -1;
	}

	qqdata += qqnolen;

	if (qqhdr->cryption == 2)
	{
		ResultFile::writeRecord(hdr, "mqq", "on", qqno);

		unsigned char key[16] = { 0 };

		int cryptlen = len - (qqdata - data);
		unsigned char *decodebuf = new unsigned char[cryptlen + 4096];
		int decodelen = cryptlen + 4096;
		int ret = qq_decrypt((unsigned char*)qqdata, cryptlen, key, decodebuf, &decodelen);
		if (/*ret && */decodelen > 0)
		{
			*(decodebuf + decodelen) = 0;
			printf("succeed decrypted size:%u,encrypted size:%u\r\n", decodelen, cryptlen);
			Public::WriteDataFile("mobileqq.dat", (const char*)decodebuf, decodelen);

			//ResultFile::writeRecord(hdr, "mqq", "on", qqno);
		}
		else {
			printf("error:decrypted size:%u,encrypted size:%u\r\n", decodelen, cryptlen);
			//printf("decrypt mobile qq fix crypt packet error\r\n");
		}

		delete decodebuf;
	}
	else if(qqhdr->cryption == 0){
		printf("no cryption mobile qq packet\r\n");
	}
	else if (qqhdr->cryption == 1)
	{

	}
	else {
		printf("error qq packet cryption\r\n");
		return -1;
	}

	return 0;
}


int MobileQQ::isMobileQQPack(DATALISTHEADER hdr) {
	int dport = hdr.sock.dstport;
	char * data = hdr.datalist->data;
	int len = hdr.sizelist->size;

	if (hdr.sock.protocol == 6 &&(dport == 8080 || dport == 443 || dport == 80 || dport == 14000))
	{
		int packlen = ntohl(*(int*)data);
		if (len == packlen )
		{
			char crypt = *(data + 8);
			if (crypt == 1 || crypt == 2 || crypt == 0)
			{
				int ver = *(int*)(data + sizeof(int));
				//3 = 2010 11 = 2016
				if (ver == 0x0a000000 || ver == 0x0b000000 || ver == 0x09000000)
				{
					return TRUE;
				}
			}
		}
	}

	return FALSE;
}

tea_crypt算法解密源码:

cpp 复制代码
/**
* The QQ2003C protocol plugin
*
* for gaim
*
* Copyright (C) 2004 Puzzlebird
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
* OICQ encryption algorithm
* Convert from ASM code provided by PerlOICQ
*
* Puzzlebird, Nov-Dec 2002
*/

/*****************************************************************************/
/*Notes: (OICQ uses 0x10 iterations, and modified something...)

IN : 64  bits of data in v[0] - v[1].
OUT: 64  bits of data in w[0] - w[1].
KEY: 128 bits of key  in k[0] - k[3].

delta is chosen to be the real part of
the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32.

0x61C88647 is what we can track on the ASM codes.!!
*/

//#ifndef _WIN32
//#include <arpa/inet.h>
//#else
//#include "win32dep.h"
//#endif
#ifndef _QQ_QQ_CRYPT_C_
#define _QQ_QQ_CRYPT_C_

#include <string.h>
#include "qqcrypt.h"
#include <winsock2.h>
#include <stdlib.h>

void qq_encipher(
	unsigned long *const        v,
	const unsigned long *const  k,
	unsigned long *const        w);

void qq_decipher(
	unsigned long *const        v,
	const unsigned long *const  k,
	unsigned long *const        w);

void qq_encrypt(
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_prt);

int qq_decrypt(
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_ptr);

/*****************************************************************************/
void qq_encipher(
	unsigned long *const        v,
	const unsigned long *const  k,
	unsigned long *const        w)
{
	register unsigned long
		y = ntohl(v[0]),
		z = ntohl(v[1]),
		a = ntohl(k[0]),
		b = ntohl(k[1]),
		c = ntohl(k[2]),
		d = ntohl(k[3]),
		n = 0x10,
		sum = 0,
		delta = 0x9E3779B9; /*  0x9E3779B9 - 0x100000000 = -0x61C88647 */

	while (n-- > 0) {
		sum += delta;
		y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
		z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
	}

	w[0] = htonl(y); w[1] = htonl(z);
}

/*****************************************************************************/
void qq_decipher(
	unsigned long *const        v,
	const unsigned long *const  k,
	unsigned long *const        w)
{
	register unsigned long
		y = ntohl(v[0]),
		z = ntohl(v[1]),
		a = ntohl(k[0]),
		b = ntohl(k[1]),
		c = ntohl(k[2]),
		d = ntohl(k[3]),
		n = 0x10,
		sum = 0xE3779B90,
		/* why this ? must be related with n value*/
		delta = 0x9E3779B9;

	/* sum = delta<<5, in general sum = delta * n */
	while (n-- > 0) {
		z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
		y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
		sum -= delta;
	}

	w[0] = htonl(y); w[1] = htonl(z);
}

/********************************************************************
* encrypt part
*******************************************************************/

void qq_encrypt(
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_prt)
{
	unsigned char
		plain[8],         /* plain text buffer*/
		plain_pre_8[8],   /* plain text buffer, previous 8 bytes*/
		*crypted,        /* crypted text*/
		*crypted_pre_8,  /* crypted test, previous 8 bytes*/
		*inp;            /* current position in instr*/
	int
		pos_in_byte = 1,  /* loop in the byte */
		is_header = 1,      /* header is one byte*/
		count = 0,          /* number of bytes being crypted*/
		padding = 0;      /* number of padding stuff*/

						  //  int rand(void);
						  //  void encrypt_every_8_byte (void);    
						  //  int rand(void) {    /* it can be the real random seed function*/
						  //    return 0xdead; }  /* override with number, convenient for debug*/

						  /*** we encrypt every eight byte ***/
						  //  void encrypt_every_8_byte (void) {
						  //    for(pos_in_byte=0; pos_in_byte<8; pos_in_byte++) {
						  //      if(is_header) { plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; }
						  //      else { plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; }
						  //    } /* prepare plain text*/
						  //    qq_encipher( (unsigned long *) plain,
						  //       		       (unsigned long *) key, 
						  //         		     (unsigned long *) crypted);   /* encrypt it*/
						  //    
						  //    for(pos_in_byte=0; pos_in_byte<8; pos_in_byte++) {
						  //      crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte]; 
						  //    } 
						  //    memcpy(plain_pre_8, plain, 8);     /* prepare next*/
						  //    
						  //    crypted_pre_8   =   crypted;       /* store position of previous 8 byte*/
						  //    crypted         +=  8;             /* prepare next output*/
						  //    count           +=  8;             /* outstrlen increase by 8*/
						  //    pos_in_byte     =   0;             /* back to start*/
						  //    is_header       =   0;             /* and exit header*/
						  //  }/* encrypt_every_8_byte*/

	pos_in_byte = (instrlen + 0x0a) % 8; /* header padding decided by instrlen*/
	if (pos_in_byte) {
		pos_in_byte = 8 - pos_in_byte;
	}
	plain[0] = (rand() & 0xf8) | pos_in_byte;

	memset(plain + 1, rand() & 0xff, pos_in_byte++);
	memset(plain_pre_8, 0x00, sizeof(plain_pre_8));

	crypted = crypted_pre_8 = outstr;

	padding = 1; /* pad some stuff in header*/
	while (padding <= 2) { /* at most two byte */
		if (pos_in_byte < 8) { plain[pos_in_byte++] = rand() & 0xff; padding++; }
		if (pos_in_byte == 8) {
			//encrypt_every_8_byte(); } 
			//void encrypt_every_8_byte (void) 
			{
				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					if (is_header) { plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; }
					else { plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; }
				} /* prepare plain text*/
				qq_encipher((unsigned long *)plain,
					(unsigned long *)key,
					(unsigned long *)crypted);   /* encrypt it*/

				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte];
				}
				memcpy(plain_pre_8, plain, 8);     /* prepare next*/

				crypted_pre_8 = crypted;       /* store position of previous 8 byte*/
				crypted += 8;             /* prepare next output*/
				count += 8;             /* outstrlen increase by 8*/
				pos_in_byte = 0;             /* back to start*/
				is_header = 0;             /* and exit header*/
			}/* encrypt_every_8_byte*/
		}
	}

	inp = instr;
	while (instrlen > 0) {
		if (pos_in_byte < 8) { plain[pos_in_byte++] = *(inp++); instrlen--; }
		if (pos_in_byte == 8) {
			//encrypt_every_8_byte(); }
			//void encrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					if (is_header) { plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; }
					else { plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; }
				} /* prepare plain text*/
				qq_encipher((unsigned long *)plain,
					(unsigned long *)key,
					(unsigned long *)crypted);   /* encrypt it*/

				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte];
				}
				memcpy(plain_pre_8, plain, 8);     /* prepare next*/

				crypted_pre_8 = crypted;       /* store position of previous 8 byte*/
				crypted += 8;             /* prepare next output*/
				count += 8;             /* outstrlen increase by 8*/
				pos_in_byte = 0;             /* back to start*/
				is_header = 0;             /* and exit header*/
			}/* encrypt_every_8_byte*/
		}
	}

	padding = 1; /* pad some stuff in tailer*/
	while (padding <= 7) { /* at most sever byte*/
		if (pos_in_byte < 8) { plain[pos_in_byte++] = 0x00; padding++; }
		if (pos_in_byte == 8) {
			// encrypt_every_8_byte(); 
			//void encrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					if (is_header) { plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; }
					else { plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; }
				} /* prepare plain text*/
				qq_encipher((unsigned long *)plain,
					(unsigned long *)key,
					(unsigned long *)crypted);   /* encrypt it*/

				for (pos_in_byte = 0; pos_in_byte<8; pos_in_byte++) {
					crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte];
				}
				memcpy(plain_pre_8, plain, 8);     /* prepare next*/

				crypted_pre_8 = crypted;       /* store position of previous 8 byte*/
				crypted += 8;             /* prepare next output*/
				count += 8;             /* outstrlen increase by 8*/
				pos_in_byte = 0;             /* back to start*/
				is_header = 0;             /* and exit header*/
			}/* encrypt_every_8_byte*/
		}
	}

	*outstrlen_prt = count;
}/* qq_encrypt*/


 /********************************************************************
 * [decrypt part]
 * return 0 if failed, otherwise return 1
 ********************************************************************/

int qq_decrypt(
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_ptr)
{
	unsigned char
		decrypted[8], m[8],
		*crypt_buff,
		*crypt_buff_pre_8,
		*outp;
	int
		count,
		context_start,
		pos_in_byte,
		padding;
	//  int decrypt_every_8_byte (void);
	//  int decrypt_every_8_byte (void) {
	//    for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte ++ ) {
	//        if (context_start + pos_in_byte >= instrlen) return 1;
	//        decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
	//    }
	//    qq_decipher( (unsigned long *) decrypted, 
	//       	  	     (unsigned long *) key, 
	//        	  	   (unsigned long *) decrypted);
	//    
	//    context_start +=  8;
	//    crypt_buff    +=  8;
	//    pos_in_byte   =   0;
	//    return 1;
	//  }/* decrypt_every_8_byte*/

	/* at least 16 bytes and %8 == 0*/
	if ((instrlen % 8) || (instrlen < 16)) return 0;
	/* get information from header*/
	qq_decipher((unsigned long *)instr,
		(unsigned long *)key,
		(unsigned long *)decrypted);
	pos_in_byte = decrypted[0] & 0x7;
	count = instrlen - pos_in_byte - 10; /* this is the plaintext length*/
										 /* return if outstr buffer is not large enought or error plaintext length*/
	if (*outstrlen_ptr < count || count < 0) return 0;

	memset(m, 0, 8);
	crypt_buff_pre_8 = m;
	*outstrlen_ptr = count;   /* everything is ok! set return string length*/

	crypt_buff = instr + 8;   /* address of real data start */
	context_start = 8;        /* context is at the second 8 byte*/
	pos_in_byte++;           /* start of paddng stuffv*/

	padding = 1;              /* at least one in header*/
	while (padding <= 2) {    /* there are 2 byte padding stuff in header*/
		if (pos_in_byte < 8) {  /* bypass the padding stuff, none sense data*/
			pos_in_byte++; padding++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = instr;
			//      if (!decrypt_every_8_byte())
			//		  return 0; 
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
						return 0;
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				qq_decipher((unsigned long *)decrypted,
					(unsigned long *)key,
					(unsigned long *)decrypted);

				context_start += 8;
				crypt_buff += 8;
				pos_in_byte = 0;
				//		  return 0;
			}/* decrypt_every_8_byte*/
		}
	}/* while*/

	outp = outstr;
	while (count != 0) {
		if (pos_in_byte < 8) {
			*outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte];
			outp++;
			count--;
			pos_in_byte++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = crypt_buff - 8;
			//      if (! decrypt_every_8_byte()) return 0;
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
						return 0;
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				qq_decipher((unsigned long *)decrypted,
					(unsigned long *)key,
					(unsigned long *)decrypted);

				context_start += 8;
				crypt_buff += 8;
				pos_in_byte = 0;
				//		  return 0;
			}/* decrypt_every_8_byte*/

		}
	}/* while*/

	for (padding = 1; padding < 8; padding++) {
		if (pos_in_byte < 8) {
			if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]) return 0;
			pos_in_byte++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = crypt_buff;
			//      if (! decrypt_every_8_byte()) return 0;
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				int haveData = 1;
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
					{
						haveData = 0;
						break;
					}
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				if (haveData == 1)
				{
					qq_decipher((unsigned long *)decrypted,
						(unsigned long *)key,
						(unsigned long *)decrypted);

					context_start += 8;
					crypt_buff += 8;
					pos_in_byte = 0;
				}
				//		  return 0;
			}/* decrypt_every_8_byte*/
		}
	}/* for*/
	return 1;
}/* qq_decrypt*/

 /*****************************************************************************/
 /* This is the Public Function */
 /* return 1 is succeed, otherwise return 0*/
int qq_crypt(
	unsigned char   flag,
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_ptr)
{
	if (flag == DECRYPT)
		return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr);
	else if (flag == ENCRYPT)
		qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr);

	return 1; /* flag must be DECRYPT or ENCRYPT*/
}/* qq_crypt*/
 /*****************************************************************************/
 /* END OF FILE*/











int qq_decrypt2(
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_ptr)
{
	unsigned char
		decrypted[8], m[8],
		*crypt_buff,
		*crypt_buff_pre_8,
		*outp;
	int
		count,
		context_start,
		pos_in_byte,
		padding;
	//  int decrypt_every_8_byte (void);
	//  int decrypt_every_8_byte (void) {
	//    for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte ++ ) {
	//        if (context_start + pos_in_byte >= instrlen) return 1;
	//        decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
	//    }
	//    qq_decipher( (unsigned long *) decrypted, 
	//       	  	     (unsigned long *) key, 
	//        	  	   (unsigned long *) decrypted);
	//    
	//    context_start +=  8;
	//    crypt_buff    +=  8;
	//    pos_in_byte   =   0;
	//    return 1;
	//  }/* decrypt_every_8_byte*/

	/* at least 16 bytes and %8 == 0*/
	if ((instrlen % 8) || (instrlen < 16)) return 0;
	/* get information from header*/
	qq_decipher((unsigned long *)instr,
		(unsigned long *)key,
		(unsigned long *)decrypted);
	pos_in_byte = decrypted[0] & 0x7;
	count = instrlen - pos_in_byte - 10; /* this is the plaintext length*/
										 /* return if outstr buffer is not large enought or error plaintext length*/
	if (*outstrlen_ptr < count || count < 0) return 0;

	//   if(count!=285 && count!=143)
	// 	  return 0;




	memset(m, 0, 8);
	crypt_buff_pre_8 = m;
	*outstrlen_ptr = count;   /* everything is ok! set return string length*/

	crypt_buff = instr + 8;   /* address of real data start */
	context_start = 8;        /* context is at the second 8 byte*/
	pos_in_byte++;           /* start of paddng stuffv*/

	padding = 1;              /* at least one in header*/
	while (padding <= 2) {    /* there are 2 byte padding stuff in header*/
		if (pos_in_byte < 8) {  /* bypass the padding stuff, none sense data*/
			pos_in_byte++; padding++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = instr;
			//      if (!decrypt_every_8_byte())
			//		  return 0; 
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
						return 0;
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				qq_decipher((unsigned long *)decrypted,
					(unsigned long *)key,
					(unsigned long *)decrypted);

				context_start += 8;
				crypt_buff += 8;
				pos_in_byte = 0;
				//		  return 0;
			}/* decrypt_every_8_byte*/
		}
	}/* while*/

	bool bcheck = false;
	outp = outstr;
	while (count != 0) {

		if ((outp - outstr)>4 && false == bcheck)
		{
			int aat = outstr[0] * 256 + outstr[1];
			if (*outstrlen_ptr - aat != 4)
				return 0;

			if (outstr[2] == 0 && outstr[3] == 0)
			{
				bcheck = true;
			}
			else if (outstr[2] == 1 &&
				(outstr[3] >= '0' && outstr[3] <= '9') ||
				(outstr[3] >= 'a' && outstr[3] <= 'z') ||
				(outstr[3] >= 'A' && outstr[3] <= 'Z')
				)
			{
				bcheck = true;
			}
			else
				return 0;
			// 		  if(memcmp(outstr+2,"\x00\x00",2)==0)
			// 		  {
			// 			 // return 1;
			// 		  }
			// 		  else
			// 		  {
			// 			  return 0;
			// 		  }
		}




		if (pos_in_byte < 8) {
			*outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte];
			outp++;
			count--;
			pos_in_byte++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = crypt_buff - 8;
			//      if (! decrypt_every_8_byte()) return 0;
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
						return 0;
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				qq_decipher((unsigned long *)decrypted,
					(unsigned long *)key,
					(unsigned long *)decrypted);

				context_start += 8;
				crypt_buff += 8;
				pos_in_byte = 0;
				//		  return 0;
			}/* decrypt_every_8_byte*/

		}
	}/* while*/

	for (padding = 1; padding < 8; padding++) {
		if (pos_in_byte < 8) {
			if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]) return 0;
			pos_in_byte++;
		}
		if (pos_in_byte == 8) {
			crypt_buff_pre_8 = crypt_buff;
			//      if (! decrypt_every_8_byte()) return 0;
			//	  int decrypt_every_8_byte (void);
			//	  int decrypt_every_8_byte (void)
			{
				int haveData = 1;
				for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
					if (context_start + pos_in_byte >= instrlen)
					{
						haveData = 0;
						break;
					}
					decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
				}
				if (haveData == 1)
				{
					qq_decipher((unsigned long *)decrypted,
						(unsigned long *)key,
						(unsigned long *)decrypted);

					context_start += 8;
					crypt_buff += 8;
					pos_in_byte = 0;
				}
				//		  return 0;
			}/* decrypt_every_8_byte*/
		}
	}/* for*/
	return 1;
}/* qq_decrypt*/



int qq_crypt2(
	unsigned char   flag,
	unsigned char*  instr,
	int             instrlen,
	unsigned char*  key,
	unsigned char*  outstr,
	int*            outstrlen_ptr
)
{
	if (flag == DECRYPT)
		return qq_decrypt2(instr, instrlen, key, outstr, outstrlen_ptr);
	else if (flag == ENCRYPT)
		qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr);

	return 1; /* flag must be DECRYPT or ENCRYPT*/
}/* qq_crypt*/


#endif
相关推荐
用户962377954482 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954482 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star2 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954482 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher4 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行7 天前
网络安全总结
安全·web安全
red1giant_star7 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全
ZeroNews内网穿透7 天前
谷歌封杀OpenClaw背后:本地部署或是出路
运维·服务器·数据库·安全