I got a bit too excited when I started my newest knitting project and accidentally turned my challenge flag into a knitting pattern.

Category: misc

Solver: MarDN, linaScience

Flag: GPNCTF{Congr4tulati0ns-Y0u-h4v3-Fr0gged-H0urs-Of-My-W0rk-for-Th1s-Fl4g!}

Writeup

This challenge consists of a description of a knitting project, indicating a pattern of knit and purl stitches. There is also a note that the piece is knitted flat and that odd rows show the right side of the project.

Finding patterns in knitting patterns

After briefly considering knitting the whole thing, as a first step we translated the written instructions into a long form with a simple python script, which then looked like this:

KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKPKKKKKPKKKPPPPKPPKKKK
KKKKKKPPKPKKPPKPPKKPPPKKKK
KKKKPPKKPKKPKKPKKPPPKPKKKK
KKKKKPPPKKPPPPKKPKPPKPKKKK
KKKKKPPPKKPPKKPPPKPKKPKKKK
KKKKKKPKPPKPPPKPKPKPKKKKKK
KKKKPKPPKKKPKKKKKKPKKPKKKK
KKKKKKPKPPKPPPKPPKKPPKKKKK
KKKKKKPKPKKPKKPKPPKKKPKKKK
KKKKKPKPKPPPPPKKPPKKKKKKKK
KKKKKPKKPKPPKKKPPKKKKPKKKK
KKKKKKPKPPKPPPKPKKPPKPKKKK
KKKKPKKPPKKPKKKKKKPPKPKKKK
KKKKKPPPKKPPPPKKPKPPKPKKKK
KKKKPKPPKKKPKKKPKPKKKPKKKK
KKKKKPKKPKKKPPKKPPKKKKKKKK
KKKKKPKKPKPPKKPPKPPKKPKKKK
KKKKKPPKKPPPPPKPPKKPKPKKKK
KKKKKKKPPKKPKKPPPPKKPPKKKK
KKKKKPKKKPPKPPKPPPKKPKKKKK
KKKKKPKKPKPPKKKKPPKKPPKKKK
KKKKKKPPKPKKPPKPPPKPPKKKKK
KKKKPPPKPKKPKKKPKKPKPPKKKK
KKKKKKPPKKKKPPKPPPKPKPKKKK
KKKKKPPKKPKPKKKPKKPKPPKKKK
KKKKKPPKPPPKPPKPPPKKPPKKKK
KKKKPPPPKKPPKKKPPKPKKPKKKK
KKKKKPPKKKKPPPKPPPKPKKKKKK
KKKKPPKKPKKPKKKPKPKKKPKKKK
KKKKKKPPKPKKPPKPPPKPKKKKKK
KKKKPKPPKKKPKKKKKPPKKPKKKK
KKKKKPPKPPPPPPKPPKPPPKKKKK
KKKKKKPPPPKPKKKKPKKKKPKKKK
KKKKKPKPKPKKPPKPKKKPPKKKKK
KKKKKKPPPPKPKKPKKKPPKPKKKK
KKKKKPKKKPPPPPKPKPKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK
KKKKKKKKKKKKKKKKKKKKKKKKKK

We first suspected a visible picture in this, so we replaced the K and P with some symbols that were easier to differentiate:

##########################
##########################
##########################
##########################
#####.#####.###....#..####
######..#.##..#..##...####
####..##.##.##.##...#.####
#####...##....##.#..#.####
#####...##..##...#.##.####
######.#..#...#.#.#.######
####.#..###.######.##.####
######.#..#...#..##..#####
######.#.##.##.#..###.####
#####.#.#.....##..########
#####.##.#..###..####.####
######.#..#...#.##..#.####
####.##..##.######..#.####
#####...##....##.#..#.####
####.#..###.###.#.###.####
#####.##.###..##..########
#####.##.#..##..#..##.####
#####..##.....#..##.#.####
#######..##.##....##..####
#####.###..#..#...##.#####
#####.##.#..####..##..####
######..#.##..#...#..#####
####...#.##.###.##.#..####
######..####..#...#.#.####
#####..##.#.###.##.#..####
#####..#...#..#...##..####
####....##..###..#.##.####
#####..####...#...#.######
####..##.##.###.#.###.####
######..#.##..#...#.######
####.#..###.#####..##.####
#####..#......#..#...#####
######....#.####.####.####
#####.#.#.##..#.###..#####
######....#.##.###..#.####
#####.###.....#.#.########
##########################
##########################
##########################
##########################

It became clear that this was not the case, but from this we could identify the first and last four rows and columns as probably not containing any data. We therefore proceeded to ignore them from here on. The two middle columns were also suspicious, since they alternated between containing two zeros and two ones. They might be a form of divider, but we were not sure of this at that point.

For the remaining 36 rows of 18 symbols each, we tried to come up with codes to interpret them as. We tried reading them as zeros and ones and interpreting them as binary/ASCII, but this failed at this step. Therefore, we looked into more visual codes like QR codes and Data Matrix because the two middle columns reminded us of finder patterns in those kinds of code.

Knitting knowledge needed

At this point, we had to take a step back and take a look at the provided information again. The note at the start of the challenge caught our eye, which mentioned the project being worked flat and therefore having to differentiate between even and odd lines.

It now became clear that we had to actually use our (admittedly limited) knitting knowledge, especially two points:

  1. Knitting projects that are worked flat need to be flipped horizontally after every line is finished, so that one can always knit a row from left to right.
  2. When looked at from the reverse, a knit stitch will look like a purl stitch and vice versa. This becomes interesting when flipping the work as described above.

This means that if we were to actually knit the instructions, it would not look like our first sketch. Instead, every second line would have to be reversed and the symbols inverted to make up for the flipping of the project. Additionally, one has to read the lines from last to first, since the last knitted line will be the one on top of the finished work.

For those transformations, we wrote a small python script:

filename = 'output-binary.txt'
fileout = 'output-visual.txt'

with open(filename, 'r') as file:
    lines = file.readlines()

# read lines from last to first
lines = lines[::-1]

for i in range(1, len(lines), 2):
    # reverse every second line except for last character (newline)
    lines[i] = lines[i][0:][::-1] + lines[i][-1]

    # invert every second line
    lines[i] = ''.join(['0' if x == '1' else '1' if x == '0' else '' for x in lines[i]]) + '\n'

with open(fileout, 'w') as out:
    for i in range(len(lines)):
        out.write(''.join(lines[i]))

Note that input-binary.txt contains our above visualization, but with every # replaced by a 0 and every . replaced by a 1. We visualized this output in a conditionally formatted spreadsheet:

knitting pattern

Here, we can clearly see that our assumptions about the first and last four rows and columns were correct. If we interpret the middle two columns as a divider, the result is two separated bytes per row, all of which conveniently start with a 0. Is this now the ASCII we were looking for?

Cyberchef output

Turns out, Cyberchef agrees and yields the flag to us!