Meeting
De meeting was een tikje bijzonder: er was geen spoor te bekennen van inleiding of verhaal, alleen de basisregels werden even aangestipt. Het grootste deel van de tijd konden we ons vermaken met het kijken naar de organisatie die lappen stof voor ons doormidden aan het scheuren was.
Wel was er een raar blauw-gewenkbrouwd persoon, die niets zei, ons niet leek te begrijpen, maar wel van alles bekeek.
Puzzel 1: Easy..
Op de meeting kregen we een envelop (nouja, kregen…. “Alle teams mogen een envelop pakken. Er is nu 5 minuten rust!”) waarna we in alle haast naar HQ moesten om deze op te lossen.
Het bleek een soort woordzoeker te zijn. Na het opzoeken van de woorden (http://warp.byu.edu/cgi-bin/wordsearch.py hielp een beetje) gingen we maar eens de overgebleven tekens markeren. Na een minuut of wat werken bleek dat de woorden in het begin (SXPXIXEXGXEXLXOXOXSXTX) ook meteen de enigen waren. Hoe je dit ontcijfert behoeft geen uitleg.
Typisch aan deze puzzel was dat dit niet de enige tekst was die in de puzzel zat: na het gedeelte SXPXIXEXGXEXLXOXOXSXTX ging het nog een stukje verder met letters. De totale tekst kwam uit op:
sxpxixexgxlxoxoxsxtqeyahwaeqnewqqssxrlesbfrgongzcyglldkckpzpjmkhrqzutxybdtplwdcjdlyvfzblplfqhuicnhkmswljmsjcajudgaeiezfstjccsryntojkytoldomdwaglmbxnjeibqzlowlsygwvowxoggpesidphhplpetrxhoblzrjayzhz
Aangezien je uit het gedeelte van de tekst voorbij “spiegel oost” niet veel meer kan halen dan een plaatsnaam uit Wales, en dat toch net iets te ver fietsen is voor dit spelletje, besloten we toch gewoon bij de Spiegel te gaan kijken.
Puzzel 2: Breinmeester
Het bleek helaas erg moeilijk om de puzzel te vinden. Waarschijnlijk kwam dit door de combinatie van twee feiten:
- We stuurden Koprol en On a roll op pad, twee pandora-maagden
- Tijdens de intro-meeting was de organisatie niet in staat een voorbeeldpuzzel te laten zien
Deze combinatie zorgde ervoor dat het away-team eigenlijk niet wist waar ze naar zochten, en dat is natuurlijk niet handig. Na geruime tijd vonden we de puzzel toch.
Op de link (mirror op http://www.rolstruik.nl/2013/breinmeester/) vonden we een spelletje mastermind, dat volledig in javascript draaide. Onderin stond een stuk dat eruitzag als base64, maar niet geldig gedecode kon worden. Waarschijnlijk dat de juiste tekst hier tevoorschijn zou komen als je de puzzel opgelost had. Maar goed, als het in javascript draait kunnen we vast ook iets makkelijkers bedenken dan het daadwerkelijk oplossen in maximaal 10 stappen.
De gegeven javascript-code was erg lelijk, waarschijnlijk bewust. Gelukkig bestaat er een tool om dat soort dingen te fixen. En met de redelijk leesbare versie van de code viel er opeens een stuk meer te doen.
De eerste regel die opviel was de volgende:
document.getElementsByClassName("tries")[0].innerHTML = 10 - j
Dus het aantal beurten dat je al gespeeld hebt wordt opgeslagen in de variabele j. Men zou er vast geen rekening mee gehouden hebben dat die aangepast kan worden. Met grote dank aan de auteurs van FireBug konden we het volgende statement uitvoeren:
j = -9000;
En warempel, opeens hadden we over 9000 pogingen ter beschikking en was het slechts een kwestie van geduld om de juiste oplossing te vinden.
We hadden de oplossing daarna natuurlijk in een poging of 15, want wie heeft er nou zin na te denken over de meest optimale strategie, maar er moest natuurlijk toch even verder gekeken worden of het nog verder gehackt kon worden. Een ander iets dat opviel was de definitie van een aantal JSON-objecten die aan de naamgeving te oordelen te decrypten moesten zijn.
var k = ['{"iv":"N+UxOCuMieTsk4677r/07w","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"bDGSqwnN0KU","ct":"oNk+UJQWoHZ8I3q5EYPen+pDcgbRAL97HDQu6A"}', '{"iv":"QbBjHJPzlj+LRn0zxyzsow","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"xYzAY1oU8gU","ct":"INd4Mn2RnN9Htvn+vhRHLUN8pBWrCqLnG2Tkig"}', '{"iv":"Twur/sUUCYLA9EP16Lhs0A","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"YRdSzNJP39s","ct":"74I0VvKMjN+umWL4QtPmcLdTkhFxTBxRwT97Yg"}', '{"iv":"gkzTRB0sp4cAHS6aHjxKFQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"n3fL08CEuhE","ct":"KcepVcz1l82xAlR9awQa70SaiybKUVSQDTHYxQ"}', '{"iv":"EajplerJEvndaEOu2x5pmg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"VpC38c0OT54","ct":"L9+/O/XDQrTKmm3MLvXk2Br/zj8R3mGYdYGx/w"}', '{"iv":"SgAXeYjlk6u/ZS4uMG4vWQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"2L4ndNb7TcM","ct":"IMmCJsUtsPiq/phtnK0a1HC2nl+r1LaVBRfj5H7zXwbp9RwkMiR3u3yY+6A"}'];
Het valt hierbij op dat het vijfde element een stuk langer is dan de rest. Het laat zich dan ook raden dat het juiste antwoord verstopt zit in dit element. Wederom vormde Firebug een welkome hulp
>>> sjcl.decrypt(m[5], k[5]) "De volgende puzzel is bij de Sleutel"
En eigenlijk wisten we dat ook wel voordat we de puzzel opgelost hadden, de Sleutel is natuurlijk gebouw 58 en tijdens de meeting werden we al erg gehint op dat gebouwnummer.
Puzzel 3: Find a, b, c
Puzzel 3 vonden we wat sneller, al keken we ook hier in eerste instantie straal overheen. Er stond iets in wat overduidelijk een md5-hash was, dus die ging meteen google in, met als resultaat ‘1337’. Achteraf gezien is google natuurlijk een prima ‘overpowered_decoder’ zoals vermeld in de puzzel, maar die denkstap sloegen we eigenlijk over. Hiermee waren a=1, b=2 en c=4 snel duidelijk.
De rest van de puzzel duurde iets langer. We probeerden het als een lijst met waarheids-statements te behandelen, maar aangezien er dan het e.e.a. aan tegenspraken in bleek te zitten moesten we dat toch maar verwerpen. We zaten nog een tijdje vrolijk vast, totdat Rick besloot dat het wel een goed idee was te doen alsof elke regel een lijn op een grid was, waarbij de het bereik van x of y een lijn betekende. Het uittekenen hiervan leverde al snel een set lijnen op die vrij duidelijk op CU ging uitkomen.
Het duurde nog even voordat we bedachten dat de ‘assignments’ die ontbraken simpelweg gekopieerd konden worden van de regels erboven, waarmee het plaatje compleet werd. Op naar de Cubicus.
Puzzel 4: FIXEls
On a Roll en Rick kwamen bij Cubicus aan, liepen het hoekje om en vonden direct de puzzel. Voor het thuisteam begon nu de eerste uitdaging: de foto ontcijferen: stond er nou Fixels (met een el) of Fixeis (met een ie)? Na 2 keer proberen had men de goede URL te pakken: http://iapandora.nl/puzzel/FIXEls/puzzel_echt.jpg
Het leek alsof deze puzzel uit een leeg plaatje bestond. Ervaring uit het verleden deed ons echter anders vermoeden: er zou wel een verborgen boodschap in het plaatje verborgen zijn.
Als eerste werd het plaatje door een hexdump gesmeten. Dit leverde al direct resultaat op:
Hexdumpen kan ook, maar... :p
We hielden rekening met de mogelijkheid dat we op een dwaalspoor gezet waren. er bleken coördinaten in de EXIF-data te staan (we hebben http://regex.info/exif.cgi gebruikt om deze te achterhalen):
Latitude: N 52° 14' 41.84160000 Longitude: E 6° 50' 46.00679998
Dit kwam vlakbij Logica uit; Rick en On a Roll waren nog in het veld en werden snel die kant op gestuurd.
Een kleine kanttekening voor de organisatie. De Drienerburght, uitbater van zowel Logica als de Drienerburght zelf, vind het voor de gasten niet netjes als er rond deze gebouwen gezocht en/of geschoten wordt. Door een puzzel bij Logica op te hangen is dit wel gebeurd. De puzzel hing ver genoeg weg, maar mensen zijn toch rond (en tussen) de kamers gaan zoeken. Jullie moeten het natuurlijk zelf weten, maar het is niet aan te raden om hier vaker puzzels op te hangen (de ruimtes vallen strikt gezien ook onder horeca, maar hier kan gemakkelijk verwarring over ontstaan tussen teams).
Puzzel 5: Het is niet zeventien.
Bij Logica vonden we de volgende puzzel. Hierop was een functie voor 3 waarden gedefinieerd. De waarden deden suggereren dat de beoogde functie gedefinieerd moest worden als:
f(x) = x / 2
De som eronder was, met deze functie erbij, snel opgelost. Na een paar rekenfoutjes (het was immers een hele moeilijke som!) bleek het antwoord 17 te zijn. Maar… maar… maar… dat kan natuurlijk helemaal niet! De titel vertelt ons overduidelijk dat dat 17 niet het goede antwoord is.
Rick en On a Roll werden terug naar huis geroepen om mee te puzzelen. Daar aangekomen bleek On a Roll on a roll te zijn: hij herkende direct de functie die bedoeld werd:
length("zes") = 3 length("twaalf") = 6 length("acht") = 4
Bij de som eronder moesten we dus de lengte pakken van de woorden “vier”, “twee”, “tien”, “veertien” en “zes”. On a Roll en Rick grijpen hun spullen bij elkaar en verplaatsen zich in snelfietsvaart naar gebouw 31: Windpark.
Puzzel 6: Revolutions, Revelations
Bij het windpark aangekomen lopen On a Roll en Rick naar de noordzijde: de zijde van het windpark die tegen de koeienvelden aan ligt. Met gevaar voor eigen kleding worstelen ze zich tussen de bramen door, op zoek naar de puzzel. Tevergeefs keren ze terug naar de weg.
Op de terugweg vinden ze de puzzel tegen een paaltje aan de westzijde van het windmolenpark. De organisatie zal wel net zo veel moeite hebben met windrichtingen als Rick, die meestal al moeite heeft om links, rechts en rechtdoor uit elkaar te houden.
De puzzel bestaat uit een set led-klokjes (bovenaan) en een dubbele array getallen (onderaan):
[[15,5,6],[15,5,12,7,6,11],[12,15,6,11,9],[5,7,15,6,9],[6,15,9,],[12,15,7,11,9],[5,15,12,11,6]]
De organisatie had vandaag al eerder een puzzel laten uittekenen, dus Duck begon vakjes op een ruitjespapier in te kleuren: op regel 1 werden vakjes 15, 5 en 6 ingekleurd, op lijn 2 werden vakjes 15, 5, 12, 7, 6, 11 en ga zo maar door. Dit leverde een plaatje op waar geen van de teamleden iets van kon maken. Koprol heeft het plaatje op z’n kop bekeken, maar ook dat leverde niks op.
We keken naar de titel: Revelations, Revolutions. Duck dacht aan Matrix Revolutions, Rick aan Assassin’s Creed: Revelations. De tweede suggestie leverde niks op: Revelations was juist de Assassin’s Creed waar geen puzzels in waren verwerkt. Matrix Revolutions leek beter: De reeks met cijfers onderaan leek wel een soort van matrix en de displays bovenaan waren wel een soort matrixborden. Er werd gekeken naar een oplossing in het Matrix-alfabet.
Toen ook dit op niks uit leek te komen (Koprol had het blaadje met dit alfabet 4 keer gedraaid en de tekentjes op elke mogelijke manier met de displays vergeleken), werd verder gekeken: hoe konden de 8 verschillende cijfers onderaan (aldus Duck), de 7 displays bovenaan en de 7 rijtjes onderaan met elkaar gecombineerd worden? Wat was de relatie tussen de dingen onderaan en bovenaan? Na nog een uur staren kwam On a Roll met de verlossende observatie: het waren maar 7 verschillende getallen onderaan.
Wat bleek: de 7 verschillende getallen kwamen overeen met de 7 streepjes van de getallen. Dit was het “oh ja”-moment dat we nodig hadden: On a Roll had 5 minuten later de streepjes allemaal hun eigen waarde gegeven.
De onderste rij getallen kon nu gebruikt worden om nieuwe displays te bouwen: de cijfertjes kwamen overeen met streepjes die opgelicht moesten worden.
De oplossing bleek naar Ravelijn te leiden.
Puzzel 7: Een goed begin is het halve werk
Rick en On a Roll gingen direct op weg naar…. Citadel. Gelukkig zat home team goed op de gps-tracker te letten, dus ze werden prompt ingeseind dat dit toch echt het verkeerde gebouw was. Jammergenoeg waren Rick en On a Roll te druk met zoeken bij het verkeerde gebouw om dat op te merken. Toen ze eenmaal bij het juiste gebouw aankwamen zagen ze de puzzel eigenlijk meteen. Dat was ook niet zo raar: de puzzel was zodanig opgehangen dat elke willekeurige voorbijganger hem kon spotten.
De puzzel bestond uit een lange reeks hexadecimale tekens.
800618943025315f869e4e1f094710120d61f8370cad1d412f80b84d143e1257
On a Roll wist direct op te merken dat de start van deze string overeenkwam met de signature voor een MSDOS-executable. Decompilen leverde een programma op:
add BYTE PTR [esi],0x18 xchg esp,eax xor BYTE PTR ds:0x9e865f31,ah dec esi pop ds or DWORD PTR [edi+0x10],eax adc cl,BYTE PTR ds:0xc37f861 lods eax,DWORD PTR ds:[esi] sbb eax,0xb8802f41 dec ebp adc al,0x3e .byte 0x12 push edi
Als we keken wat dit programma deed, zagen we bij het tweede commando al een actie gebeuren op een willekeurig geheugenadres. Deze oplossing leek niet de goede kant op te wijzen.
Er werd veel gekeken en Rick stack zijn handen in het haar. Hij heeft veel haar, dus hij was zijn handen even kwijt. Na meer dan een uur had Rick zijn handen weer teruggevonden en was de rest nog niet veel verder. Er werd al gesproken over een hint. Van alles was geprobeerd: googlen naar de tekenreeks, de tekenreeks maal twee doen, gedeeld door twee, etcetera.
On a Roll zag plotseling dat, als je naar de halve tekenreeks googlede, je een virusdefinitie voor je neus kreeg:
https://www.virustotal.com/en/file/f67ab10ad4e4c53121b6a5fe4da9c10ddee905b978d3788d2723d7bfacbe28a9/analysis/
Dit zorgde ervoor dat we gingen googlen met de halve tekenreeks: de eerste helft bleek de md5-sum van “F” te zijn, de tweede helft de md5-sum van “C”. Vol goede moed gingen Duck en Rick op weg naar de Faculty Club.
Puzzel 8: (K)nibble Knabbel Knuisje
Bij de Faculty Club hing goed verstopt, totdat de wind het deed opwaaien, de volgende puzzel. Deze puzzel bestond weer uit een URL.
Op de URL stonden een vijftal getallen, de tekst “(K)nibble, knabbel, knuisje, wie past er in mijn huisje?”, een invoerveld en een teller die suggereerde dat we 5 pogingen hadden. Onze eerste ingeving was natuurlijk om naar het javascript te gaan kijken. Helaas was dit er niet, deze puzzel was wel server side. Even staren naar de lijst zorgde niet voor een logisch verband, laat staan voor een hint van het getal dat we moesten hebben. Volgende stap: vul maar een willekeurig getal in, en kijk wat er gebeurt. Dit bleek een onverwacht side-effect te hebben: we kregen te horen wat de oplossing was. Helaas veranderde de lijst met getallen ook meteen, dus we konden hier niets meer mee. We gingen uiteraard gegevens verzamelen: sla de lijst met getallen op, vul iets willekeurigs in en kijk wat de uitkomst was.
Al snel bleek dat de oplossing altijd een van de getallen was. Hiermee was meteen duidelijk waarom er maar 5 pogingen waren die opeenvolgend goed moesten zijn: anders is het triviaal te brute forcen. Ook hier werd een tijdje naar verbanden gestaard, maar er was niets logisch. Het was niet altijd het hoogste getal, laagste getal, even of oneven getal of priemgetal.
Rick kwam ineens op het idee nog eens goed naar de titel en de tekst op de website te kijken, en dan met name (k)nibble. Ineens was ons duidelijk dat er iets met nibbles moest gebeuren. We gingen getallen naar hun binary representatie converteren, en al snel viel Duck op dat het juiste antwoord wel erg vaak leek precies in een willekeurig aantal nibbles, zonder voorloopnullen te vatten. Een rans-script later was de puzzel zo opgelost.
import sys for line in sys.stdin: if not line.strip(): continue frop = len(bin(int(line.strip()))) print '%s %d %d %d' % (line.strip(), frop, frop-2, (frop-2)%4)
De website bevestigde dit al snel met de tekst “5/5 — De volgende locatie is: Sportcentrum — Nice!”
Einde
Bij het sportcentrum vonden we het laatste blaadje van de avond. Op dit blaadje vonden we de volgende tekst:
Project B:12-CZ11 is small, white and leech-like, and probably the oddest thing in the Universe. It feeds on brainwave energy received not from its own carrier but from those around it. It absorbs all unconscious mental frequencies from this brainwave energy to nourish itself with. It then excretes into the mind of its carrier a telepathic matrix formed by combining the conscious thought frequencies with nerve signals picked up from the speech centres of the brain which has supplied them. The practical upshot of all this is that if you stick Project B:12-CZ11 in your mouth you can instantly understand anything in any form of language.
LET OP: Het eerste team dient project B:12-CZ11 mee te nemen naar de meeting morgen voor een bonus.
Duck en On a Roll lopen over het zebrapad bij het sportcentrum terug naar het hoofdkwartier en op het hoofdkwartier zelf wordt alvast een biertje opengeplopt. De eerste dag zit erop.
Gezien ik het tof vindt dat er ook over mijn puzzels geblogged is moet ik toch even reageren.
Wat betreft de breinbrekers puzzel, die was natuurlijk geobfuscate, alle benodigde libraries (sjcl) waren in dezelfde file gestopt. Ik had nooit verwacht dat iemand ook maar zou beginnen aan het lezen van die source. Maar toch, rolstruik is anders :).
De titel van Revolutions/Revelations sloeg inderdaad op The Matrix, maar eigenlijk was dat een veel simpelere hint dan dat jullie doorhadden. Als je aan het zeven segmentsdisplay aan elk streepje een variabele toekent, {a,b,c,d,e,f,g}, dan kom je uiteindelijk op een stelsel van 7 vergelijkingen met 7 onbekenden uit. Die kan je perfect oplossen met een matrix :). Of sterker nog, dat kan wolfram alpha heel goed.
Oh en over FIXEls wou ik ook nog iets zeggen, The Gimp gaf me de mogelijkheid dat veldje te setten, er stond eerst “Created with GIMP”, dus dat moest natuurlijk gebeuren. De titel van de puzzel bevatte natuurlijk ook een hint, als je de eerste vier letters omdraait staat er precies EXIF.