CodeGate 2012 Quals – misc #4

Für die Aufgabe 4 der Kategorie “misc” gibt es keine Beschreibung oder Hinweise darauf, was als Lösung erwartet wird, sondern nur einen Link zu einer ZIP-Datei. Das Ziel der Challenge gilt es also selbst heraus zu finden.

Nachdem die Datei entpackt ist, stellt sich der Inhalt zunächst als Webseite dar. Anhand der Bezeichnung “codegate_homepage” kann hier schon vermutet werden, um was es sich wahrscheinlich handeln wird.

rup0rt@lambda:~/codegate_site$ ls -a *
codegate_homepage.htm

codegate_homepage_files:
.                 e_menu_2.gif         e_sub_top_img_2.jpg
..                e_menu_3.gif         inc_left.htm
codegate.css      e_menu_4.gif         inc_right.htm
codegate.js       e_menu_5.gif         main_bg_1.gif
copy_logo.gif     e_menu_6.gif         main_bg_2.gif
e_6.jpg           e_menu_7.gif         Thumbs.db
e_inc_bottom.htm  e_menu_8.gif         top_img.jpg
e_inc_sub_2.htm   e_sub_title_2_2.gif
e_menu_1.gif      e_sub_title_b.gif

Als erstes öffnen wir also die “codegate_homepage.htm” im Browser und verschaffen uns einen Überblick über den Inhalt.

CodeGate CTF 2012 - misc #4 - website

Bei der Webseite scheint es sich um die normale CodeGate-Homepage zu handeln. Auf den ersten Blick erscheint nichts auffällig. Außer dieser Seite scheinen auch keine weiteren Inhalte zu existieren, da die Links weiterhin auf die orginale Webseite im Internet und nicht auf lokale Dateien verweisen.

Auf Grund der nicht vorhandenen Challenge-Beschreibung frage ich mich an dieser Stelle, ob es uns vielleicht gelingt, weiteres Wissen über die Funktionsweise der Webseite in Erfahrung zu bringen, um so zum Beispiel die Aufgabe “misc #4” online auf “erfüllt” zu setzen. Also sehen wir uns als nächstes die Skriptanteile der Webseite in der Datei “codegate.js” an.

Bei dem Javaskript scheint es sich um ganz normale Funktionen zur Organisation der Homepage zu handeln, bis auf einen Anteil, der ganz am Ende der Datei regelrecht ins Auge sticht:

eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/
^/,String)){while(c--){d
[c][/c]


=k
[c][/c]


||c}k=[function(e){return d[e]}];e= function(){return'w+'};c=1};while(c--){if(k
[c][/c]


){p=p.replace(new R egExp('b'+e(c)+'b','g'),k
[c][/c]


)}}return p}('12 7=["108262 116258","","21820142224","23273023221 0292014","31101728182416101817358"];3 2 37(5){5=5[7[0]](/ /15,1);5=5[7[0]](/38/15,0);12 13=5;5=7[1];19( 6=0;6<13[7[2]];6++){5=13[7[3]](6,6+1)+5};12 11=7[1];19(6=0;6<5[7[2] ];6+=9){11+=36[7[4]](33(5[7[3]](6,6+9),2))};34(11)};',10,39,'|||||_ 0x272dx2|i|_0xfd3a|x65||x72|_0x272dx4|var|_0x272dx3|x67|g|x61|x6F|x 43|for|x6E|x6C|x74|x73|x68|x63|x70|x75|x6D|x69|x62|x66|function|par seInt|eval|x64|String|c|t'.split('|'),0,{}))

Die Funktion selbst deutet durch "(p,a,c,k,e,d)" schon an, dass es sich um eine gepackte beziehungsweise verschleierte Funktion handelt, wie sie häufig auch von Malware oder schadhaften Webseiten verwendet wird. Die Idee dahinter ist es, dem Betrachter die eigentliche Funktionsweise des Skriptes vorzuenthalten.

Da es sich bei Javaskript aber nunmal um eine Klartext-Sprache handelt, ist es durch Interpretationen, Auswertungen und Ersetzungen immer möglich, jede Funktion in für Menschen gut lesbarem Javaskript-Code darzustellen. Mit dem online Javaskript-Unpacker/Deobfuscator Javascript Beautifier lässt sich der Code in einer ersten Stufe entpacken.

function c(_0x272dx2) {
  _0x272dx2 = _0x272dx2['replace'](/ /g, 1);
  _0x272dx2 = _0x272dx2['replace'](/t/g, 0);
  var _0x272dx3 = _0x272dx2;
  _0x272dx2 = '';
  for (i = 0; i < _0x272dx3['length']; i++) {
    _0x272dx2 = _0x272dx3['substring'](i, i + 1) + _0x272dx2
  };
  var _0x272dx4 = '';
  for (i = 0; i < _0x272dx2['length']; i += 9) {
    _0x272dx4 += String['fromCharCode'](parseInt(_0x272dx2['substring'](i, i + 9), 2))
  };
  eval(_0x272dx4)
};

Mit einigen zusätzlichen VI-Kommandos im Stil "%s:/_0x272dx2/param/g" lassen sich nun anschließend noch die Variablennamen ersetzen, so dass dieser Code entsteht:

function c(param) {
  param = param['replace'](/ /g, 1);
  param = param['replace'](/t/g, 0);
  var temp = param;
  param = '';
  for (i = 0; i < temp['length']; i++) {
    param = temp['substring'](i, i + 1) + param
  };
  var result = '';
  for (i = 0; i < param['length']; i += 9) {
    result += String['fromCharCode'](parseInt(param['substring'](i, i + 9), 2))
  };
  eval(result)
};

Das Skript scheint also eine Zeichenkette zu erwarten, in der zunächst alle Leerzeichen und Tabs durch Einsen und Nullen ersetzt werden. Danach wird die Reihenfolge der Zeichenkette umgekehrt, bevor letztendlich ein finaler Rückgabe-String erstellt wird. Dieser ergibt sich aus der binären Interpretation der Einsen und Nullen ( parseInt("", 2) ) deren Integer-Werte dann als Zeichen gedeutet werden ( String.fromCharCode() ).

Nachdem nun klar wäre, was die gepackte Funktion tut, bleibt die Frage, welchen Parameter wir übergeben müssen um (vielleicht) das Schlüsselwort zur Lösung der Challenge zu erhalten. Möglicherweise bietet uns die mitgelieferte Webseite ja weitere Informationen. Wir prüfen mal, ob und wenn ja, an welcher Stelle die Javaskript-Datei verwendet wird.

rup0rt@lambda:~/codegate_site$ grep -r codegate.js *
codegate_homepage.htm:<script src="./codegate_homepage_files/codegate.js" type="text/javascript"></script>

Okay, der Javaskript wird also nur in der Hauptseite der Homepage eingebunden. Um zu sehen, was dort geschieht, werfen wir einen Blick in den HTML-Quelltext dieser Seite. Anfangs scheint es sehr verwunderlich, dass, obwohl eine Javaskript-Datei eingebunden wurde, keine Javaskript-Funktionen daraus verwendet werden. Bei genauer Betrachtung des HTML-Dokumentes fallen allerdings die vielen Leerzeilen am Ende auf. Sieht man sich nun die letzte Zeile an, findet man doch einen Funktionsaufruf, nämlich:

Also wird die Funktion "c" direkt verwendet und hier mit vielen Leerzeichen und Tabs aufgerufen. Um zu sehen, was bei Ausführung passieren würde, kopieren wir die Funktion "c" sowie deren Parameter mit Tabs und Leerzeichen kurz in eine eigene HTML-Datei. Die "eval"-Routing der c-Funktion wird durch "alert" ersetzt um das Ergebnis direkt sehen zu können. Die Ausgabe liefert:

if(new Date().getTime()>1330268400000){
  var dummya = '1';
  var dummyb = '1';
  var dummyv = '1';
  var dummyc = '1';
  var dummys = '1';
  var dummyae = '1';
  var dummyasefa = '1';
  var dummeya = '1';
  var dummya = '1';
  var dum3mya = '1';
  var dumm54ya = '1';
  var dumm3ya = '1';
  var dum1mya = '1';
  var p = 'YTK4YPT1YK48PTK48TK34PTYK6TDKT5P2KT73TKPY4TBTK3TT4YKT4ETK4YTP7K4T6KT30TKYP7T2KYT33TKP7TY6KTYP33TKPY7PT2YT';
  p = p.replace(/T/g,'').replace(/P/g,'').replace(/Y/g,'').replace(/K/g,'%');
  var authkey = unescape(p);
}

Bei Übergabe der Zeichenkette entsteht also ein weiterer Javaskript-Code, der allerdings nur zu einer bestimmten Zeit zur Ausführung gebracht werden soll. Dieser verwendet jede Menge "dummy"-Variablen, die, wie deren Bezeichnung schon aussagt, hier keinerlei Bedeutung haben. Das interessante ist die Variable "p", die relativ kryptisch aussieht sowie die Buchstabenersetzungen, die darin vorgenommen werden, in deren Folge eine URL-kodierte Zeichenkette entsteht. Ohne uns weiter mit dem Code beschäftigen zu wollen, kopieren wir auch diesen in eine eigene HTML-Datei, entfernen die if-Bedingung und versehen ihn mit der Funktion "alert(authkey)". Beim Aufruf unserer HTML-Seite erhalten wir:

CodeGate CTF 2012 - misc #4 - solution

Die Antwort lautet also "AHH4mRsK4NGF0r3v3r".

Leave a Reply

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