Update to capture unhandled packets that can desync client (orig credit: theFoof)

Based on DM conversation, extracted GetProtocolPacket -> IsProtocolPacket

https://github.com/Jabantiz/EQ2Emulator-Rewrite/blob/master/trunk/source/common/Packets/ProtocolPacket.cpp

ProtocolPacket* subPacket = ProtocolPacket::GetProtocolPacket(p->buffer + processed + offset, subpacket_length, false);
if (subPacket) {
     //I've seen some garbage packets get sent with wrong protocol opcodes but the rest of the combine is still correct
     //So don't break if GetProtocolPacket fails
     ProcessPacket(subPacket);
     delete subPacket;
}
else if (ntohs(*reinterpret_cast<uint16_t*>(p->buffer + processed + offset)) > 0x1e) {
    //Garbage packet?
    crypto.RC4Decrypt(p->buffer + processed + offset, subpacket_length);
    LogError(LOG_PACKET, 0, "Garbage packet?!:");
    DumpBytes(p->buffer + processed + offset, subpacket_length);
}
This commit is contained in:
Image 2020-04-14 09:13:32 -04:00
parent bf4bf5ec4d
commit ae6f55fd12
3 changed files with 45 additions and 7 deletions

View file

@ -555,6 +555,31 @@ void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey
}
}
bool EQProtocolPacket::IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC) {
bool ret = false;
uint16_t opcode = ntohs(*(uint16_t*)in_buff);
uint32_t offset = 2;
switch (opcode) {
case OP_SessionRequest:
case OP_SessionDisconnect:
case OP_KeepAlive:
case OP_SessionStatResponse:
case OP_Packet:
case OP_Combined:
case OP_Fragment:
case OP_Ack:
case OP_OutOfOrderAck:
case OP_OutOfSession:
{
ret = true;
break;
}
}
return ret;
}
void DumpPacketHex(const EQApplicationPacket* app)

View file

@ -104,6 +104,8 @@ public:
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
static bool IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC);
EQProtocolPacket *Copy() {
EQProtocolPacket* new_packet = new EQProtocolPacket(opcode,pBuffer,size);
new_packet->eq2_compressed = this->eq2_compressed;

View file

@ -239,17 +239,28 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
#ifdef LE_DEBUG
LogWrite(PACKET__DEBUG, 0, "Packet", "OP_Combined Packet %i (%u) (%u): ", count, subpacket_length, processed);
#endif
EQProtocolPacket *subp=new EQProtocolPacket(p->pBuffer+processed+offset,subpacket_length);
subp->copyInfo(p);
bool isSubPacket = EQProtocolPacket::IsProtocolPacket(p->pBuffer + processed + offset, subpacket_length, false);
if (isSubPacket) {
EQProtocolPacket* subp = new EQProtocolPacket(p->pBuffer + processed + offset, subpacket_length);
subp->copyInfo(p);
//I've seen some garbage packets get sent with wrong protocol opcodes but the rest of the combine is still correct
//So don't break if GetProtocolPacket fails
#ifdef LE_DEBUG
LogWrite(PACKET__DEBUG, 0, "Packet", "Opcode %i:", subp->opcode);
DumpPacket(subp);
LogWrite(PACKET__DEBUG, 0, "Packet", "Opcode %i:", subp->opcode);
DumpPacket(subp);
#endif
ProcessPacket(subp);
ProcessPacket(subp);
#ifdef LE_DEBUG
DumpPacket(subp);
DumpPacket(subp);
#endif
delete subp;
delete subp;
}
else if (ntohs(*reinterpret_cast<uint16_t*>(p->pBuffer + processed + offset)) > 0x1e) {
//Garbage packet?
crypto->RC4Decrypt(p->pBuffer + processed + offset, subpacket_length);
LogWrite(PACKET__ERROR, 0, "Packet", "Garbage packet?!:");
DumpPacket(p->pBuffer + processed + offset, subpacket_length);
}
processed+=subpacket_length+offset;
}
break;