Information

File: libfreerdp\codecs\zgfx.c
Function: zgfx_decompress_segment()

The variable “count” is being derived from the input bitstream when reading using the “zgfx_GetBits()” macro.
Using the “while” loop, and as long as there are “1” bits in the stream, we can enlarge the value of “count” indefinitely.
Later on, the call to “zgfx_history_buffer_ring_read” uses “count”, and triggers a copy loop into “zgfx->OutputBuffer” which is of size 64KB.

Code Snippet:

if (distance != 0)
{
	/* Match */
	zgfx_GetBits(zgfx, 1);

	if (zgfx->bits == 0)
	{
		count = 3;
	}
	else
	{
		count = 4;
		extra = 2;
		zgfx_GetBits(zgfx, 1);

		while (zgfx->bits == 1)
		{
			count *= 2;
			extra++;
			zgfx_GetBits(zgfx, 1);
		}

		zgfx_GetBits(zgfx, extra);
		count += zgfx->bits;
	}

	zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
	zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
	zgfx->OutputCount += count;
}


References:
https://research.checkpoint.com/reverse-rdp-attack-code-execution-on-rdp-clients
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8784