QQ数据包解密

Windows版qq数据包格式:
在这里插入图片描述

android版qq数据包格式:

在这里插入图片描述

密钥:16个0

算法:tea_crypt算法

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

#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解密代码:


#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算法解密源码:

/**
* 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/337912.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【php】php去除excel导入时的空格

背景 PHPExcel_1.8.0导入excel&#xff0c;遇到trim无法处理的空格。 解决方案 $excelVal preg_replace(“/(\s| | |\xc2\xa0)/”, ‘’, $excelVal); 完整代码 thinkphp5代码 function readExcel($file) {require_once EXTEND_PATH . PHPExcel_1.8.0/Classes/PHPExcel.p…

汽车制动器行业调查:市场将继续呈现稳中向好发展态势

汽车制动器是汽车的制动装置&#xff0c;汽车所用的制动器几乎都是摩擦式的&#xff0c;可分为鼓式和盘式两大类。鼓式制动器摩擦副中的旋转元件为制动鼓&#xff0c;其工作表面为圆柱面;盘式制动器的旋转元件则为旋转的制动盘&#xff0c;以端面为工作表面。 目前市场上主流的…

WebSocket-黑马好客租房

文章目录 网站中的消息功能如何实现&#xff1f;什么是WebSocket&#xff1f;http与websocket的区别httpwebsocket 浏览器支持情况快速入门创建itcast-websocket工程websocket的相关注解说明实现websocket服务测试编写js客户端 SpringBoot整合WebSocket导入依赖编写WebSocketHa…

全网最高质量文章:重新学习Java中的HashMap!!

前言 本文参考了美团技术团队的科普文章Java 8系列之重新认识HashMap - 知乎 (zhihu.com) 这篇文章的质量极其高&#xff0c;高到很有可能是全网介绍HashMap这个知识点最优秀的文章&#xff0c;没有之一&#xff01;&#xff01;&#xff01;因此&#xff0c;我决定在我自己的…

智能安全帽定制_基于联发科MT6762平台的智能安全帽方案

智能安全帽是一种具备多项功能的高科技产品&#xff0c;其功能集成了视频通话监控、高清图像采集、无线数据传输、语音广播对讲、定位轨迹回放、静默报警、危险救援报警、脱帽报警、碰撞报警、近电报警以及智能调度系统等&#xff0c;同时还支持多功能模块的自由添加&#xff0…

设计模式-责任链

之前写代码的时候看到过有审批场景使用了责任链&#xff0c;当时大概看了一下代码实现&#xff0c;今天终于有时间抽出来梳理一下&#xff0c;下面是本文的大纲&#xff1a; 使用场景 审批场景的普遍应用 实际案例&#xff1a;HttpClient中的责任链模式 责任链模式在事件处理、…

RocketMQ学习总结

一、架构 1、NameServer&#xff1a;注册中心。Broker信息注册到NameServer&#xff1b;producer/consumer根据某个topic通过NameServer获取对应broker的路由信息 &#xff1b; 2、Broker&#xff1a;负责存储、拉取、转发消息&#xff1b; 3、Producer&#xff1a;消息生产者…

creature_summon_groups

字段介绍 这个表保存了关于临时召唤生物的数据 creature_summon_groups summonerId&#xff08;召唤者ID&#xff09; summonerType 0 时&#xff0c;此处为 creature 的 entrysummonerType 1 时&#xff0c;此处为 gameobject 的 entrysummonerType 2 时&#xff0c;此处…

从设备维修到机器视觉:我的职业发展之路

大家好&#xff01;我是学员向工&#xff0c;今天很高兴有机会与大家分享我的职业经历。十年前&#xff0c;18岁中专毕业的那年&#xff0c;我踏入社会&#xff0c;至今已经过去了十年。一开始&#xff0c;我主要从事设备的维修、装配、钳工和电工等多岗位工作。 然而&#xff…

大数据关联规则挖掘:Apriori算法的深度探讨

文章目录 大数据关联规则挖掘&#xff1a;Apriori算法的深度探讨一、简介什么是关联规则挖掘&#xff1f;什么是频繁项集&#xff1f;什么是支持度与置信度&#xff1f;Apriori算法的重要性应用场景 二、理论基础项和项集支持度&#xff08;Support&#xff09;置信度&#xff…

༺༽༾ཊ—Unity之-02-简单工厂模式—ཏ༿༼༻

首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 建基础通用包 创建一个Plane 重置后 缩放100倍 加一个颜色 任务&#xff1a;使用【简单工厂模式】生成四种不同怪物 【按不同路径移动】 首先资源商店下载四个怪物模型 接下来我们选取四个怪物作为预制体并分别起名…

【Java并发】聊聊concurrentHashMap扩容核心流程

扩容 什么时候扩容 链表转红黑树。需要判断数组长度&#xff0c;触发扩容调用putAll() , 触发tryPresize() 方法数据量达到阈值 tryPresize-初始化数组 // 扩容前操作&#xff0c;putAll or 链表转红黑树 // size是原数组长度 * 2private final void tryPresize(int size) {…

如何在Servlet中获取请求参数的值

看看这个大佬做的动图吧&#xff01; 在Servlet中&#xff0c;你可以使用HttpServletRequest对象来获取请求参数的值。HttpServletRequest对象提供了一些方法&#xff0c;允许你访问从客户端发送的请求信息。以下是一些获取请求参数的常用方法&#xff1a; getParameter(String…

《SPSS统计学基础与实证研究应用精解》视频讲解:变量和样本观测值基本操作

《SPSS统计学基础与实证研究应用精解》4.1 视频讲解 视频为《SPSS统计学基础与实证研究应用精解》张甜 杨维忠著 清华大学出版社 一书的随书赠送视频讲解4.1节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。本书旨在手把手教会使…

k8s-ingress一

Comfigmap&#xff1a;存储数据 Date&#xff1a; Key&#xff1a;value 挂载的方式&#xff0c;把配置信息传给容器 生产当中的yml文件很长&#xff1a; 有deployment 容器的探针 资源限制 Configmap 存储卷 Service Ingress K8s的对外服务&#xff0c;ingress Se…

2023年总结我所经历的技术大变革

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不仅…

只需要1天+10元,上线我的第①个工具站 - 50个工具站打卡计划

2023年用了一整年的时间探索技术变现的方式&#xff0c;学习到了特别多的理论知识。2024年到了爆发的时间了。今年计划上线50款出海工具站计划&#xff0c;我会详细记录开发工具站的全部流程。 工具站的核心任务是找到关键字&#xff0c;找对关键词并成功注册到适当的域名&…

logstack 日志技术栈-04-opensource 开源工具 SigNoz+Graylog

3. SigNoz SigNoz 是一个日志收集和分析工具&#xff0c;可以收集和管理来自各种来源的日志、指标、跟踪和异常。 它为使用 OpenTelemetry 检测应用程序提供本机支持&#xff0c;以防止供应商锁定&#xff0c;将收集到的数据存储在 ClickHouse 中&#xff0c;然后在用户友好的…

༺༽༾ཊ—Unity之-01-单例模式—ཏ༿༼༻

在游戏开发过程中&#xff0c;我们会创建各种各样的类&#xff0c;再用new生成实例&#xff0c;有些时候我们需要这个类在整个游戏中是唯一出现的&#xff0c;比如一些管理器比如声音管理器等&#xff0c;没必要创建很多实例&#xff0c;就算有很多模块需要各种声音功能&#x…

NSIS来打包windows安装程序,开源免费简单小巧,支持中文

NSIS (Nullsoft脚本安装系统)是一个专业的开源系统&#xff0c;用于创建 Windows 安装程序。它被设计成尽可能小和灵活&#xff0c;因此非常适合互联网分发&#xff0c;并且原生支持中文&#xff0c;不像inno setup还需要你单独安装一个中文语言包。 NSIS官网&#xff1a;NSIS…
最新文章