Beim Aufruf der Webseite der “huge.js” – Challenge erschien nach unwesentlicher aber bemerkbarer Wartezeit dieses Bild mit einer eingeblendeten Inputbox. Der Quellcode erstaunlich einfach gestrickt:
<body> <div id="panel"> </div> <script src="huge.js" language="javascript"></script> </body>
Klarer Fall, erstmal die Ressource huge.js runterladen … erster Schock – 25 MB komprimiertes Javascript 🙂 Na danke!
Dateianalyse via “SharpEye-Methode” ergab, dass es sich um ein paar wenige Byte JS-Code, dann 99,9999% Hexkrams und ein paar schließende Klammern am Ende der Datei handelte.
Naja, die erste Maßnahme war dann einfach mal den Code zu minimieren, dazu einfach die ersten Zeilen extrahiert und dann noch die letzten Zeilen und hoffen, dass nicht zwischendrin noch ein oder mehrere Codeblöcke sind (kann man aber mit cat huge.js | xxd –c 60 | less wunderbar durchscrollen 🙂
Raus kam dann erstmal das hier, was ja schonmal ganz nett aussieht.
Bettet man den um den HEX-Krams erleichterte Quellcode dann in ein HTML Dokument small.html ein, dann erhält man zunächst tatsächlich ein valides Dokument mit JS bestehend aus zwei Funktionen d() und x(). Beim Aufruf der Seite erfolgt keinerlei Ausgabe. Fügt man ein document.write(o); in Zeile 12 hinzu, sollte es eigentlich zu einer Ausgabe kommen – wenn man nicht gerade Firebug laufen hat… naja, ein Auskommentieren des Funktionsaufrufs von d() und endlich ist auch etwas das nach weiterem Quellcode aussieht zu erkennen.
Wiederholt man den ganzen Vorgang und schneidet die 24,99999MB Hex nicht aus wird dieser Code erzeugt:
Auf den ersten Blick ein wenig enttäuschend, da es sich wieder um ganz viel hässlichen Hex-Krams handelt. Allerdings fällt auf, dass der Code sich verändert hat und nicht mehr die selbe Struktur wie vorher aufweist (hierbei handelte es sich um nen Packer, hab ich aber so nicht sofort erkannt …. )
Scrollt man wieder bis ans Ende, “dadaaaa”:
– endlich mal richtiger Code zu sehen! Wieder selbes Spielchen wie vorher, Dateianfang und Dateiende extrahieren, das ganze lesbar machen durch Einrückungen etc. Nach ner halben Ewigkeit kommt dann die huge_unpacked.js dabei raus, bestehend aus etlichen Funktionen mit ganz viel Cryptovodoo.
Interessant sind aber eigentlich nur die letzten Zeilen, die Ausgabe der Inputbox und die Validierung der Eingabe.
/* * Password checking routine * charset: 0-9a-zA-Z<>(){}-+ */ function unlock(node) { var code = node.value; if (code && (code.length == 5)) { if ( (xxx(code).substr(0,16)=='b3336efd42e29780') && (xxx(kkk(code)).substr(16,16)=='261804c5f2f0a47e') ) { var flag = document.createElement('span'); var t = document.createTextNode('YAY, you got the flag ! --> '+xxx(code)); flag.appendChild(t); flag.style.font='Helvetica, 1.2em, bold'; document.getElementById('panel').appendChild(flag); node.style.display = 'none'; node.value = ''; } } } /* Create an input box */ var pwd = document.createElement('input'); pwd.setAttribute('type','text'); pwd.setAttribute('value','Enter the unlock code here ...'); document.getElementById('panel').appendChild(pwd); pwd.addEventListener('keyup', function() { var t=pwd; unlock(t) }, false);
Bei jedem Tastendruck wird die Funktion unlock() mit dem Inhalt der Inputbox aufgerufen, wenn der Inhalt die Länge 5 hat, dann wird ein Hash aus dem Code mittels der Funktionen xxx und kkk erzeugt und wenn der mit dem hart-codierten Wert übereinstimmt, dann gib den Hash in dem DIV-Container aus, den man dann hoffentlich auf der Webseite eintragen kann …
Aus dem Kommentar geht der erlaubte Zeichensatz für den Code hervor :
0-9a-zA-Z<>(){}-+
Bevor man jetzt sich großartig mit dem Hashalgorithmus beschäftigt, kurz mal nachrechnen:
26+26+10+8 = 70 Zeichen ^5 Stellen = 1.680.700.000 Möglichkeiten
Folgerung: das dürfte schneller ge-BruteForced sein als alles andere und sogar mit JavaScript sollte das nicht zu lange dauern
Kurze Cracking-Routine dazu direkt in das Dokument rein (ctf.html) führt dann irgendwann nach gar nicht so langer Zeit zum gewünschten Ergebnis „code == i<C3Js“
Okay, ich geb zu: die Routine is shaise, aber ich war jung und brauchte das Geld …
Besonderheit: Bei Firefox gab es Probleme mit der Skriptausführung, nur die JS-Engine von Opera war in der Lage die Jquery-Get Requests abzusetzen, wärend der Cracker lief.
Die Sources gibts hier: files