www.pudn.com > QQ_Sniffer.rar > myfollow.cpp


/* 
 *  doublelee@etang.com 
 *  date: 2004-11-30 
 *   
 *  target: to get what we need in the data after decryting the packet body. 
 */ 
#include "stdafx.h" 
#include "myfollow.h"
#include "mycrypt.h"
#include "mystate.h"
 
/* 
hh_udp_header * format_hh_udp_header(hh_udp_header * h)
{
    h->sender_ver = swapu16(h->sender_ver);
    h->hh_cmd     = swapu16(h->hh_cmd);
    h->sq_no      = swapu16(h->sq_no);
    return h;
}
*/
CMyFollow::CMyFollow() 
{ 
	hhstate = NULL; 
} 
CMyFollow::~CMyFollow()
{
}

u_int CMyFollow::hh_parse_common(u_char * data, u_int len, void* reserved) 
{ 
    if(len%4) 
        return 0; 
    if(len%8)   //C2S, has hhnumber, len = 8*N+4 
		return decrypt_msg(data+4, len-4, (unsigned long *)hhstate->key1, hh_plain_text, (unsigned long *)(&hh_len_plain)); 
    else        //S2C 
        return decrypt_msg(data,   len,   (unsigned long *)hhstate->key1, hh_plain_text, (unsigned long *)(&hh_len_plain)); 
 
} 


unsigned short CMyFollow::hh_analysis(struct tuple4 addr,  u_int proto,  const hh_udp_header * pquh, const size_t datalen, FILE* pipe )
{
	//u_int direct;

	// outputBinary(pquh->data, datalen, stderr);
	tuple4 tpaddr = addr;
	if( !(datalen%4) && !(datalen%8))   //this is s2c, because c2s: has hh_number, len = 8*N+4 
	{
		tpaddr.saddr = addr.daddr;
		tpaddr.daddr = addr.saddr;
		tpaddr.source = addr.dest;
		tpaddr.dest = addr.source; 
	}

    switch ( pquh->hh_cmd )
    {
    case HH_CMD_PRE_LOGIN: 
		//        fprintf( stderr, "pre-login packet found! \n" ); 
        //here should process it,some data here in fact 
        return pquh->sq_no; 
		 
    case HH_CMD_LOGOUT: 
		//fprintf( stderr, "\na log out packet found!"); 
		g_objState.FindState(tpaddr,  proto);
        { 
            if(hhnumber == swapu32( *(unsigned int*)pquh->data ) ) 
            { 
                fprintf( stderr, "\nhh %d logged out!\n", hhnumber); 
                online = 0; 
            } 
			else 
            { 
				//                fprintf( stderr, "\nhh %d logging out!, but hhnumber is %d\n", 
				//					swapu32(*(unsigned int*)pquh->data), hhnumber); 
//                online = 0; 
            } 
        } 
        return pquh->sq_no; 
 
    case HH_CMD_LOGIN: 
		{
			CMyCrack objHHCrack;
			objHHCrack.setaddr(tpaddr,proto);
			if(objHHCrack.crack_hh_login( pquh->data, datalen, NULL) == 1)
			{
				fprintf( stderr, "found a login hh packet, now cracking...\n");
				//outputBinary( hh_plain_text, hh_len_plain, stdout); 
				return 1;
			}
			else 
				return 0; 
		} 
 
	case HH_CMD_SEND_IM: 
		hhstate = g_objState.FindState(tpaddr,  proto);
		if (hhstate && hhstate->state == 2)
		{ 
			//fprintf( pipe, "sending message,now trying to decrypt……"); 
            if(hh_parse_common((unsigned char*) pquh->data, datalen, NULL)) 
			{ 
				//fprintf( pipe, "success!\n"); 
				//outputBinary( hh_plain_text, hh_len_plain, pipe); 
				outputtext( hh_plain_text, hh_len_plain, C2S, pipe); 
				return 1; 
				//所有workkey加密的数据至此已为明文。 
            } 
            else 
			{ 
				//fprintf( pipe, "failed :(\n"); 
				return 0; 
			} 
		}
        else 
            return 0; 
	case HH_CMD_RECV_IM: 
		hhstate = g_objState.FindState(tpaddr,  proto);
		if (hhstate && hhstate->state == 2) 
		{ 
			//fprintf( pipe, "receiving message, now trying to decrypt……"); 
            if(hh_parse_common((u_char*)pquh->data, datalen, NULL)) 
			{ 
				//fprintf( pipe, "success!\n"); 
				outputtext( hh_plain_text, hh_len_plain, S2C, pipe); 
				return 1; 
				//所有workkey加密的数据至此已为明文。 
            } 
            else 
			{ 
				//fprintf( pipe, "failed :(\n"); 
				return 0; 
			} 
		} 
        else 
            return 0; 
 
 
 
    default:
/* 
        if(online) 
        { 
 
            fprintf( pipe, "hh_cmd is 0x%04x, len 0x%04x, now trying to decryptit...", 
                         pquh->hh_cmd, datalen); 
            if(hh_parse_common( pquh->data, datalen, NULL)) 
            { 
                fprintf( pipe, "success!\n"); 
				//需要调试分析其他数据的话打开下面这句。 
				//outputBinary( hh_plain_text, hh_len_plain, pipe); 
				return 1; 
				//所有workkey加密的数据至此已为明文。 
            } 
            else 
			{ 
                fprintf( pipe, "failed!\n"); 
				return 0; 
			} 
 
        } 
        else 
// */ 
		return 0;
    }
            
}


unsigned short CMyFollow::parse_hh1(struct tuple4 addr,  u_int proto,  const u_char * byteArray, const size_t byteArrayLen, FILE* pipe )
{
    hh_udp_header * pquh;
    hh_tcp_header * pqth;
    u_int           datalen;
    u_char          buf_copy[MAX_P_LEN] = {0};

    memcpy(buf_copy, byteArray, byteArrayLen>MAX_P_LEN? MAX_P_LEN: byteArrayLen);
    //don't format or decrypt on buffer of byteArray, it may destroy the byteArray.
    
    switch(proto)
    {
    case 6:
        pqth    = (hh_tcp_header*)(buf_copy);
        datalen = byteArrayLen;
        if(datalen < MIN_P_LEN)
        {
            return 0; 
        }
        if ( datalen != swapu16(pqth->p_len) )
        {
    	    return 0;
        }
        datalen -= (LEN_TCP_HEADER + LEN_TAIL) ;
        pquh    = &(pqth->quh);
        break;
    case 17:
        pquh    = (hh_udp_header*)(buf_copy);
        datalen = byteArrayLen - (LEN_UDP_HEADER + LEN_TAIL);
        if(datalen < MIN_P_LEN)
        {
//          fprintf( stderr, "too short, rejected!\n");
            return 0; 
        }
        break;
    default:
        return 0;
    }
    
    
    if(pquh->begin_tag != HH_BEGIN_TAG || pquh->data[datalen] != HH_END_TAG)
    {
		//fprintf( stderr, "TAG check failed! -> %d and %d \n", pquh->begin_tag, pquh->data[datalen]);
    	return 0;
    }

	//outputBinary(pquh->data, datalen, stderr );
    format_hh_udp_header(pquh); //调用这个函数必须在局部的内存上
	//fprintf( stderr, "Found a valid hh packet, now analysing...\n"); 
	//fprintf( stderr, "packet sender version is 0x%04x and cmdcode is 0x%04x\n",
	//pquh->sender_ver, pquh->hh_cmd );
    
    return hh_analysis(addr, proto, pquh, datalen, pipe );
   
}