HACKVent 2020 – Day 16

Challenge – Naughty Rudolph

Santa loves to keep his personal secrets on a little toy cube he got from a kid called Bread. Turns out that was not a very good idea. Last night Rudolph got hold of it and frubl’d it about five times before spitting it out. Look at it! All the colors have come off! Naughty Rudolph!

Download

Hints

  • The flag matches /^HV20{[a-z3-7_@]+}$/ and is read face by face, from left to right, top to bottom
  • The cube has been scrambled with ~5 moves in total
  • jElf has already started trying to solve the problem, however he got lost with all the numbers. Feel free to use his current state if you don’t want to start from scratch…

(Not the) Solution

The file contained the model of a Rubiks cube with the letters of the flag on it, but it was scrambled. According to the hint with about 5 moves of simplified notation (FRUBL). This makes 18 different moves.

\(faces = \{ Front, Right, Up, Back, Left, Down \}\) \(rotation = \{ CW, 2xCW, 3xCW \}\) \(moves = faces × rotation\)

We started the challenge late in the evening, with two approches. One was to work from scratch, the other one used the provided template, but ported to C#.

First we wrote down the letters from the cube into matrices, then worked on encoding the rotations. Unfortunately we made some mistakes. For one, we wrote 1 (one) instead of l (lowercase L) and second, we had bugs in the rotation algorithm. The provided skeleton code, uses a 3 dimensional matrix to index face, x and y position. This makes the rotation algorithm very time consuming to write because you have to properly index 3 faces per edge block and 2 per middle block. Not feeling like encoding this for 6 faces we felt clever and reused the existing impl. but just parameterized the faces. This works for the rotated face, but it does not work for the adjacent faces. The block-face indices (x,y) depend on the rotated face and we them hard coded.

By the time we had figured out most of the problems it was already short before midnight. We tried fixing what we knew to be wrong but never got a correct flag. Since full points were now gone and a new day of work coming up, we decided to leave it.

In retrospect, there probably was an issue in our coordinate system. I suspect how we wrote letters of the faces into the matrix, did not match the access pattern of the rotation algorithm. Keeping the axes, indexing via (x,y,z) and having the face as member would have resulted in less complex code I believe.

Solution

With the full points and the “perfect scorer” status now gone, we took another look at the challenge over the next few days. After fixing a few more small bugs in the rotation algorithm, we still didn’t get a valid flag.

In an act of desperation, we had all the variants printed to screen in which “HV20” occurs in any reading direction. There were many. Fortunately, the following one caught our eye because it read “highscore”:

FRONT	HV20{no_s       o0H_{Vsn2       s_on{02VH       2nsV{_H0o
LEFT	ipln_ecs3       cnis_p3el       3sce_nlpi       le3p_sinc
Right	5o_dt@a__       ad5_to_@_       __a@td_o5       _@_ot_5da
Back	}tsal_7a_       7a}alt__s       _a7_last}       s__tla}a7
Top	erocsh6ih       6ceisrhho       hi6hscore       ohhrsiec6
Bottom	e_4wks_le       _welk_es4       el_skw4_e       4se_klew_

The following “words” jumped right out at us:

hi6hscore
_a7_last}
HV20{

The remaining options were quickly tried, and so we got the following flag:

HV20{no_sle3p_since_4wks_lead5_to_@_hi6hscore_a7_last}

Today’s source code is a bit longer than the others, which is why it is zipped here:

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *