Hello,
Je suis en train de coder un Sniffer pour D2 utilisant SharpPcap et PacketNet, cela m'évite de passer par un hook/detour en mode MITM et je trouve ces libs plutot cools enfin bref. Je rencontre un petit probleme concernant la construction de mes paquets D2. J'ai bien conscience que je recois mes données sous forme d'un flux d'octets. ![img]()
J'ai egalement conscience que dans une reception coté sniffer je peux avoir 1 paquet complet + le bout d'un second paquet ou 1 paquet complet ou la suite d'un paquet. Cependant il semblerait que la manière dont je build mes paquets n'est pas bonne dans le cas d'un paquet split en plusieurs receptions :teeth:. J'ai étudié la methode lowReceive du fichier ServerConnection.as. Voici mon code si quelqu'un pourrait m'éclairer sur ce probleme de splitting ca serait super ! :D
public class DofusPacketBuilder
{
private int? _header;
private int? _payloadLen;
private uint? _instanceId;
private int? MessageId => _header >> 2;
private int? LenType => _header & 0b11;
private byte[] _buffer;
private byte[] _temp = Array.Empty<byte>();
public bool TryBuild(byte[] data, out DofusPacket packet, bool isClient)
{
packet = default;
/* Adding previous bytes remaining after the previous packet construction */
if (_temp.Length > 0)
{
data = data.Concat(_temp).ToArray();
_temp = Array.Empty<byte>();
}
IDataReader reader = new BigEndianReader(data);
/* Constructing the header - metadata */
if (reader.BytesAvailable >= 2 && !_header.HasValue)
{
_header = reader.ReadUShort();
_instanceId = isClient ? reader.ReadUInt() : 0;
}
if (LenType.HasValue && reader.BytesAvailable >= LenType && !_payloadLen.HasValue)
{
if (LenType is < 0 or > 3)
throw new Exception(
"Malformated Message Header, invalid bytes number to read message length (inferior to 0 or superior to 3)");
_payloadLen = 0;
for (int i = LenType.Value - 1; i >= 0; i--) _payloadLen |= reader.ReadByte() << (i * 8);
}
/* End of metadata information */
// first case : no data read
if (_buffer == null && _payloadLen.HasValue)
{
if (_payloadLen == 0) _buffer = Array.Empty<byte>();
// enough bytes in the buffer to build a complete message
if (reader.BytesAvailable >= _payloadLen)
_buffer = reader.ReadBytes(_payloadLen.Value);
// not enough bytes, so we read what we can
else if (_payloadLen > reader.BytesAvailable) _buffer = reader.ReadBytes((int) reader.BytesAvailable);
}
//second case : the message was split and it missed some bytes
if (_buffer != null && _payloadLen.HasValue && _buffer.Length < _payloadLen)
{
int bytesToRead = _buffer.Length + reader.BytesAvailable < _payloadLen /* still miss some bytes */
? (int) reader.BytesAvailable
: _payloadLen.Value - _buffer.Length; /* enough bytes in the buffer to complete the message*/
if (bytesToRead != 0) /* adding missing bytes to the buffer */
{
int oldLength = _buffer.Length;
Array.Resize(ref _buffer, _buffer.Length + bytesToRead);
Array.Copy(reader.ReadBytes(bytesToRead), 0, _buffer, oldLength, bytesToRead);
}
}
/* We can construct our packet */
if (_header.HasValue && _payloadLen.HasValue && _instanceId.HasValue && _payloadLen == _buffer?.Length)
{
DofusPacketMetadata metadata = new(MessageId!.Value, LenType!.Value, _payloadLen!.Value, _instanceId!.Value);
packet = new DofusPacket(metadata, _buffer);
/* Reset building state */
_header = null;
_payloadLen = null;
_instanceId = null;
_buffer = null;
/* Adding the remaining data bytes for the next packet construction */
if (reader.BytesAvailable > 0)
_temp = reader.ReadBytes((int) reader.BytesAvailable);
return true;
}
return false;
}
Code appelant :
var ipPacket = (IPPacket) ((EthernetPacket) packet).PayloadPacket;
Packet payloadPacket = ipPacket.PayloadPacket;
byte[] data = payloadPacket.PayloadData;
if (data.Length <= 0 && (data.Length != 1 || data[0] == 0x00)) return;
bool isClient = Equals(ipPacket.SourceAddress, IPAddress.Parse("192.168.1.33"));
if (!packetBuilder.TryBuild(data, out dofusPacket, isClient))
return;
Message msg = MessageReceiver.ComputeMessage(dofusPacket.Metadata.MessageId, dofusPacket.Payload);
Type downcastType = msg.GetType();
object downcast = Convert.ChangeType(msg, downcastType);
builder.AppendLine(
$"> {(isClient ? "Client sent" : "Server sent")}: {downcastType.Name}, Metadata = {dofusPacket.Metadata}");
builder.AppendLine(JsonSerializer.Serialize(downcast, serializerOptions));
Console.WriteLine(builder.ToString());
builder.Clear();
Erreur coté console :

EDIT : J'ai l'impression d'avoir un decalage sur la data que je traite (mes IO sont goods ils ont été testées)
Bonne journée et merci pour votre aide
Ps : l'image provient de ce blog Dofus et le reverse-engineering (2/2) (jaichange.fr)