Register for your free account! | Forgot your password?

You last visited: Today at 23:54

  • 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: 319
Received Thanks: 48
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 05/16/2018, 08:53   #2
 
elite*gold: 0
Join Date: Apr 2018
Posts: 22
Received Thanks: 0
im following


ghosfromhell is offline  
Old 05/16/2018, 10:10   #3
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,966
Received Thanks: 3,329
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 05/17/2018, 14:39   #4
 
elite*gold: 0
Join Date: May 2006
Posts: 319
Received Thanks: 48
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 05/17/2018, 17:34   #5
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,966
Received Thanks: 3,329
The unknown byte is the number of fields ... If I remember correctly.
Spirited is offline  
Old 05/17/2018, 21:44   #6
 
elite*gold: 0
Join Date: May 2006
Posts: 319
Received Thanks: 48
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 05/17/2018, 23:27   #7
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,966
Received Thanks: 3,329
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  
Old 05/23/2018, 04:03   #8
 
elite*gold: 0
Join Date: May 2006
Posts: 319
Received Thanks: 48
Quote:
Originally Posted by Spirited View Post
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, thank you again! Now I realized and I am convinced about the need of using google protocol buffer (you had to say it out loud twice, right? ). I notice that some packets of same type were changing a bit their internal offsets, so I dig a bit about packet encoding.

This reference:

https://developers.google.com/protoc.../docs/encoding

specifically shows how to do it (encode/decode) manually (the way I like to do). Basically it uses 7 bit encoding (to shrink bytes / network bandwidth traffic I believe) and a tag (pair key-wiretype) to serialize data.

If someone interested about 7 bit encoding, this video explain it nicely

So, that previous "unknown byte" of value 0x08 means the following:
0x 08 = 0b 0(000 1)(000) => field number 1 and datatype = 0 (varint), so it's expected that next bytes following on the stream to be a varint (int32, int64 etc) encoded in 7 bits. So in the first example we have in the begining of the chat packet:

Code:
A      B      C         D            E      F
3f 00 59 08 | 08 | ff ff ff ff 0f | 10 | d0 0f |18 00 ...
It is decoded as following:

A: packet lenght = 0x3f
B: packet type = 0x859
C: tag (key-wiretype) = pair(1, 0) = field 1 is varint (below)
D: varint = decode7bits(ff ff ff ff 0f) = 0xffffff7f
E: tag = pair(2, 0) => next field is varint
F: varint = decode7bits(d0 0f) = 0xf28
and so on...

I've just write a 7bit encode and decode functions do parse the packets manually, but I will give a try using .proto files before brushing bits everywhere, seems cleaner.

It's very trick to use 7bits encoding to pack packets, you dont need to use all bytes of the data type if you dont used large numbers too often. The next output is just to ilustrate this point of view. I mean, if you have a lot of DWORDs (four bytes) that often just fill 2 bytes of non-zeros numbers, why send a bunch of zeros to network?

Code:
Encoding 10 (0xa): 10
Decoding 10 (0xa): : 10 size: 1
---------------------------------------
Encoding 100 (0x64): 100
Decoding 100 (0x64): : 100 size: 1
---------------------------------------
Encoding 1000 (0x3e8): 2024
Decoding 2024 (0x7e8): : 1000 size: 2
---------------------------------------
Encoding 10000 (0x2710): 20112
Decoding 20112 (0x4e90): : 10000 size: 2
---------------------------------------
Encoding 100000 (0x186a0): 429472
Decoding 429472 (0x68da0): : 100000 size: 3
---------------------------------------
Encoding 1000000 (0xf4240): 4031680
Decoding 4031680 (0x3d84c0): : 1000000 size: 3
---------------------------------------
Encoding 10000000 (0x989680): 81964416
Decoding 81964416 (0x4e2ad80): : 10000000 size: 4
---------------------------------------
Encoding 100000000 (0x5f5e100): 802669184
Decoding 802669184 (0x2fd7c280): : 100000000 size: 4
---------------------------------------
Encoding 1000000000 (0x3b9aca00): 16591328384
Decoding 16591328384 (0x3dceb9480): : 1000000000 size: 5
---------------------------------------
What is very nice in this encoding is that the packet stream has already a structure (flexible) signed inside it, I mean, some metadata usefull for reversing without touching the assembly!

I will have a break guys, real job is killing me. I will be back in a couple of weeks, I believe. Cya! As always, have fun!
giacometti is offline  
Thanks
1 User
Old 05/23/2018, 04:06   #9
 
elite*gold: 12
Join Date: Jul 2011
Posts: 6,966
Received Thanks: 3,329
I'm glad you're making headway now. Good work.
Spirited is offline  
Old 05/24/2018, 04:12   #10
 
elite*gold: 0
Join Date: May 2006
Posts: 319
Received Thanks: 48
Code:
enum WIRETYPE { Varint = 0, Fixed64, String, GroupStart, GroupEnd, Fixed32	};
Code:
23-05-2018 22:53:08 [SENT] Type: 2137 Lenght: 71
===================================================================
47 00 59 08 08 ff ff ff ff 0f 10 d0 0f 18 00 20  ; G.Y............ 
cd 11 28 00 30 00 52 0c 77 69 6e 64 77 61 6c 6b  ; ..(.0.R.windwalk
65 72 33 32 52 04 41 6c 6c 20 52 00 52 13 48 65  ; er32R.All R.R.He
6c 6c 6f 20 77 6f 72 6c 64 20 69 6e 20 61 6c 6c  ; llo world in all
21 52 00 52 00 52 00                             ; !R.R.R.

[DECODED]  Decoded-Lenght: 95 Decoded-Fields: 20
Field's size: 8, 4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 0, 4, 19, 4, 0, 4, 0, 4, 0, 
Field's type: 0, 0, 0, 0, 0, 0, 5, 2, 5, 2, 5, 2, 5, 2, 5, 2, 5, 2, 5, 2, 
47 00 59 08 ff ff ff ff 00 00 00 00 d0 07 00 00  | G.Y.............
00 00 00 00 cd 08 00 00 00 00 00 00 00 00 00 00  | ................
0c 00 00 00 77 69 6e 64 77 61 6c 6b 65 72 33 32  | ....windwalker32
04 00 00 00 41 6c 6c 20 00 00 00 00 13 00 00 00  | ....All ........
48 65 6c 6c 6f 20 77 6f 72 6c 64 20 69 6e 20 61  | Hello world in a
6c 6c 21 00 00 00 00 00 00 00 00 00 00 00 00     | ll!............

Code:
23-05-2018 22:53:08 [RECV] Type: 2137 Lenght: 151
===================================================================
97 00 59 08 08 ff ff ff 07 10 d5 0f 18 00 20 bd  ; ..Y........... .
0e 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 68 3c  ; MR.ALLUSERSR.Rh<
2a 53 61 76 69 6f 72 41 6e 67 65 6c 2a 3e 20 64  ; *SaviorAngel*> d
65 66 65 61 74 65 64 20 61 20 64 65 76 69 6c 20  ; efeated a devil 
69 6e 20 74 68 65 20 44 65 69 74 79 6c 61 6e 64  ; in the Deityland
20 61 6e 64 20 72 65 63 65 69 76 65 64 20 61 20  ;  and received a 
72 61 72 65 20 74 72 65 61 73 75 72 65 20 44 65  ; rare treasure De
69 74 79 6c 61 6e 64 59 65 6c 6c 6f 77 52 75 6e  ; itylandYellowRun
65 50 61 63 6b 21 20                             ; ePack! 

[DECODED]  Decoded-Lenght: 170 Decoded-Fields: 16
Field's size: 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 4, 8, 4, 0, 4, 104, 
Field's type: 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 5, 2, 5, 2, 5, 2, 
97 00 59 08 ff ff ff 00 d5 07 00 00 00 00 00 00  | ..Y.............
3d 07 00 00 00 00 00 00 00 00 00 00 01 00 00 00  | =...............
00 00 00 00 06 00 00 00 53 59 53 54 45 4d 08 00  | ........SYSTEM..
00 00 41 4c 4c 55 53 45 52 53 00 00 00 00 68 00  | ..ALLUSERS....h.
00 00 3c 2a 53 61 76 69 6f 72 41 6e 67 65 6c 2a  | ..<*SaviorAngel*
3e 20 64 65 66 65 61 74 65 64 20 61 20 64 65 76  | > defeated a dev
69 6c 20 69 6e 20 74 68 65 20 44 65 69 74 79 6c  | il in the Deityl
61 6e 64 20 61 6e 64 20 72 65 63 65 69 76 65 64  | and and received
20 61 20 72 61 72 65 20 74 72 65 61 73 75 72 65  |  a rare treasure
20 44 65 69 74 79 6c 61 6e 64 59 65 6c 6c 6f 77  |  DeitylandYellow
52 75 6e 65 50 61 63 6b 21 20                    | RunePack!
One function to rule them all!
I don't think I will need one .proto for every message now (but it will need one class for each packet type as usual, kinda same amount of coding work)... I had to do this before my break, it was exploding inside my mind. Cya!
giacometti is offline  
Old 05/25/2018, 05:46   #11
 
elite*gold: 0
Join Date: Aug 2010
Posts: 983
Received Thanks: 1,054
Now that you know how to identify the field types, restructuring the packet should be a cake walk.

{ Angelius } is offline  
Thanks
1 User
Old 05/25/2018, 12:39   #12
 
elite*gold: 0
Join Date: May 2006
Posts: 319
Received Thanks: 48
Quote:
Originally Posted by { Angelius } View Post
Now that you know how to identify the field types, restructuring the packet should be a cake walk.

Yes! I have just set to "auto" decode every packet received and works very well with other types. But it fail to decode on some packets (show not enumerated typewires), didnt make a deep analysis yet, but I guess not every packet is encoded...

Wow, what a spoiler!!! Thanks man!

Well, my nexts learning/challenging steps is going to struct the packets to make an "item on ground manager" and an "entity manager". I can't wait to start dissecting them, but so much to do in real job... I will be back!


giacometti is offline  
Reply


Similar Threads
[Help] Weather Packet (My First Packet)
06/07/2014 - CO2 PServer - Discussions / Questions - 95 Replies
delete this thread.
Understanding the Packet System - Basics of a Packet explained
11/03/2012 - Cabal Main - Discussions / Questions - 30 Replies
Read the advice first... *****************UPDATED 12/11/2011********************************* **** ADDED VB6 PROXY BOT SOURCE-CODE, WORKING EXAMPLE OF PROXY BOT****** ****************************************************************** The...
[Request] Packet Structure for CharData Packet
05/16/2011 - SRO Ask the Experts - 4 Replies
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 for me/ too much information for my head. :handsdown: S->C(3013)...
[Question] Packet data , packet editing ??
10/13/2009 - 9Dragons - 2 Replies
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 ??



All times are GMT +2. The time now is 23:54.


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.