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!
804fa458-c10c-4627-89df-18028bff6efa.zip
Hints:
/^HV20{[a-z3-7_@]+}$/
and is read face by face, from left to right, top to bottom
The file contained a STL 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 bordering 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) depends 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.
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 printed all cube faces, for all reading directions for each step to the screen in which "HV20" occurs. There were many, but we wanted to make sure we didn't miss anything even if our algorithm was off somehow. Fortunately, the following one caught our eye because it read "highscore" for one cube face:
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:
hi6hscore
_a7_last}
HV20{
We manually parsed and assembled the text fragments in front of us to get the following flag:
HV20{no_sle3p_since_4wks_lead5_to_@_hi6hscore_a7_last}
Today's source code is a bit longer than for the other challenges, which is why it is attached as archive here: