Register for your free account! | Forgot your password?

You last visited: Today at 05:11

  • Please register to post and access all features, it's quick, easy and FREE!

 

Chat Packet

Reply
 
Old   #1
 
elite*gold: 0
Join Date: May 2006
Posts: 300
Received Thanks: 42
Post Chat Packet Manipulation in C++

Hello all, I am kinda going to use this post as a log of my packet study progress. Feel free to comment, contribute, correct and fill the gaps (and why not flame a bit, just a bit!)

Some background info: I'm kinda new to packet stuff, Usually I used to made my bots and tools calling game functions directly. Well, I have just hooked conquer packets recv/send functions and start sniffing them. I'm using C++.

This is about the current lastest oficial conquer patch: 6715.

I'm starting with some chat packets, here are some received ones:

Code:
Chat in talk channel
3f 00 59 08 08 ff ff ff ff 0f 10 d0 0f 18 00 20  ; ?.Y............ 
e7 0b 30 00 38 00 40 01 48 00 52 08 50 69 72 61  ; ..0.8  [MENTION=6808217].H.[/MENTION]R.Pira
74 65 33 32 52 04 41 6c 6c 20 52 00 52 0b 6f 6c  ; te32R.All R.R.ol
61 20 6e 6f 20 61 6c 6c 6c 52 00 52 00 52 00     ; a no alllR.R.R.

Chat in talk channel with recipient target
48 00 59 08 08 ff ff ff ff 0f 10 d0 0f 18 00 20  ; H.Y............ 
e8 0b 30 00 38 00 40 01 48 00 52 08 50 69 72 61  ; ..0.8  [MENTION=6808217].H.[/MENTION]R.Pira
74 65 33 32 52 0c 77 69 6e 64 77 61 6c 6b 65 72  ; te32R.windwalker
33 32 52 00 52 0c 6f 6c 61 20 63 6f 6d 20 6e 6f  ; 32R.R.ola com no
6d 65 52 00 52 00 52 00                          ; meR.R.R.

Chat in whisper channel
45 00 59 08 08 ff ff ff ff 0f 10 d1 0f 18 00 20  ; E.Y............ 
e8 0b 30 ae a3 5f 38 00 40 01 48 00 52 08 50 69  ; ..0.._8  [MENTION=6808217].H.[/MENTION]R.Pi
72 61 74 65 33 32 52 0c 77 69 6e 64 77 61 6c 6b  ; rate32R.windwalk
65 72 33 32 52 00 52 07 77 68 69 73 70 65 72 52  ; er32R.R.whisperR
00 52 00 52 00                                   ; .R.R.
Code:
A system message (at game's top left corner)
31 [PACKET RECV <<] Type: 2137 Length: 143
8f 00 59 08 08 ff ff ff 07 10 d5 0f 18 00 20 95  ; ..Y........... .
07 30 00 38 00 40 01 48 00 52 06 53 59 53 54 45  ; .0.8  [MENTION=6808217].H.[/MENTION]R.SYSTE
4d 52 08 41 4c 4c 55 53 45 52 53 52 00 52 60 3c  ; MR.ALLUSERSR.R`<
2a 2a 41 68 6d 65 64 5f 46 61 64 65 6c 2a 2a 3e  ; **Ahmed_Fadel**>
20 64 65 66 65 61 74 65 64 20 61 20 64 65 76 69  ;  defeated a devi
6c 20 69 6e 20 74 68 65 20 44 65 69 74 79 6c 61  ; l in the Deityla
6e 64 20 61 6e 64 20 72 65 63 65 69 76 65 64 20  ; nd and received 
61 20 72 61 72 65 20 74 72 65 61 73 75 72 65 20  ; a rare treasure 
46 61 6e 63 79 43 61 76 65 46 6c 61 67 21 20     ; FancyCaveFlag!

Well, I intend to structure chat packet like this:

Code:
struct Packet_ChatMessage {
	WORD wSize;
	WORD wType;
	BYTE bUnknown;		//0x08 always?
	DWORD dwFontColor;	//not sure
	WORD wUnknown;		//0x100f for chat msg
	WORD wChannel;		//0x0fd1 = whisper, 0x0fd0 = talk, 	
	char szUnknown1[16];
	char* szMessagePack;
			//MessagePack struct, dinamyc allocated
			//BYTE bSenderNameLen;
			//char szSenderName[bSenderNameLen];
			//BYTE bSeparator;	// 0x52
			//BYTE bRecipientNameLen;
			//char szRecipientName[bRecipientNameLen]; 
			//char szSeparator[3]; //0x52 0x00 0x52
			//BYTE bMessageLen;
			//char szMessage[bMessageLen];
			//char szMessageEnd[6]; //0x52 0x00 0x52 0x00 0x52 0x00
};
I am surprised that I can just replay a recv chat packet to client (send the packet again to client) and it just worked well (re-displayed the chat message). I thought that it could have some packet count/time check or some mechanism to invalidate "wrong packets". Well, maybe is just about the chat, I will try later with other packets type.

So, with this stuff in mind I think it's all about dissecting other packets and PARSING them FTW. Seems much more easier than hooking dozen of game functions. If someone have some packet functions parser or related stuff to share could save me time, otherwise I'm just writing mines atm.

Cheers



giacometti is offline  
Thanks
1 User
Old   #2
 
elite*gold: 0
Join Date: Apr 2018
Posts: 4
Received Thanks: 0
im following


ghosfromhell is offline  
Old   #3
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,832
Received Thanks: 3,297
It's using Google Protocol Buffers for encoding and decoding the packet body (offset 4 and beyond). There is a time mechanism. Here's the older packet structure for reference: .
Spirited is offline  
Thanks
1 User
Old   #4
 
elite*gold: 0
Join Date: May 2006
Posts: 300
Received Thanks: 42
Well, I have looked about google's proto buffers, didn't feel confortable using it. Even not sure conquer is using it for serializing its structures, I think its still possible using it to de-serializing packets in any shape you may want. Well, for my purpose I dont need to know what means every single byte from packet (not yet) so I find easy doing a "raw" parsing like this:

Code:
#pragma once

#include <Windows.h>
#include <string>

enum COPacket : WORD
{
	Message = 2137
	
};

enum MessageType : WORD
{
	Chat = 0x100F
};

enum ChatChannel : WORD
{
	Talk = 0xfd0,
	Whisper = 0xfd1,
	World = 0xfe5

};


#pragma pack(push, 1)		//avoid structure padding
class Packet_Message {
public:
	WORD wSize;
	WORD wType;
	BYTE szUnknown1;		//0x08 always?
	DWORD dwFontColor;		//not sure
	WORD wMessageType;		//0x100f for chat msg
	/*from here I should make a union, it depends on MessageType*/
	WORD wChatChannel;		//0xfd1 = whisper, 0xfd0 = talk, 	0xfe5 = world
	char szUnknown2[14];
	BYTE szMessagePack;		
			//MessagePack struct, dinamyc allocated
			//BYTE bSenderNameLen;
			//char szSenderName[bSenderNameLen];
			//BYTE bSeparator;	// 0x52
			//BYTE bRecipientNameLen;
			//char szRecipientName[bRecipientNameLen]; 
			//char szSeparator[3]; //0x52 0x00 0x52
			//BYTE bMessageBodyLen;
			//char szMessageBody[bMessageBodyLen];
			//char szSeparator[6]; //0x52 0x00 0x52 0x00 0x52 0x00

	std::string getSender()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		return std::string((const char*)(&this->szMessagePack), 1, bSenderNamelen);
	}

	std::string getRecipient()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1), 1, bRecipientNamelen);
	}

	std::string getMessageBody()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		DWORD bMessageBodylen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3), 1, bMessageBodylen);
	}

	void showinfo() 
	{
		cout << hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " wSize: " << hex << this->wSize << endl;
		cout << hex << std::setw(4) << (DWORD)&this->wType - (DWORD)&this->wSize << " wType: " << hex << this->wType << endl;
		cout << hex << std::setw(4) << (DWORD)&this->szUnknown1 - (DWORD)&this->wSize << " bUnknown: " << hex << (DWORD)this->szUnknown1 << endl;
		cout << hex << std::setw(4) << (DWORD)&this->dwFontColor - (DWORD)&this->wSize << " dwFontColor: " << hex << this->dwFontColor << endl;
		cout << hex << std::setw(4) << (DWORD)&this->wMessageType - (DWORD)&this->wSize << " wMessageType: " << hex << this->wMessageType << endl;
		
		cout << hex << std::setw(4) << (DWORD)&this->wChatChannel - (DWORD)&this->wSize << " wChannel: " << hex << this->wChatChannel << endl;
		cout << hex << std::setw(4) << (DWORD)&this->szMessagePack - (DWORD)&this->wSize << " szMessagePack: " << dec << (DWORD)this->szMessagePack << endl;

		cout << hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Sender: " << this->getSender() << endl;
		cout << hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Recipient: " << this->getRecipient() << endl;
		cout << hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " MessageBody: " << this->getMessageBody() << endl;

	}
};
#pragma pack(pop) //avoid structure padding
And using code above produces output like this:

Code:
[RECV]
7e 00 59 08 08 ff ff ff ff 0f 10 e5 0f 18 00 20  ; ~.Y............ 
fd 03 30 00 38 00 40 01 48 00 52 0d 59 75 6e 6b  ; ..0.8 [MENTION=6808217].H.[/MENTION]R.Yunk
6f 2e 4c 61 76 65 7a 7a 69 52 04 41 6c 6c 20 52  ; o.LavezziR.All R
00 52 45 53 65 6c 6c 3e 3e 3e 20 61 6c 6c 20 5b  ; .RESell>>> all [
49 74 65 6d 20 45 67 79 70 74 4a 65 72 73 65 79  ; Item EgyptJersey
20 31 30 37 36 31 35 37 32 36 33 20 34 32 39 34  ;  1076157263 4294
39 36 37 32 39 35 5d 20 20 65 6c 20 45 76 65 6e  ; 967295]  el Even
74 20 35 6c 73 20 3a 44 52 00 52 00 52 00        ; t 5ls :DR.R.R.

0000 wSize: 7e
0002 wType: 859
0004 bUnknown: 8
0005 dwFontColor: ffffffff
0009 wMessageType: 100f
000b wChannel: fe5
001b szMessagePack: 13
0000 Sender: Yunko.Lavezzi
0000 Recipient: All 
0000 MessageBody: Sell>>> all [Item EgyptJersey 1076157263 4294967295]  el Event 5ls :D
Well, I am happy with the result. Just need to make the union structs stuff to handle it in a general fashion. C++ Struct Padding was a concept I didn't know and took me an hour of debugging to find out what was happing that my code was not working (in the begining)... Dam crap (awesome =p) otimizations!

Don't expect me to do this for every packet type, with this I think it's enough for manipulating packets buffers in C++.

Cheers


giacometti is offline  
Old   #5
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,832
Received Thanks: 3,297
The unknown byte is the number of fields ... If I remember correctly.
Spirited is offline  
Old   #6
 
elite*gold: 0
Join Date: May 2006
Posts: 300
Received Thanks: 42
Field's number of what? It doesn't seem correlated with message's fields (I could not see any correlation with the number 08 at least).


I think I'm done with chat packets. I feelling ready to move on, this basic packet's manipulation seems enough. For post completeness, just sharing more organized code. I did a union implementation for chat/system messages but it turned out very ugly code. Some object oriented hierarchy just came in handy (see below).

This output:
Code:
Received packets: 13
Found Chat Message Packet, dissecting:
(~asd~)ahmed~) -> All : Buy 30 [Item SeniorEXPBall 1076943851 4294967295] Offer
Found a System Message Packet, dissecting:
SYSTEM -> ALLUSERS: <BeTshR> defeated a devil in the Deityland and received a rare treasure FaithfulJadeBox! 
Found Chat Message Packet, dissecting:
MaFiaa -> All : #36[Item SuperTriumphRapier(+12) 1075430744 4293649791] [Item SuperLordPistol(+12) 1075430745 4293649791]
Found a System Message Packet, dissecting:
SYSTEM -> ALLUSERS: <Zeck> defeated a devil in the Deityland and received a rare treasure DeitylandYellowRunePack! 
Found Chat Message Packet, dissecting:
*~BlacK~Wing~* -> All : #36[Item VioletGem 1083046370 4293395709][Item MoonGem 1083028805 4278255360]#36
Found a System Message Packet, dissecting:
SYSTEM -> ALLUSERS: <romansya> defeated a devil in the Deityland and received a rare treasure DeitylandAttributePack!
Came from this:
Code:
cout << "Received packets: " << log_packets_received.size() << endl;
for (auto& packet : log_packets_received) {
	if (packet->getType() == COPacket::Message) {
		Packet_MessageChat* copacket = (Packet_MessageChat*)packet->getBuffer();
		if (copacket->wMessageType == MessageType::Chat) {
			cout << "Found Chat Message Packet, dissecting:" << endl;
			//packet->ShowHexDump();
			//copacket->showinfo();
			cout << copacket->getMessage() << endl;
		}
		else {
			cout << "Found a System Message Packet, dissecting:" << endl;
			cout << ((Packet_MessageSystem*)copacket)->getMessage() << endl;
		}
	}
}
Using this:
Code:
#pragma once

#include <Windows.h>
#include <string>

enum COPacket : WORD
{
	Message = 2137
	
};

enum MessageType : WORD
{
	Chat = 0x100F,
	System = 0xEA10,
	Qualifier = 0xE610

};

enum ChatChannel : WORD
{
	Talk = 0xfd0,
	Whisper = 0xfd1,
	World = 0xfe5

};


#pragma pack(push, 1)		//avoid structure padding
struct Packet_Message 
{
	WORD wSize;
	WORD wType;
	BYTE szUnknown1;		//0x08 always?
	DWORD dwFontColor;		//not sure
	WORD wMessageType;		//0x100f for chat msg
};

struct Packet_MessageChat : public Packet_Message 
{
	WORD wChatChannel;		//0xfd1 = whisper, 0xfd0 = talk, 	0xfe5 = world
	char szUnknown2[14];
	BYTE szMessagePack;		//1st byte of messagepack struct
			//MessagePack struct, dinamyc allocated
			//BYTE bSenderNameLen;
			//char szSenderName[bSenderNameLen];
			//BYTE bSeparator;	// 0x52
			//BYTE bRecipientNameLen;
			//char szRecipientName[bRecipientNameLen]; 
			//char szSeparator[3]; //0x52 0x00 0x52
			//BYTE bMessageBodyLen;
			//char szMessageBody[bMessageBodyLen];
			//char szSeparator[6]; //0x52 0x00 0x52 0x00 0x52 0x00

	std::string getSender()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		return std::string((const char*)(&this->szMessagePack), 1, bSenderNamelen);
	}

	std::string getRecipient()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1), 1, bRecipientNamelen);
	}

	std::string getMessageBody()
	{
		if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		DWORD bMessageBodylen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3), 1, bMessageBodylen);
	}

	void showinfo()
	{
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " wSize: " << std::hex << this->wSize << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wType - (DWORD)&this->wSize << " wType: " << std::hex << this->wType << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->szUnknown1 - (DWORD)&this->wSize << " bUnknown: " << std::hex << (DWORD)this->szUnknown1 << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->dwFontColor - (DWORD)&this->wSize << " dwFontColor: " << std::hex << this->dwFontColor << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wMessageType - (DWORD)&this->wSize << " wMessageType: " << std::hex << this->wMessageType << std::endl;

		std::cout << std::hex << std::setw(4) << (DWORD)&this->wChatChannel - (DWORD)&this->wSize << " wChannel: " << std::hex << this->wChatChannel << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->szMessagePack - (DWORD)&this->wSize << " szMessagePack: " << std::dec << (DWORD)this->szMessagePack << std::endl;

		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Sender: " << this->getSender() << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Recipient: " << this->getRecipient() << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " MessageBody: " << this->getMessageBody() << std::endl;

	}

	std::string getMessage() 
	{
		return getSender() + " -> " + getRecipient() + ": " + getMessageBody();
	}
};

struct Packet_MessageSystem : public Packet_Message
{
	char szUnknown2[15];
	BYTE szMessagePack;

	std::string getSender()
	{
		//if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		return std::string((const char*)(&this->szMessagePack), 1, bSenderNamelen);
	}

	std::string getRecipient()
	{
		//if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1), 1, bRecipientNamelen);
	}

	std::string getMessageBody()
	{
		//if (this->wMessageType != MessageType::Chat) return "";

		DWORD bSenderNamelen = (DWORD)this->szMessagePack;
		DWORD bRecipientNamelen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1);
		DWORD bMessageBodylen = (DWORD)*(BYTE*)((DWORD)&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3);
		return std::string((const char*)(&this->szMessagePack + 1 + bSenderNamelen + 1 + 1 + bRecipientNamelen + 3), 1, bMessageBodylen);
	}

	void showinfo()
	{
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " wSize: " << std::hex << this->wSize << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wType - (DWORD)&this->wSize << " wType: " << std::hex << this->wType << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->szUnknown1 - (DWORD)&this->wSize << " bUnknown: " << std::hex << (DWORD)this->szUnknown1 << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->dwFontColor - (DWORD)&this->wSize << " dwFontColor: " << std::hex << this->dwFontColor << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wMessageType - (DWORD)&this->wSize << " wMessageType: " << std::hex << this->wMessageType << std::endl;

		std::cout << std::hex << std::setw(4) << (DWORD)&this->szMessagePack - (DWORD)&this->wSize << " szMessagePack: " << std::dec << (DWORD)this->szMessagePack << std::endl;

		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Sender: " << this->getSender() << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " Recipient: " << this->getRecipient() << std::endl;
		std::cout << std::hex << std::setw(4) << (DWORD)&this->wSize - (DWORD)&this->wSize << " MessageBody: " << this->getMessageBody() << std::endl;

	}

	std::string getMessage()
	{
		return getSender() + " -> " + getRecipient() + ": " + getMessageBody();
	}
};
#pragma pack(pop) //avoid structure padding
Sorry for duplicating almost identical methods in both derived class, didn't figure it out another way of coding...

I hope I could motivate and helped someone else interested in packet sniffing/manipulation. I've enjoyed the process a lot! This is
definitely not a step by step tutorial but it can give some directions on how abstract packet buffers into classes, at least. It's not even a tutorial, its missing some code, but I think I put sufficient for anyone interested enough to follow along.
giacometti is offline  
Old   #7
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,832
Received Thanks: 3,297
Google protocol buffers is a packing encoder for structured data. That byte is the only guaranteed to be it's own variable. It's the number of fields / variables in that structure. For the chat packet, that's the user ID / timestamp, channel, style, color, mesh1, mesh2, string list count, and string packer. 8 fields in total. If you'd like to decode this packet, you more or less have to use Google Protocol Buffers.



https://developers.google.com/protocol-buffers/


Spirited is offline  
Reply



« Previous Thread | Next Thread »

Similar Threads
[Help] Weather Packet (My First Packet)
delete this thread.
95 Replies - CO2 PServer - Discussions / Questions
Understanding the Packet System - Basics of a Packet explained
Read the advice first... *****************UPDATED 12/11/2011********************************* **** ADDED VB6 PROXY BOT SOURCE-CODE, WORKING...
30 Replies - Cabal Main - Discussions / Questions
[Request] Packet Structure for CharData Packet
can someone tell me which structure the CharData packet has? i would really appreciate this, since im still noob in such things. its just too high...
4 Replies - SRO Ask the Experts
[Question] Packet data , packet editing ??
I would like to know : What is packet data? How do i get the address for hacking a item in game? How to use it ??
2 Replies - 9Dragons



All times are GMT +2. The time now is 05:11.


Powered by vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Abuse
Copyright ©2018 elitepvpers All Rights Reserved.