⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucparse.c

📁 UC用户名破解算法 输入用户名会被加密成包中的字符哦 很好哦
💻 C
字号:
/************************************************
 *  UC packet parser.
 *	Incompletely reversed by doublelee 
 *  data: 2003.7
 *  edited: 2005.7
 ************************************************/


#include "ucparse.h"

#define  PRINT_SECTION  \
	section_len = (u_short)*ptext;\
	ptext += 2;\
	sub_len -= 2;\
	if(ptext+section_len>text+textlen)\
		return 0;\
	for(i=0; i<section_len; i++)\
	{\
		fprintf(pipe, "%c", *ptext++);\
		sub_len--;\
	}
//  to print a section, length as header 2-byte indexed.

#define	PRINT_UCID \
	ucid = *(u_int*)ptext;\
	fprintf(pipe, "%d\n", ucid);\
	ptext += 8;\
//  to print a 8-byte ucid.

#define PRINT_UCNICK \
	section_len = *ptext++;\
	if(ptext+section_len>text+textlen)\
		return 0;\
	fprintf(pipe, "UC nick is:\t");\
	for(i=0; i<section_len; i++)\
	{\
		fprintf(pipe, "%c", *ptext++);\
	}\
	fprintf(pipe, "\n");\
//	to print a uc nickname, one byte indexed.

void outputBinary ( const u_char * byteArray, const size_t byteArrayLen, FILE* pipe)
{
    u_long offset;
    int    i, j, k;

    fprintf( pipe, "binary data [ %lu bytes ] ----> \n", ( long unsigned int )byteArrayLen );
    if ( byteArrayLen <= 0 )
    {
        return;
    }
    i      = 0;
    offset = 0;
    for ( k = byteArrayLen / 16; k > 0; k--, offset += 16 )
    {
        fprintf( pipe, "%08X ", ( unsigned int )offset );
        for ( j = 0; j < 16; j++, i++ )
        {
            if ( j == 8 )
            {
                fprintf( pipe, "-%02X", byteArray[i] );
            }
            else
            {
                fprintf( pipe, " %02X", byteArray[i] );
            }
        }
        fprintf( pipe, "    " );
        i -= 16;
        for ( j = 0; j < 16; j++, i++ )
        {
            /* if ( isprint( (int)byteArray[i] ) ) */
            if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 ) )
            {
                fprintf( pipe, "%c", byteArray[i] ); 
            }
            else
            {
                fprintf( pipe, "." ); 
            }
        }
        fprintf( pipe, "\n" );
    }  /* end of for */
    k = byteArrayLen - i;
    if ( k <= 0 )
    {
        return;
    }
    fprintf( pipe, "%08X ", ( unsigned int )offset );
    for ( j = 0 ; j < k; j++, i++ )
    {
        if ( j == 8 )
        {
            fprintf( pipe, "-%02X", byteArray[i] );
        }
        else
        {
            fprintf( pipe, " %02X", byteArray[i] );
        }
    }
    i -= k;
    for ( j = 16 - k; j > 0; j-- )
    {
        fprintf( pipe, "   " );
    }
    fprintf( pipe, "    " );
    for ( j = 0; j < k; j++, i++ )
    {
        if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 ) )
        {
            fprintf( pipe, "%c", byteArray[i] ); 
        }
        else
        {
            fprintf( pipe, "." ); 
        }
    }
    fprintf( pipe, "\n" );
    return;
}  /* end of outputBinary */

void printip(ip_info* pi, FILE* pipe)
{
//	struct in_addr si;
//	si.S_un.S_addr = pi->src_ip;
//	fprintf(pipe, "Source: %s", inet_ntoa(si));

	fprintf(pipe, "Source: %d.%d.%d.%d: %d\t Destination: %d.%d.%d.%d: %d\n\n",
		(pi->src_ip)&0xFF,         (pi->src_ip>>8)&0xff,
		(pi->src_ip>>16)&0xff,     (pi->src_ip>>24)&0xff,
		((pi->src_port>>8)&0xff) + ((pi->src_port<<8)&0xff00),
		(pi->dst_ip)&0xFF,         (pi->dst_ip>>8)&0xff,
		(pi->dst_ip>>16)&0xff,     (pi->dst_ip>>24)&0xff, 
		((pi->dst_port>>8)&0xff) + ((pi->dst_port<<8)&0xff00) );
	// a little ugly but maybe quicker than inet_ntoa();
}

int outputtext_tcp(u_char* text, u_short textlen, FILE* pipe)
{
	u_short data_len, sub_len, section_len, count;
	u_short room_id;
	u_int   i;
	u_char* ptext;

#ifdef _DEBUG
	outputBinary(text, textlen, pipe);
	return 1;
#endif //_DEBUG 

	ptext    = text;
	sub_len  = 0;
	data_len = (u_short)(*ptext);

	if( data_len+2 > textlen )
		return 0;

	ptext += 4;
	room_id = *(u_short*)(ptext);
//	fprintf(pipe, "\nRoom ID is %d\n", room_id);
	ptext += 4;

	data_len = *(u_short*)(ptext);
	if(ptext+data_len>text+textlen)
	{
		return 0;
	}

	ptext += 2;

	switch( *(u_short*)ptext )
	{
	case UC_WEB_CHAT:
		ptext += 0x0E;
		sub_len = *(u_short*)ptext;
		ptext += 2;

		PRINT_SECTION

		fprintf(pipe, " (Font:");
		section_len = *(u_short*)ptext;
		ptext += 2;
		sub_len -= 2;
		for(i=0; i<section_len; i++)
		{
			if( '|' == *ptext )
			{
				fprintf(pipe, ")\n");
				ptext++;
				sub_len--;
				continue;
			}
			fprintf(pipe, "%c", *ptext++);
			sub_len--;
		}

		for(i=0; i+0x11 < sub_len; i++)
			fprintf(pipe, "%c", *ptext++);

		fprintf(pipe, "\n%%1=%d, %%2=%d\n", 
			*(u_int*)ptext, *(u_int*)(ptext+8) );

		return 1;

	case UC_WEB_USERIN:
//		outputBinary(text, textlen, pipe);
		ptext += 6;
		fprintf(pipe, "用户(ucid=%d)(", *(u_int*)ptext);
		ptext += 8;
		PRINT_SECTION
		fprintf(pipe, ")来了\tuser status: ");
		for(i=0; i<8; i++)
		{
			fprintf(pipe, "%02x", *ptext++);
		}
		fprintf(pipe, "\n");
		return 1;

	case UC_WEB_USEROUT:
		ptext += 6;
		fprintf(pipe, "用户(ucid=%d)走了\n", *(u_int*)ptext);
		return 1;
	case UC_WEB_BROADCAST:
		ptext += 2;
		if( 0 == *(int*)ptext )
			fprintf(pipe, "★系统广播★\n");
		else
			fprintf(pipe, "★房间广播★(ucid=%d)发布\n", *(u_int*)ptext);
		ptext += 8;
		PRINT_SECTION		
		fprintf(pipe, "\n");
		return 1;
	case UC_WEB_ROOMINFO:
		ptext += 0x0B;
		PRINT_SECTION		

		fprintf(pipe, "\nIP Address:");
		PRINT_SECTION		
		fprintf(pipe, "\tPort:%d", *(u_short*)ptext);
		ptext += 2;

		fprintf(pipe, "\n★公告★本聊天室的主题是:");
		PRINT_SECTION		

		fprintf(pipe, "\n★公告★\n");
		PRINT_SECTION		
		fprintf(pipe, "\n");
		return 1;

	case UC_WEB_GETLIST:
		ptext += 6;
		count =  *(u_short*)ptext;
		ptext += 2;

		fprintf(pipe, "聊天室中的%d人名单:\n",count);
		for(; count--; )
		{
			fprintf(pipe, "ucid=%d", *(u_int*)ptext );
			ptext += 8;

			fprintf(pipe, "\tnick=");
			PRINT_SECTION		
			fprintf(pipe, "\tuser status: ");
			for(i=0; i<8; i++)
			{
				fprintf(pipe, "%02x", *ptext++);
			}
			fprintf(pipe, "\n");
		}
		return 1;

	case UC_WEB_CHAT2:
	case UC_WEB_UNK1:
	case UC_WEB_UNK2:
	case UC_WEB_UNK3:
	case UC_WEB_UNK4:
	case UC_WEB_UNK5:
	default:
		break;
	}

	return 0;
}

int outputtext_udp(u_char* text, u_short textlen, FILE* pipe)
{
	u_short data_len, sub_len, section_len, cmd, i;
 	u_int   ucid;
	u_char* ptext, direction;

#ifdef _DEBUG
	outputBinary(text, textlen, pipe);
	return 1;
#endif //_DEBUG

	ptext    = text;
	data_len = (u_short)(*ptext);

	if(data_len+2>textlen)
		return 0;

	ptext += 2;
	direction = *ptext++;

sub1:
	sub_len = (u_short)(*ptext);
	ptext += 2;

	switch( cmd = *(u_short*)ptext )
	{
	case UC_CMD_LOGIN_54:
	case UC_CMD_LOGIN_58:
	case UC_CMD_LOGIN_5C:
	case UC_CMD_LOGIN_5E:
	case UC_CMD_LOGIN_62:
	case UC_CMD_LOGIN_6B:
	case UC_CMD_LOGIN_6A:

		ptext += 2;
		fprintf(pipe, "Login Client version:\t");
		PRINT_SECTION
		fprintf(pipe, "\n");

		fprintf(pipe, "Login UC number:\t");
		PRINT_UCID

		if( UC_CMD_LOGIN_54 == cmd || UC_CMD_LOGIN_58 == cmd )
		{
			fprintf(pipe, "Login As:\t\t");
			PRINT_SECTION
			fprintf(pipe, "\n");
		}
		fprintf(pipe, "Login Password:\t\t");
		PRINT_SECTION
		fprintf(pipe, "\n");

		if( UC_CMD_LOGIN_54 == cmd )
		//	此时 *ptext == x (x=1代表通行证方式,x=2手机号,x=3邮件) 
			ptext += 2;
		if( UC_CMD_LOGIN_58 == cmd )
			ptext ++;
		ptext += 0x0E;
		fprintf(pipe, "Login IP is:\t\t");
		PRINT_SECTION
		fprintf(pipe, "\n");

		ptext += 20;
		fprintf(pipe, "User is:\t");
		PRINT_UCID
		PRINT_UCNICK

		return 1;

	case UC_CMD_CHG_STATUS:
	case UC_CMD_CHG_STATUS_68:

		ptext += 2;
		ucid   = *(u_int*)ptext;
		ptext += 0x08;

		if(UC_CMD_CHG_STATUS == cmd)
			ptext++;	//should be a byte of 0x01.
		ptext++;	//should be former status.

		switch(*ptext++)
		{
		case UC_STATUS_OFFLINE:
			//seems like some time counting data in this packet.
			fprintf(pipe, "ucid %d is logging out!\n", ucid);
			return 1;

		case UC_STATUS_HIDDEN:
			fprintf(pipe, "ucid %d is hidden.\n", ucid);
			return 1;

		case UC_STATUS_ONLINE:
			fprintf(pipe, "ucid %d is online!\t", ucid);
			PRINT_SECTION
			fprintf(pipe, "\n");
			return 1;
		
		case UC_STATUS_GOAWAY:
			fprintf(pipe, "ucid %d is away!\t", ucid);
			PRINT_SECTION
			fprintf(pipe, "\n");
			return 1;
		default:
			return 0;
		}

	case UC_CMD_RREQ_FRI:
	case UC_CMD_RREQ_FRI+1:
	case UC_CMD_FRI_LIST:
	case UC_CMD_FRI_LIST+1:
	case UC_CMD_SEARCH:
	case UC_CMD_SEARCH+1:
	case UC_CMD_FRI_STATUS:
	case UC_CMD_FRI_STATUS+1:
		break;

	case UC_CMD_TMP_STORE:
		// send to server to store temporarily.
	case UC_CMD_TMP_STORE+1:
		// get from server the stored info.
		ptext += 2;
		fprintf(pipe, "Receiver ucid:\t");
		PRINT_UCID
		goto sub1;

	case UC_CMD_BROADCAST:
		ptext += 3;
		fprintf(pipe, "Broadcast content:\n");
		PRINT_SECTION
		fprintf(pipe, "\n");
		return 1;

		break;

	case UC_CMD_REDIR:
		// redirected packet, need decipher again.
		ptext += 2;

/*		fprintf(pipe, "Receiver ucid:\t");
		PRINT_UCID
		fprintf(pipe, "Sender ucid:\t");
		PRINT_UCID
*/		//don't print redirected packets' header, because I don't know if the 
		//data is meaningful for us.
		ptext += 0x10;

		ptext += 5;
		section_len = (u_short)*ptext;
		if(section_len%8) return 0;
		ptext += 2;

		for(i=0; i<section_len/8; i++)
		{
			UC_decipher( (u_long*)(ptext+8*i), (u_long*)(ptext+4+8*i) );
		}
//		outputBinary(text, textlen, pipe);
		return outputtext_udp(ptext, section_len, pipe);

	case 0x00E7:
	case 0x00E8:	//older version?
	case 0x00EA:
	case 0x00EB:	// get friend info details.
		break;

	case 0x03E9: //4.01.920, 4.10.625
	case 0x0487: //2.40 ~ 4.00.200
		ptext += 2;

		fprintf(pipe, "Sender ucid:\t");
		PRINT_SECTION
		fprintf(pipe, "\n");
		fprintf(pipe, "Sender nick:\t");
		PRINT_SECTION
		fprintf(pipe, "\n");

//		fprintf(pipe, "Receiver:\t(see Destination IP and port)\n");
//		if you don't parse friend status packet and keep their status, you
//		won't know who is the Receiver. While the real Receiver, the one
//		listening on the correct ip and port knows that it is for him or her.

		ptext += 6;
		fprintf(pipe, "content:\t");
		PRINT_SECTION
		fprintf(pipe, "\n");
		// following are other information such as font. 

		return 1;

	case UC_CMD_ADD_FRI:
		// add friend request.
/*		ptext += 2;
		fprintf(pipe, "Sender ucid:\t");
		PRINT_UCID

		fprintf(pipe, "Sender nick:\t");
		PRINT_SECTION

		ptext += 6;
		fprintf(pipe, "info:\t\t");
		PRINT_SECTION
		return 1;
*/
		break;

	case UC_CMD_KEEP_ALIVE_C8:
	case UC_CMD_KEEP_ALIVE_C8+1:
	case UC_CMD_KEEP_ALIVE_CB:
	case UC_CMD_KEEP_ALIVE_CB+1:
		break;

	case 0x6365:	//ack of comman packet.
		// infact "echo" here(65 63 68 6F)
/*		fprintf(pipe, "echo: received!\n");
		ptext += 0x18;
		fprintf(pipe, "ucid is:\t");
		PRINT_UCID
		PRINT_UCNICK
		return 1;
*/
		break;

	default:
//		outputBinary(text, textlen, pipe);
//		fprintf(pipe, "unknown cmd code is %02X\n", *(u_short*)ptext);
		return 0;
	}
	return 0;
}

u_short parse_uc( const u_char * byteArray, const size_t byteArrayLen, FILE* pipe )
{
	u_short  i;
	u_char*  pdata;
	u_int    datalen;
	uc_header           *puh;
	uc_webchat_header   *puwch;
	ip_info				*pi;

	pi = (ip_info*)&byteArray[0x1A];

	if(byteArray[23] == 0x11) //UDP, should be port 3000~3003
	{
		pdata = (u_char*)(byteArray + LIBNET_ETH_H + LIBNET_IP_H + LIBNET_UDP_H);

		puh = (uc_header*)pdata;
		datalen = byteArrayLen - (LIBNET_ETH_H + LIBNET_IP_H + LIBNET_UDP_H);
		
		if (puh->begin_tag != UC_BEGIN_TAG)
			return 0;
		
		if(datalen - puh->uc_cipher_len	- UC_HEAD_LEN != 0 )
			return 0;
		
		if(puh->uc_unknown2 != UC_UNKNOWN2 )
			return 0;
		
		for(i=0; i < puh->uc_cipher_len/8; i++)
		{
			UC_decipher((u_long*)&puh->data[8*i],(u_long*)&puh->data[4+8*i]);
		}
		
		if(outputtext_udp(puh->data, puh->uc_cipher_len, pipe))
			printip(pi, pipe);
		return 1;
	}

	if(byteArray[23] == 0x06) //TCP, should be port 5000+
	{
		pdata = (u_char*)(byteArray + LIBNET_ETH_H + LIBNET_IP_H + LIBNET_TCP_H); 
		//maybe multi-message in one packet.
		datalen = byteArrayLen - (LIBNET_ETH_H + LIBNET_IP_H + LIBNET_TCP_H);

		do
		{
			puwch = (uc_webchat_header*)pdata;
			
			if (puwch->begin_tag != UC_BEGIN_TAG)
				return 0;
			if (puwch->begin_tag2 != UC_BEGIN_TAG2)
				return 0;
			if(datalen - puwch->uc_cipher_len - UC_HEAD_LEN < 0 )
				return 0;
			
			if (*((u_short*)(&puwch->data[puwch->uc_cipher_len])) != UC_END_TAG2)
				return 0;
			if ((u_char*)(puwch->data[puwch->uc_cipher_len+2]) != UC_END_TAG)
				return 0;
			if (*((u_short*)(&puwch->data[puwch->uc_cipher_len+3])) != puwch->uc_cipher_len)
				return 0;
			
			for(i=0; i < puwch->uc_cipher_len/8; i++)
			{
				UC_decipher((u_long*)&puwch->data[8*i],(u_long*)&puwch->data[4+8*i]);
			}
			
//			outputBinary(puwch->data, puwch->uc_cipher_len, pipe);
			if(outputtext_tcp(puwch->data, puwch->uc_cipher_len, pipe))
				printip(pi, pipe);

			//one subpacket parsed!

			datalen -= (puwch->uc_cipher_len + UC_HEAD_LEN);
			pdata += (puwch->uc_cipher_len + UC_HEAD_LEN);

		}
		while(datalen > 0);

		if(datalen == 0)
			return 1;
		else
			return 0;
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -