Hello, today i bring you how to encode and decode the packets of the new darkorbit(which uses netty).
Dictionary:
Short - 2 bytes
Int - 4 bytes
Bool - 1 byte
Str or UTF - Short Length of String + String
The structure of the packets are:
1 - Short Length of all packet
2 - Short Packet ID
3 - Short version (normally 0)
4 - PACKET with shorts, ints, bools and strings (utf)
To encode/decode the bytes, you must use this functions:
Code:
public static int ReadInt(byte[] data)
{
int outputResult = 0;
outputResult += data[0] << 24;
outputResult += data[1] << 16;
outputResult += data[2] << 8;
outputResult += data[3];
return outputResult;
}
public static int ReadShort(byte[] data)
{
int outputResult = 0;
outputResult += data[0] << 8;
outputResult += data[1];
return outputResult;
}
public static byte[] WriteInt(int num)
{
byte[] dataToOuput = new byte[4];
dataToOuput[0] = (byte)(num >> 24);
dataToOuput[1] = (byte)(num >> 16);
dataToOuput[2] = (byte)(num >> 8);
dataToOuput[3] = (byte)(num);
return dataToOuput;
}
public static byte[] WriteShort(int num)
{
byte[] dataToOuput = new byte[2];
dataToOuput[0] = (byte)(num >> 8);
dataToOuput[1] = (byte)(num);
return dataToOuput;
}
And to read the packets or encode, you must use this 2 classes:
Code:
class packetBuilder
{
List<byte> data;
public packetBuilder(int ID)
{
data = new List<byte>();
writeShort(ID);
}
public void writeInt(int num)
{
data.AddRange(Program.WriteInt(num));
}
public void writeShort(int num)
{
data.AddRange(Program.WriteShort(num));
}
public void writeBool(bool state)
{
data.Add(state ? (byte)1 : (byte)0);
}
public void writeString(string str)
{
if (str == null)
{
str = "";
}
byte[] byteStr = Encoding.UTF8.GetBytes(str);
writeShort(byteStr.Length);
data.AddRange(byteStr);
byteStr = null;
}
public byte[] GetBytes()
{
List<byte> list = new List<byte>();
list.AddRange(System.BitConverter.GetBytes(this.data.Count));
list.Reverse();
list.AddRange(data);
System.Console.WriteLine(Encoding.UTF8.GetString(list.ToArray()));
return list.ToArray();
}
}
class packetParser
{
private byte[] Body;
private int Pointer = 0;
public packetParser(byte[] Packet)
{
Body = Packet;
this.Lenght = ReadShort();
this.Id = ReadShort();
}
public short Lenght;
public short Id;
public short ReadShort()
{
return Convert.ToInt16(Program.ReadShort(
new byte[] {
Body[Pointer++],
Body[Pointer++]
}));
}
public int ReadInt()
{
return Program.ReadInt(
new byte[] {
Body[Pointer++],
Body[Pointer++],
Body[Pointer++],
Body[Pointer++],
});
}
public ushort ReadUShort()
{
return Convert.ToUInt16(Program.ReadShort(
new byte[] {
Body[Pointer++],
Body[Pointer++]
}));
}
public uint ReadUInt()
{
return Convert.ToUInt32(Program.ReadInt(
new byte[] {
Body[Pointer++],
Body[Pointer++],
Body[Pointer++],
Body[Pointer++],
}));
}
public string ReadString()
{
try
{
int Lenght = ReadShort();
string data = Encoding.UTF8.GetString(Body, Pointer, Lenght);
Pointer += Lenght;
return data;
}
catch (System.Exception)
{
return "";
}
}
}
Example to use packetParser:
the first packet you receive from the client, apart from the policy, is id: 666.
To read:
Code:
int bytesRead = handler.EndReceive(ar);
if(bytesRead > 0)
{
byte[] Body = new byte[bytesRead];
Array.Copy(buffer, Body, bytesRead);
packetParser packet = new packetParser(Body);
if (packet.Id == 666)
{
Console.WriteLine(packet.ReadInt()); //Version Major
Console.WriteLine(packet.ReadInt()); //Version Minor
Console.WriteLine(packet.ReadInt()); //Version Build
}
}
Example to use packetBuilder:
To respond to the version request (ID:666), you must build a packet like this:
Code:
packetBuilder enc = new packetBuilder(667);
enc.writeShort(0); // version
enc.writeBool(true);
enc.writeInt(0); //Version Major
enc.writeInt(0); //Version Minor
enc.writeInt(27); //Version Build
this.handler.Send(enc.GetBytes());
The Version Major, Minor and Build must be equal to which the client sent
SOMETHING INTERESTING:
To operate an upgraded server darkorbit is not necessary to start encryptions as ARC4 and IOW (InjectedObfuscationWrapper) because it are optional.
Credits
Me.
LittleJ.