Skip to content

Instantly share code, notes, and snippets.

@atoponce
Last active March 8, 2022 08:04
Show Gist options
  • Save atoponce/2c10f40a84ad0aa0a7bf5fd2d442ea9a to your computer and use it in GitHub Desktop.
Save atoponce/2c10f40a84ad0aa0a7bf5fd2d442ea9a to your computer and use it in GitHub Desktop.
Convert any binary to an image

Convert any binary to PNG

This walk through comes from @GalacticFurball who tweeted two images representing the youtube_dl source code as of 2020-09-20. They mentioned later in the thread that they struggled converting the gzip-compressed tarball of the source code with Imagemagick to a PNG, so they ended up using a 3rd party website to do the work. This Gist will show you how to do it cleanly and exactly.

Instructions

If you would like to convert any non-image binary into PNG, Imagemagick makes this trivial. I will be executing the commands on a Debian Linux system, so you may need to adjust the commands for BSD, macOS, or Windows as necessary.

0. Theory

We will be treating the binary bytes as 24 bit RGB values. This means there are 8 bits for red, 8 bits for green, and 8 bits for blue. We will not worry about an alpha channel. This means that your binary needs to be a multiple of 3 bytes for a full RGB conversion of the binary into an image. This may mean appending null bytes to the end of the binary to make it the right size.

We will then divide this number by 3, as each pixel will represent 3 bytes. This will give us the total number of pixels in our image. To get a square-ish image, we will need to get the divisors of this number, so we can find an exact width and height the image will be.

We can then use Imagemagick to make the conversion. Let's get started.

1. Get exact bytes

I already have a copy of the youtube_dl-2020.9.20 source code, so I'm going to build a compressed archive from it. Instead of GZIP however, I'm going to use XZ with the tightest compression possible to make the resulting image as small as possible. Also, for greater platform compatability, I'll be using cpio(1) to create the archive:

$ find youtube_dl-2020.9.20 | cpio -o | xz -9 > youtube_dl-2020.9.20.cpio.xz

Now get the byte size of the compressed archive:

$ ls -l youtube_dl-2020.9.20.cpio.xz
-rw-rw-r-- 1 aaron aaron 1043128 Oct 28 21:12 youtube_dl-2020.9.20.cpio.xz

The compressed archive is 1043128 bytes in size.

2. Append null bytes (if needed)

Our byte size needs to be a multiple of 3. Unfortunately, 1043128 divided by 3 is 347708 remainder 1. This means we need to append two bytes to the archive. We can do this fairly trivially:

$ truncate -s +2 youtube_dl-2020.9.20.tar.xz

Now check our byte size of the archive:

$ ls -l youtube_dl-2020.9.20.cpio.xz
-rw-rw-r-- 1 aaron aaron 1043130 Oct 28 21:13 youtube_dl-2020.9.20.cpio.xz

We're now ready to roll. We know our image will have 1043130/3 = 347710 pixels in total. However, before we go any further, we should get the SHA-256 digest of our compressed archive, to verify that all the bits are correctly in place for our recipient when the deconvert the image back:

$ shasum -a 256 youtube_dl-2020.9.20.cpio.xz 
3811fa8c563e38568a5a609d0c59c206a889c2a2570be2609852e38d2112aea0  youtube_dl-2020.9.20.cpio.xz

4. Find the exact width and height

The proper divisors of 347710 are 1*347710, 2*173855, 5*69542, 10*34771, 11*31610, 22*15805, 29*11990, 55*6322, 58*5995, 109*3190, 110*3161, 145*2398, 218*1595, 290*1199, 319*1090, and 545*638. To make one as square as possible, we'll create a 545*638 image.

5. Convert!

So, now that we have our divisors, if you don't already have Imagemagick installed, do that now, then execute the following command:

$ convert -depth 8 -size 545x638 rgb:youtube_dl-2020.9.20.cpio.xz youtube_dl-2020.9.20.png

Our result:

youtube_dl-2020 9 20

6. Deconvert

Let's double-check that it worked by converting the PNG back into the compressed archive, checking its SHA-256 digest, then unrolling the archive and navigating the source code:

$ curl -o gist.png https://user-images.githubusercontent.com/699572/97525713-120e7880-196d-11eb-97dc-5fec97418393.png
$ convert -depth 8 gist.png rgb:gist.cpio.xz
$ shasum -a 256 gist.cpio.xz
3811fa8c563e38568a5a609d0c59c206a889c2a2570be2609852e38d2112aea0  gist.cpio.xz

This SHA-256 matches what we expect, so we can safely assume all the bits are correctly in place. From here, we can extract the data:

$ truncate -s -2 gist.cpio.xz
$ xz -cd gist.cpio.xz | cpio -id
11964 blocks
$ ls youtube_dl-2020.9.20
AUTHORS    MANIFEST.in  setup.cfg   youtube-dl.1
ChangeLog  PKG-INFO     setup.py    youtube-dl.bash-completion
docs       README.md    test        youtube_dl.egg-info
LICENSE    README.txt   youtube_dl  youtube-dl.fish

It worked!

7. A brief note about PNG images and social media

Most online platforms will modify images on upload, such as removing EXIF data, or resizing the image at the risk of data loss. Further, many social media platforms will convert the image to JPEG, regardless of the source format, such as Twitter, Facebook, and Instagram, among others. These come with inherent risks of losing the ability to recover the compressed archive from the image after downloading. I don't know all of the online image hosting sites, pastebins, and other services, nor do I know which ones will modify the image on upload and which won't. This is something you'll have to discover for yourself.

Background - AACS Controversy

In 2006, the Advanced Access Content System (AACS), a Digital Restrictions Management (DRM) solution applied to BluRay and HD-DVD discs, was cracked. The encryption key 0x09F911029D74E35BD84156C5635688C0 was posted online along with software that utilize the key, to decrypt the DRM on these DVDs.

Since this initial posting, the key went viral showing up on pastebins, forums, social networks, blogs, and other corners of the Internet, including the Link aggregator Digg. The Motion Picture Association of America (MPAA) began issuing cease and desist letters citing anti-circumvention provisions of the United States Digital Millennium Copyright Act (DCMA). Digg followed suit by deactivating accounts and removing posts containing or alluding to the key.

In a social revolt against Digg, the AACS encryption key become more popular, and people started getting creative in how to share the key in various ways of obfuscation. The most popular result was the "Free Speech Flag", which is a flag of five colors with the text "+C0" in the lower right corner, pictured below:

Free Speech Flag

Since this initial posting, AACS keys have continued to be cracked and posted online. The currently known keys total at least 28 different keys.

youtube_dl and the RIAA

On October 23, 2020, the Recording Industry Association (RIAA) issued a DCMA takedown request to GitHub where the source code for the youtube_dl project was being hosted. GitHub agreed to the RIAA's request, and deleted the youtube_dl repo. Just like the AACS controversy of 2007, users socially revolted online, reposting the source code all over the internet in personally hosted Git repositories, pastebins, file sharing sites, and elsewhere.

This is where @GalacticFurball comes in. They decided to follow the lead of the Free Speech Flag of the AACS controversy, and convert a compressed archive of the source code to two images, which were then shared on Twitter with instructions on how to convert them back to the compressed archive, and extract the source code to youtube_dl:

convert -depth 8 yt_dl1.png rgb:yt_dl1.part
convert -depth 8 yt_dl2.png rgb:yt_dl2.part
cat yt_dl1.part yt_dl2.part > yt_dl-2020.9.20.tar.gz
yt_dl1.part yt_dl2.part

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment