Hello UGBASE,
For the past few days I've been experimenting with ZombieNet on my test server to track down a crash. I discovered a bug in RakNet (which SA:MP uses): inside RakPeer :: DeallocatePacket it calls delete instead of delete[] when packet->deleteData is true.
This is already fixed in OpenMP, so the issue affects only SA:MP.
Somewhere in samp03svr there appears to be a double-free vulnerability.
What does double-free mean?
• If you allocate memory and then free it (via free or delete), that memory is released. If the code later frees the same pointer again, the result is undefined — in this case it leads to a server crash.
Here are my findings so far:
The function that sets deleteData = true is AllocPacket:
AllocPacket is called when receiving packets like ID_TIMESTAMP, ID_RPC, ID_RPC_REPLY, ID_NEW_INCOMING_CONNECTION, ID_RECEIVED_STATIC_DATA, etc. from the client.
I tried to exploit ID_RPC_REPLY, since it seemed the most promising:
If you can find a reliable way to trigger or exploit this double-free, please credit me. I have limited time and haven’t completed a full exploit, but I wanted to share these findings with the community.
Thanks.
For the past few days I've been experimenting with ZombieNet on my test server to track down a crash. I discovered a bug in RakNet (which SA:MP uses): inside RakPeer :: DeallocatePacket it calls delete instead of delete[] when packet->deleteData is true.
This is already fixed in OpenMP, so the issue affects only SA:MP.
C++:
void RakPeer::DeallocatePacket( Packet *packet )
{
if ( packet == 0 )
return;
if (packet->deleteData)
delete packet->data; // problem here
free(packet);
}
Somewhere in samp03svr there appears to be a double-free vulnerability.
What does double-free mean?
• If you allocate memory and then free it (via free or delete), that memory is released. If the code later frees the same pointer again, the result is undefined — in this case it leads to a server crash.
Here are my findings so far:
The function that sets deleteData = true is AllocPacket:
C++:
Packet *AllocPacket(unsigned dataSize, unsigned char *data)
{
Packet *p = (Packet *)malloc(sizeof(Packet));
p->data=data;
p->length=dataSize;
p->deleteData=true; // here
return p;
}
I tried to exploit ID_RPC_REPLY, since it seemed the most promising:
- AllocPacket is called (with deleteData = true).
- After processing, DeallocatePacket is called. That frees the packet once — Valgrind warns about it, but freeing it once doesn't immediately crash the server. It may corrupt the heap slightly but not trigger an instant crash.
C++:
if ( (unsigned char) packet->data[ 0 ] == ID_RPC_REPLY )
{
HandleRPCReplyPacket( ( char* ) packet->data, packet->length, packet->playerId );
DeallocatePacket( packet );
packet=0; // Will do the loop again and get another packet
}
If you can find a reliable way to trigger or exploit this double-free, please credit me. I have limited time and haven’t completed a full exploit, but I wanted to share these findings with the community.
Thanks.