A Plaid Puzzle

We have a Puzzlescript puzzle that we should solve, where the visible part just lets us input a flag and check if it is correct. Examining the source shows a large invisible board of symbols above the flag – the puzzle, after starting the check, looks something like the following:


The f’s are flag characters, A’s and R’s are random symbols from two different sets of 64 symbols (let’s label the sets A and R), and F and C are special symbols. We win if, after applying the rules, F and C are adjacent.

There are several types of rules:

For convenience, let’s label the function that maps (A, char) -> L as T(a,c), and the function that maps (L, R) -> R as F(l,r). We can see that, if we label the elements of a row as

a[n] ... a[2] a[1] a[0] r

the entire row will disappear if it is finally reduced to Rt, i.e.

F(T(a[n], flag[n]), ... F(T(a[1], flag[1]), F(T(a[0], flag[0]), r))) = Rt

It is useful to take a second look at the structure of the functions F and T. If we do this, we will see that F(l, F(l, r)) = r for all l and r, and that there exists an l0 such that F(l0, r) = r for all r. Therefore, if the sets L and R were equal, we could conclude that the group (L, T) is isomorphic to bit-strings of length 6 with xor as the group operator.

Similarly, looking at T shows that we can find a0 and c0 such that T(a0, c) = l0 and T(a, c0) = l0 for all a and c. For all a other than a0, T(a, c1) != T(a, c2), and similarly for c’s. This all strongly hints that we are dealing with a finite field that is most likely GF(2^6), with T as the multiplication operator and F as the addition, with the added complication that each element can be written in four different ways, as an element of L, R, A or a flag character.

This means that, if we can find mappings from all four of these sets to some set X, we could define a field (X, +, *), where + is F and * is T, in which our condition for a row to disappear is:

a[n]*flag[n] + ... + a[1]*flag[1] + a[0]*flag[0] + r = Rt

Assume that we know the elements of R, C (the set of characters) and A that map to the relevant neutral elements of the field: r0, c1 and a1. We can then build the entire mapping as:

For each guess of these three values, we build the field, check that it reasonable (for each set, all elements map to different field elements; it is consistent with the rules given; field axioms hold), and then solve the set of linear equations given by the rows to find the flag.

This returns several candidate flags (though this might be due to a missing check in my implementation), but it is easy to filter the candidates for the one matching the flag format: PCTF{CTFs4R3Ju5TPuzZLeHUnTSWi7hM0reCoMPut3R5}.