A heap OOB write in RakNet's split-packet reassembly logic (misattributed to DoS, reported to the RakNet project by 8ARTEK0V0 & fixed in 2014) that affects Legacy Roblox binaries from 2012 through mid-late 2017 due to no one merging the upstream fix.
InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketChannel *splitPacketChannel, CCTimeType time )
{
#if PREALLOCATE_LARGE_MESSAGES==1
InternalPacket *returnedPacket=splitPacketChannel->returnedPacket;
RakNet::OP_DELETE(splitPacketChannel, __FILE__, __LINE__);
(void) time;
return returnedPacket;
#else
unsigned int j;
InternalPacket * internalPacket, *splitPacket;
int splitPacketPartLength;
// Reconstruct
internalPacket = CreateInternalPacketCopy( splitPacketChannel->splitPacketList[0], 0, 0, time );
internalPacket->dataBitLength=0;
for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++)
internalPacket->dataBitLength+=splitPacketChannel->splitPacketList[j]->dataBitLength;
splitPacketPartLength=BITS_TO_BYTES(splitPacketChannel->firstPacket->dataBitLength);
internalPacket->data = (unsigned char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES( internalPacket->dataBitLength ), _FILE_AND_LINE_ );
internalPacket->allocationScheme=InternalPacket::NORMAL;
for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++)
{
splitPacket=splitPacketChannel->splitPacketList[j];
memcpy(internalPacket->data+splitPacket->splitPacketIndex*splitPacketPartLength, splitPacket->data, (size_t) BITS_TO_BYTES(splitPacketChannel->splitPacketList[j]->dataBitLength));
}
for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++)
{
FreeInternalPacketData(splitPacketChannel->splitPacketList[j], _FILE_AND_LINE_ );
ReleaseToInternalPacketPool(splitPacketChannel->splitPacketList[j]);
}
RakNet::OP_DELETE(splitPacketChannel, __FILE__, __LINE__);
return internalPacket;
#endif
}
There is no check on splitPacket->splitPacketIndex*splitPacketPartLength
Roblox never pulled the upstream fix that fixed it until mid-late 2017, where we observe no crashes/OOB writes. The proper fix, if you had source, would be to pull the ReliabilityLayer fixes.
We don't have the source to these clients so we have to improvize. We've made a novel patcher that runs in your browser! to fix this issue with mid-function-hooking in a different (security oriented) manner.
The patch is a mid-function hook inside the memcpy loop of BuildPacketFromSplitPacketList. This is what it basically does.
for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++)
{
splitPacket=splitPacketChannel->splitPacketList[j];
if (splitPacket->splitPacketIndex * splitPacketPartLength
+ (size_t) BITS_TO_BYTES(splitPacket->dataBitLength)
> (size_t) BITS_TO_BYTES(internalPacket->dataBitLength))
continue;
memcpy(internalPacket->data+splitPacket->splitPacketIndex*splitPacketPartLength, splitPacket->data, (size_t) BITS_TO_BYTES(splitPacketChannel->splitPacketList[j]->dataBitLength));
}
This is a security fix. Our patch prevents it from writing past the buffer.