"RakWrite"

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.

The issue

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

PoC

NOTE: This PoC does not escalate this and is inconsistent. It only triggers a StartProcessException crash and may require multiple runs (or may trigger upon program exit). This PoC can cause unintended side-effects, not limited to corrupting Lua scripts in the game. This PoC will kick you out of the game when ran

poc.py

Patch

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.

Patching for Legacy Roblox clients

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.