Here's a write-up of the PoC||GTFO 0x19 issue.

Overview

a polyglot file

a PDF document (initially)

The file is a 80 page PDFLaTeX-generated document, and normalized via mutool clean.

the main Page

the PDF header

manual compatibility fix

The compatibility of this issue was tricky: some very simple vector drawings with Inkscape were corrupting Android & Kindle viewers and some MuPDF versions, but no other viewer or tool.

These drawings are very standard and without any fancy feature (for example, gradients are typically wrong under Safari), but the page would stop rendering after these illustrations, while all the other pages were rendered fine.

Running GhostScript on the file (thanks Kurt for the pointer!) shows the following error:

   **** Error: Ignoring spurious ET operator.
               Output may be incorrect.
   **** Error: Executing Do inside a text block, attempting to recover
               Output may be incorrect.

But it also displays the buggy picture - while all other softwares with bugs just stopped the rendering, and most software would just overcome the mistake and display it the expected way!

a drawing with two arrows too thick

After running mutool clean -d to decompress the page contents, one can find:

[...]
0 0 0 rg BT
25.980761 15 15 -25.980761 612.950443 680.352788 Tm
/f-0-0 1 Tf
[(collision)]TJ
25.980761 -15 -15 -25.980761 6.96737 586.05846 Tm
q
[(collision)]TJ
ET
1 0 0 1 0 0 cm
[...]

PDF has a lot of operators that have to be balanced (see GenDX's operators cheat sheet), and notably here: - BT (Begin Text) and ET (End Text) - q (push state) and Q (pop state).

Clearly here, the End Text tag ET is after the graphical state push q, unbalanced.

The quickest fix was to patch the page contents manually and rebalance the operators, then recompress the PDFs:

[...]
[(collision)]TJ
ET
q
1 0 0 1 0 0 cm
[...]

a drawing with all arrows just fine

So just make sure you run GhostScript in your testing pipeline if you want better compatibility.

a ZIP archive

The file is also a valid ZIP file:

a valid ZIP archive

an HTML page

The file is also an HTML page with JavaScript payload.

an MD5 pile-up

A tree of 3 chosen-prefix collisions of MD5 have been computed, so that for any suffixes, 4 prefixes can be swapped, and the file will keep its MD5.

Each of these suffix start a different file type: a PDF document, a PE executable, a PNG image and an MP4 video.

ZIP, HTML, and (PDF ^ EXE ^ PNG ^ MP4)

MD5s:

ac75bf434f3624612cc3b6ee1aa59218 *pocorgtfo19.pdf
ac75bf434f3624612cc3b6ee1aa59218 *pocorgtfo19.mp4
ac75bf434f3624612cc3b6ee1aa59218 *pocorgtfo19.exe
ac75bf434f3624612cc3b6ee1aa59218 *pocorgtfo19.png

SHA2s:

891b6c4e0cc8f88af2b8c2467c1558b806d2f21be4c7518e7833c27885713464 *pocorgtfo19.pdf
a324d093f178e54cf6d159a9a005204761ffa7b0cb539e328a8371388167cc70 *pocorgtfo19.mp4
0c5e147a27ce71d2e2eb1e5618a08aa0f67d2dc8e9a9f1ed119de3938318dfc6 *pocorgtfo19.exe
76ecc052df4b264a3653822a902ef2db6c042807f12d498d8e7f4dd5ada1724f *pocorgtfo19.png

layout of the file

These 4 prefixes were embedded in the JavaScript payload of an HTML page, embedded in the file suffix - the rest of the file is commented out.

prefixPNG = "iVBORw0K..."
prefixPDF = "JVBERi0x..."
prefixMP4 = "AAAAbGZy..."
prefixPE =  "TVo9LT0t..."
// [...]

Write-up

Rename extension

If you rename the original pocorgtfo19.pdf as .html page and open it in a browser, you see this page.

the HTML payload in a brower

The page payload escapes out of the whole file so that the browser stops loading the whole file (which is 64 Mb).

document.documentElement.innerHTML = document.getElementById('mypage').innerHTML;

Drop file onto itself

The JavaScript of the page only has access to the HTML part of the file, so you need to drop the file on the html page so that it can read the whole file and identify the prefix.

The JavaScript payload identifies the prefix of the current file, and lets you save the file with any of the 4 prefixes.

the HTML payload once the file was dropped onto itself

Note that typically downloading .EXE extensions is forbidden, so you'll need to rename the .EX file to be able to run it.

Colliding payloads

Portable executable

The PE payload is a PDF viewer, Sumatra, version 1.8 (from 2011): it's standalone, fairly small, and the earliest version that renders the whole doc properly.

So the self-collision of the file can view itself.

the PDF payload showing the colliding PDF file

manual compatibility fix

It was compressed with UPX so that the PDF keywords it contains don't interfere with the parsing of the PDF part of the file.

Since it uses the MSVC library, some checks have been patched out since altering the PE header for the collisions will interfere with the UPX de-packing, leading to incorrect sections permissions, wich will prevent it to work after a misleading Runtime R6002 - floating point not loaded error.

Patch this:

C1E81F shr   eax,01F
F7D0   not   eax
83E001 and   eax,1

to set eax to 1 instead.

Portable Network Graphics image

The PNG image is a diagram of the pileup.

It will not open in Safari or OS X preview because they expect the file to start with its IHDR chunk and not collision blocks.

MP4 video

The last colliding file is a short looping video by KidMoGraph that shows 2 cars racing next to each other, almost... colliding:

a near-collision video loop