Poor Print Cipher Solutions Term 1

As you may or may not know, I have been set the task of writing cipher puzzles for The Poor Print, Oriel College’s Student Paper. However, nothing is secret for every and today is the day I pass to you the solutions to these ciphers.

First Puzzle - Most things are meaningless


The Cipher

The first puzzle plays with the idea that people tend to thing things have meaning when they really don’t. I use this idea by making a cipher where a message is hidden amongst meaningless garbage. The generation of the cipher text is very simple.

  1. Take your message and split the characters up
  2. Prepend each letter in the plain text with a mark letter, in our case it is ‘r’
  3. Fill the gaps between the pairs of letters with a random amount of random letters.

In case you care, here is the python code used to generate it:

import random
import string
import sys

msg = raw_input("Message: ")
mrk = raw_input("Mark Letter: ")

Padding = list(string.punctuation + string.ascii_letters)

for ch in msg:
    pad = random.randint(0,15)
    for i in range(1,pad):
        index = random.randint(0,len(Padding) - 1)
    sys.stdout.write(mrk + ch)

for i in range(0,5):
    index = random.randint(0,len(Padding) - 1)


How to Crack It

Like all other ciphers, the first thing to do is frequency analyse it. The result will be very interesting. An unusually high amount of ‘r’s and an essentially even number of everything else. The strange distribution means that it can’t be a substitution cipher, but the high number of ‘r’s can’t be meaningless! Everything else is pretty much uniform, therefore possibly padding. From this we can conclude that ‘r’ is a mark character and the character appended to each ‘r’ is the message.

Puzzle 2 – Starting from a clean slate

To crack this puzzle, first you need to work out what links Quiet Ravers, Quaint Racoons and the Queen's Riches. They are all Quite Relevant to the solution.
I look forward to your Quick Response!

The Cipher

This cipher, in my opinion, is slightly easier than the last, but takes more work to crack! Firstly, the clue is hinting at QR codes and it is the case that the string of binary represents a QR code. If you care about how that string was made, the QR code was generated online and I copied the QR code into a numbers spreadsheet by hand! Coping the QR code The QR code leads to this website, which seems blank.

How to Crack It

Hopefully you can work out the QR code riddle. Next thing to think about is how the QR code is encoded.

Non-technical Method For Stage 1

You can count the 1s and 0s and see that there are 625 in total, leading us to conclude it is a 25x25 grid. Next, You could hand draw a 25x25 grid and colour them in, or you could make an excel/numbers spreadsheet and enter the 1s and 0s, then use conditional formatting to colour squares black and white accordingly. But this may take forever so I have included the technical method that I would have used below:

Technical Method For Stage 1

I would head to the (UNIX) terminal and do the following:

$ echo -n '111111101....' > text

this simply prints the binary into a file. The -n is needed to ensure there isn’t an additional newline character at the end. Next, we can type:

$ wc -m text

which tells us how many characters are in the file. The response is 625. $625 = \sqrt{25}$ so maybe the binary represents a square grid with a 1 representing a black square and a 0 a white. This makes sense if you have ever seen a QR code reader. With this in mind, I wrote a haskell program that would take the text and turn it into a QR code. Here is the code:

import System.Environment

block = "██"
gap   = "  "
dim = 25
dim' = 2 * dim

main = getContents >>= return . take (dim^2) >>= substitute >>=  return . transform >>= prettyPrint

transform :: String -> [String]
transform [] = []
transform s = take dim' s : (transform $ drop dim' s)

substitute = return . concat . map rep 
  where rep '0' = block
        rep '1' = gap

prettyPrint str = filler >> mapM (\s -> putStrLn $ concat [block, s, block]) str >> filler

filler = putStrLn (take (dim' + 4) $ cycle block)

Here is it working:

QR Code Printer

The code is very simple and I will walk you through it:

  1. We import System.Environment so that we can get our input through POSIX Pipes
  2. we define block, gap dim and dim’ such that block is what we will print for a white square, gap for black, dim is the side length of our QR code and dim’ is the same, adjusting for the fact that both block and gap are 2 characters long.
  3. the main function binds a bunch of monadic functions together. getContents gets our input, return . take (dim * dim) ensures that we have exactly 625 characters, substitute is defined later and replaces each 1 with gap and each 0 with block, return . transform turns the list of chanters into a matrix of characters for printing and prettyPrint prints it to the screen with a border.
  4. transform traverses the list, taking a line, turning that into a list, and attaching that to the rest of the lists of lines.
  5. substitute maps a function onto each character that turns it into either a block or a gap, then joins the list of blocks and gaps into one long string again.
  6. prettyPrint first calls filler, then prints the matrix (with an additional block at the beginning and end of each line to give the QR code a border) and finally calls filler again.
  7. filler is a function that simply prints a line of blocks to add the top and bottom of the border to the QR code.

I then compiled the program to a file called ‘solution’ which I called cat text | ./solution. If you don’t know, cat prints out a file, and | redirects standard output to be the input to the next program.

Stage 2

Now that we have our QR code, we can scan it with a phone app and it takes us to this site. BUT ALAS! The site is blank. I’ll be honest, this stage was a bit of a dick move. Simply highlight the page! The text is coloured white!

Highlight text to show message

Puzzle 3 – The Beast

The Cipher

Now I am not going to post the whole of the instructions here, because it is more than 1 page so I shall leave the instructions here. The first stage is a perfectly secure cyber with an online portal to get the key. Having solved this, we get taken to this page, giving us more instructions and a PDF puzzle. We are finally taken to this page whee the last clue lies in an audio file.

How to Crack It

Stage 1

The first step is to read the specification and try to understand as much of it as you can, before heading to the link and entering some random numbers. What you will see is a time elapsed indicator. This has been left there intentionally and is the weakness in the first stage. Looking back at the instructions, it shows a function for checking. As you can see, as soon as it finds an incorrect number, it exits. This means that the more correct numbers in a row you enter, the longer the elapsed time will be! This hypothesis is backed up by trying a bunch of numbers and seeing that numbers beginning with $3$ take longer to check.

There are two ways to go from here:

  1. Systematically changing the last digit of the password until you get the password correct.
  2. Programming a solution.

My programmatic solution, gets the password in about 8 seconds. The first step was viewing the source of the website and noticing that all it does is send what you enter as a password to http://www.hobson.space/cgi-bin/poor_print.cgi?password="<PASS>" My program is written in BASH and looks like this:

trap "exit 0" TERM
export TOP_PID=$$
function tester {
  echo -n "$1  "
  s=$(seq 4 | xargs -i curl -s "http://www.hobson.space/cgi-bin/poor_print.cgi?password=\"${A}${1}\"")
  end=$(grep -Eio 'Wrong' <<< $s)
  if [ "4" != "$(wc -w <<< $end)" ]
    >&2 echo $1
    kill -s TERM $TOP_PID
  echo $s | grep -Eo '[0-9].[0-9]{1,2}' | sort -nr | head -n 1
export -f tester
while true; do
  A=$A$(seq 0 9 | parallel tester {} $$ | sort -nrk 2 | head -c 1)
  echo -n ${A: -1}
  export A

This will work on any UNIX based system with GNUParallel installed.

Having got the password, we can get the key, decrypt the message as specified in the PDF and head to the next stage.

Stage 2

Stage 2 involves a PDF. The message is a distraction, what really matters is the title. Cross referencing this with the poor print, we will see that it is the same as the title of Tom Saer’s Poetry. When the PDF is printed and overlaid with the poetry, the boxes cover the words ‘recycling’ and ‘people’. These two words get us to stage 3.

Stage 3

At this stage, you discover the audio file. It begins with a clearly evil conversation between two people: M and J. This is then followed by a digital audio signal. The audio is accompanied with a clue:

My advice, when thinking about this puzzle is to slow down and scan your brain for any clues.

With ‘slow’ and ‘scan’ in italics. If you Google ‘slow scan’, you come across Slow Scan Television, a way of transmitting pictures over radio in frequencies within the range of human hearing. You can then deduce that the bleeping at the end of the message is actually an SSTV broadcast. Downloading an SSTV app onto your phone, you can play the audio and extract the picture. Here is a screenshot of me doing just that:


And thats it! A fun little thing to note is that the answers were actually on the wall of Michael’s and my room all along. We have a picture of Bertand Russell, a painting of Charles Mingus and a picture of the Duke Humpfrey Library!


We are at the end of a term of great puzzles! See you next term for some more, where Michael and I will be increasing the stakes each week…