Terminal Pictures - 20/03/20

Back to Main Page

I had been thinking about CTF challenges, since the moderators of the John Hammond discord server, me included, were thinking about putting one on, and while doing so, I watched a video by Daily Dose of Internet. In this video, he shows how someone cracked a code that was displayed on the side of the CN tower in Toronto, Canada. (The specific part of the video is at 1:47)

This interested me, and I started thinking of a challenge where you would connect to a server, and it would print out a cryptic string which, if printed to a terminal would cause it to print out blocks of colour. This string would change every so often, and stringing all of the blocks of colour together would create an image.

I already knew that this would, in theory, be possible, since the colours can be changed on any ANSI-compatible terminal, which includes the linux and windows terminals, however I wasnt sure how well it would work with python. With a little digging around on the internet, I found this page on Haoyi's Programming Blog, which told me everything I needed to know.

The code needed a little tweaking to get the colours displaying right, but once I got it working, I could print out text with any of the foreground and background colours.

The available combinations of colours

After I got that working correctly, I wanted to have as much potential colour variation as possible, so I made it cycle through every letter, showing every combination of foreground and background, clearing the terminal between every letter using another ANSI control sequence.

Then, to get the average colours of each combination of letter, foreground and background, I used PIL again. I learnt that PIL has a very useful module called ImageGrab, which allows it to take screenshots. I simply used that to take a screenshot of my terminal, then extract each character in turn, resize the image section to 1x1 pixels, and get the colour of that pixel. This gave me the average colour of each possible character.

The next part was to convert images over to this format, which required me to find the best colour for each pixel of the input image. The only way I could think to do this would be to try every colour individually and score it based on how close it was to the target colour, then get the colour with the lowest score. However, with each pixel having to search through 13,312 different colours, it is very slow. I was recommended to try some more advanced searching algorithms, but I am not sure of the best way to do that at the moment.

Once I have the best colour for each pixel, then I just have to set the foreground and background colours, and write the character, and repeat that for every pixel in the image. Once thing to note is that the text on my terminal is in blocks of 8x16 pixels, so to compensate for the aspect ratio I have to make all the images 50% the usual height.

Here is an example image, downloaded from here:

The converted picture

There are a couple of portability issues with the code, such as the screenshot is tailored to my terminal emulator, and the python script output working in windows, but the output text file only working correctly in linux, but it will provide a good starting point for any future work I want to do in this vein.

You can download the code here, and you will need PIL to run it.

Back to Main Page