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 );
}