NcN 2013 CTF Quals – Level 1

NcN 2013 Qualification - Level 1 - Task Description

To get the key for “Access Level 1” we need to pass an authentication form. When trying to submit a key, we get the following reply:

NcN 2013 Quals - Level 1 - Invalid Password

So we need to have a look into the source code of the password validation functions. At first we are going to see the HTML lines (index.php). The interesting ones are these:

<script type="text/javascript" src="crypto.js"></script>

<form action="login.php" method="POST" onsubmit="return encrypt(this);">
  <input id="key" type="hidden" name="key" value="" />
  <input id="verification" type="hidden" name="verification" value="yes" />
</form>

As we can see the page uses an external JavaScript file to calculate the validation of the password. Next step will be to examine this script file (crypto.js). It looks like this:

var _0x52ae=["\x66\x20\x6F\x28\x38\x29\x7B\x63\x20\x69...
...,"\x67"];eval(function (_0x7038x1,_0x7038x2,_0x7038x3..
...toString(36));};if(!_0x52ae[4][_0x52ae[6]](/^/,String)..
...[0],46,46,_0x52ae[3][_0x52ae[2]](_0x52ae[1]),0,{}));

The JavaScript itself uses many “eval” (evaluation) functions, confusing variable names and is incredible obfuscated at all. It cannot be read this way! So we need make it readable again – at best evaluate the “eval” function to get the real plain source code. It very good way to do so is using raw SpiderMonkey – the Mozilla JavaScript engine:

Continue reading

DEF CON CTF 2013 – rememberme

DEFCON CTF 2013 - rememberme - task description

Diese Challenge (rememberme) nennt wieder nur eine Webseite, die wir für einen ersten Eindruck direkt besuchen.

DEFCON CTF 2013 - rememberme - website

Die Seite selbst verlinkt zwei Dateien und bietet einen Login an, den wir jedoch ohne Zugangsdaten nicht nutzen können. Beim Aufruf der Datei “usernames.txt” kann man folgendes erkennen:

DEFCON CTF 2013 - rememberme - usernames.txt

Neben den Benutzernamen fällt hier jedoch besonders die URL mit dem Parameter “accesscode” auf. Der Hash-Wert dieses Parameters entspricht im vorliegenden Fall, der folgenden Berechnung:
Continue reading

Boston Key Party CTF 2013 – MITM

Boston Key Party CTF 2013 - MITM - task description

Ohne weitere Informationen erhalten wir bei dieser Challenge (MITM) nur eine Textdatei, die folgenden Inhalt besitzt.

message 1:  QUVTLTI1NiBFQ0IgbW9kZSB0d2ljZSwgdHdvIGtleXM=
encrypted:  THbpB4bE82Rq35khemTQ10ntxZ8sf7s2WK8ErwcdDEc=
message 2:  RWFjaCBrZXkgemVybyB1bnRpbCBsYXN0IDI0IGJpdHM=
encrypted:  01YZbSrta2N+1pOeQppmPETzoT/Yqb816yGlyceuEOE=
ciphertext: s5hd0ThTkv1U44r9aRyUhaX5qJe561MZ16071nlvM9U=

Demnach handelt es sich offensichtlich um drei Nachrichten, von denen die ersten beiden in Klar- und Schlüsseltext vorliegen. Die letzte Nachricht (ciphertext) liegt nur in verschlüsselter Form vor, was diese zum primären Ziel der Challenge macht.

Zunächst sehen wir uns die Klartexte der beiden Nachrichten indem wir sie mit BASE64 dekodieren.

rup0rt@lambda:~/BkP2013$ echo "QUVTLTI1NiBFQ0IgbW9kZSB0d2ljZSwgdHdvIGtleXM=" | base64 -d
AES-256 ECB mode twice, two keys
rup0rt@lambda:~/BkP2013$ echo "RWFjaCBrZXkgemVybyB1bnRpbCBsYXN0IDI0IGJpdHM=" | base64 -d
Each key zero until last 24 bits

Wir erhalten zwei Hinweise:

  • Zum Verschlüsseln der Nachrichten wurde zweifachse AES-256 ECB verwendet
  • Der Schlüssel besteht jeweils aus Nullen – bis auf die letzten drei Zeichen

Continue reading

EBCTF Teaser 2013 – CRY100

EBCTF Teaser 2013 - Cry100 - task description

Bei der CRY100 (“Espionage”) Challenge erhalten wir den Auftrag, Nachrichten zu entschlüsseln. Als Ressourcen wird uns dafür ein Archiv bereit gestellt, das wir direkt entpacken.

cry100_espionage/
cry100_espionage/crypto.py
cry100_espionage/msg001.enc
cry100_espionage/msg002.enc
cry100_espionage/README

Wir erhalten ein Python-Skript, zwei verschlüsselte Nachrichten und einen Hinweis-Text, der wie folgt lautet:

We suspect an employee of one of the embassies has leaked
confidential information to a foreign intelligence agency.

We've managed to capture an individual whom we assume to be the
recipient of the info. Our forensics department has managed to
recover two messages from his outbox, which appear to be encrypted
using some crypto tool. Along with each email our suspect also
received an SMS message containing a password, however we were
only able to recover one - "SieR1mephad7oose".

Could you help us decrypt both messages?

Eine Nachricht konnte demnach offenbar bereits entschlüsselt werden, um die zweite müssen wir uns selbst kümmern. Zunächst testen wir, ob das mitgelieferte Python-Skript die Nachricht wirklich entschlüsseln kann und das darin enthalten ist.
Continue reading

EBCTF Teaser 2013 – WEB200

EBCTF Teaser 2013 - WEB200 - task description

Diese Challenge (WEB200 – “Wooden Shoes”) war umfangreicher als zuerst erwartet. Alles beginnt mit einer kurzen Beschreibung und der Benennung einer Webseite.

EBCTF Teaser 2013 - WEB200 - Wooden Shoes website

Wir finden eine Webseite vor, auf der Schuhe gesucht und bestellt werden können. Dem ersten Eindruck nach werden wir eine SQL-Injection oder ähnliches durchführen müssen. Beim Versuch, Sonderzeichen in das Suchfeld einzufügen, erhalten wir jedoch, diese Ausgabe:

EBCTF Teaser 2013 - WEB200 - sql injection error

So kommen wir also nicht weiter.
Continue reading

ForbiddenBITS CTF 2013 – Old

ForbiddenBITS CTF 2013 - old - task description

Wie gewohnt ist Weniger auch diesmal Mehr und wir erhalten als Aufgabe (old) nur einen Kommentar, dass es sich um einen “scheinbaren binären Auftrag” handelt. Zusätzlich wird eine Datei zum Download bereit gestellt.

Die erste Betrachtung mit dem Werkzeug “file” um festzustellen, um was für einen Typ von Datei es sich in Wirklichkeit handelt, liefert:

rup0rt@lambda:~/FB2013/old$ file bin.bin
bin.bin: x86 boot sector, code offset 0x6e

Uns liegt also ein bootbares Image vor, das durch Übergabe an einen Emulator, wie QEMU gestartet werden könnte. Da die Datei allerdings nur 512 Bytes groß ist und das simple Starten per Emulator ohnehin nicht die Flagge liefern wird, sehen wir uns direkt etwas genauer an. Zunächst prüfen wir, welche Zeichenketten enthalten sind:

rup0rt@lambda:~/FB2013/old$ strings bin.bin
Password: 
,jNice, 16bits world is nice :D. Validate using that password :)
No :(, try again.

Offensichtlich scheint eine Passwortabfrage implementiert zu sein, die abhängig von der korrekten Eingabe eine positive oder negative Rückmeldung erzeugt. Unser Ziel zur Lösung der Challenge wird es also sein, an genau dieses Passwort zu gelangen.
Continue reading

ForbiddenBITS CTF 2013 – X95

ForbiddenBITS CTF 2013 - X95 - task description

Zum Lösen dieser Challenge (X95) muss der Aufgabenstellung nach ein Passwort angegriffen und anschließend offensichtlich auf dem Zielsystem unter Port 3002 eingegeben werden. Zusätzlich erhalten wir den Quellcode des Dienstes, der auf dem System lauscht.
Bevor wir uns überhaupt mit dem Server verbinden, sehen wir uns das mitgelieferte Perl-Script an. Folgende Funktionsweise ist darin implementiert:

#!/usr/bin/perl
use IO::Socket;
my $welcome_msg = <<"EOT";
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 _    _  95   _________   ______   ______  _    _  _____  ______   ______
\\ \\  / /     | | | | | \\ | |  | | | |     | |  | |  | |  | |  \\ \\ | |
 >|--|<      | | | | | | | |__| | | |     | |--| |  | |  | |  | | | |----
/_/  \\_\\     |_| |_| |_| |_|  |_| |_|____ |_|  |_| _|_|_ |_|  |_| |_|____

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

EOT

$|=1;
$lis = IO::Socket::INET->new (
  LocalPort =gt; 3002,
  Type =gt; SOCK_STREAM,
  Reuse=> 1,
  Listen => 1000
) or die "Error #1 $@\n";

Das Skript definiert zunächst eine Willkommens-Nachricht und öffnet einen Socket, der auf Port 3002 lauscht.

while( $c = $lis->accept() ) {
  if ($pid=fork) {
    next;
  } else {
    unless (defined $pid) { die "Threads problem $! \n"; }
    $flag="";
    print $c $welcome_msg."\n\n";

    [... siehe nächster Auszug ...]

  }
   exit;
}
close $lis;

Anschließend wird die eigentliche Hauptschleife erreicht, die für jede Verbindung einen neuen Thread erstellt, die Variable $flag defininiert – die hier, anders auf dem Zielsystem laufenden Dienst, leer ist – und die Willkommensnachricht ausgibt. Was passiert nun genau, wenn ein Client sich zum Server verbindet?
Continue reading

CScamp 2012 Quals – Crypt 300

CScamp CTF 2012 - Crypt 300 - task description

Bei dieser Challenge (Crypt 300) sollen wir den originalen Schlüssel zu einem Schlüsseltext bestimmen. Wir erhalten dazu das Verschlüsselungsprogramm, ein Linux 64bit Binary, die Information, dass der Schlüssel alphanumerisch sowie 11 Zeichen lang ist, den Schlüsseltext “7f e7 ff ce 0 98 15 dd 88 fb 6e” und die CRC-XMODEM Prüfsumme 0x8124 des Originalschlüssels.

Zunächst einmal sehen wir uns die Binary genauer an um die Aufgabe etwas besser fassen und das Ziel näher bestimmen zu können:

rup0rt@linux64:~$ ./crypt 111
your encrypted key is : ff ff ff 0 0 0 0 0 0 0 0 
rup0rt@linux64:~$ ./crypt 123456
your encrypted key is : ff 86 89 d3 89 27 0 0 0 0 0 
rup0rt@linux64:~$ ./crypt A A A 
your encrypted key is : 8f 0 0 0 0 0 0 0 0 0 0

Auf den ersten Blick sieht es so aus, dass das crypt-Tool einen Parameter übernimmt, diesen zeichenweise auswertet, dabei das entsprechende Zeichen verschlüsselt und den verschlüsselten Key ausgibt. Wir müssen es demnach schaffen, den originalen Schlüssel (Übergabeparameter) zu finden bzw. so zu wählen, dass der von der Aufgabe geforderte Cipher “7f e7 ff ce 0 98 15 dd 88 fb 6e” entsteht.

Um dies zu erreichen Schreiben wir ein (hier zugegeben sehr unsauberes) Python-Skript, dass den Schlüssel per Brute Force bestimmt:

#!/usr/bin/python

import commands
import re

chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

for c1 in chars:
 if re.match(".* : 7f.*", commands.getoutput("./crypt " + c1)):
  for c2 in chars:
   if re.match(".* : 7f e7.*", commands.getoutput("./crypt " + c1 + c2)):
    for c3 in chars:
     if re.match(".* : 7f e7 ff.*", commands.getoutput("./crypt " + c1 + c2 + c3)):
      for c4 in chars:
       if re.match(".* : 7f e7 ff ce.*", commands.getoutput("./crypt " +c1+c2+c3+c4)):
        for c5 in chars:
         if re.match(".* : 7f e7 ff ce 0.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5)):
          for c6 in chars:
           if re.match(".* : 7f e7 ff ce 0 98.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6)):
            for c7 in chars:
             if re.match(".* : 7f e7 ff ce 0 98 15.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6+c7)):
              for c8 in chars:
               if re.match(".* : 7f e7 ff ce 0 98 15 dd.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6+c7+c8)):
                for c9 in chars:
                 if re.match(".* : 7f e7 ff ce 0 98 15 dd 88.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6+c7+c8+c9)):
                  for c10 in chars:
                   if re.match(".* : 7f e7 ff ce 0 98 15 dd 88 fb.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6+c7+c8+c9+c10)):
                    for c11 in chars:
                     if re.match(".* : 7f e7 ff ce 0 98 15 dd 88 fb 6e.*", commands.getoutput("./crypt " +c1+c2+c3+c4+c5+c6+c7+c8+c9+c10+c11)):
                      print c1+c2+c3+c4+c5+c6+c7+c8+c9+c10+c11

Continue reading

Nuit du Hack 2012 Quals –
Unknown text

Nuit du Hack 2012 - Unknown text - task description

Zu Beginn dieser Challenge (Unknown text) erhalten wir eine Email von Jessica, die uns mitteilt, dass sie einen unverständlichen -möglicherweise verschlüsselten- Text erhalten hat und beauftragt uns damit, weitere Informationen aus diesem Text zu gewinnen und im besten Fall zu entschlüsseln.

Ein ersten Blick auf den Text lässt uns sofort folgendes feststellen:
– bei den Buchstaben des Textes handelt es sich ausschließlich um Kleinbuchstaben
– die Verteilung der Leerzeichen zeigt, dass nur die Buchstaben verschlüsselt wurden
– die Sonderzeichen im unteren Teil lassen einen Quellcode (Assembler?) vermuten

Mein erster Gedanken bei solchen Texten geht immer in Richtung Caesar-Verschlüsselung und obwohl Wörter wie “nrnvlqqq” schon vermuten lassen, dass es sich nicht um Caesar handelt (da sonst wieder ein Wort mit drei gleichen Buchstaben am Ende entstehen würde) probieren wir es dennoch aus.
Continue reading

CodeGate 2012 Quals – misc #1

CodeGate CTF 2012 - misc #1 - task description

Die Aufgabenstellung (misc #1) ist mal wieder recht unklar. Das 35mb-Zipfile zu durchsuchen würde jedenfalls in echte Arbeit ausarten. Also sehen wir uns zuerst den Text der Aufgabenstellung an und versuchen diesen zu dechiffrieren.

“Az hrb eix mcc gyam mcxgixec rokaxioaqh hrb mrqpck gyam lbamgarx oatygqh Erxtoigbqigarx Gidc hrbg gasc gr koaxd erzzcc zro i jyaqc Kr hrb ocqh rx Ockubqq ro Yrg man? Gyc ixmjco am dccqihrbgm”

Was sofort auffällt ist:
– es sind Satzzeichen vorhanden
– teilweise beginnen die “Wörter” mit Großbuchstaben
– einige Zeichenketten wiederholen sich (z.B. “hrb”)

Es liegt also nahe, dass es sich um einen Caesar-Chiffre handelt. Das testen wir an den ersten Wörtern kurz durch:

rup0rt@lambda:~$ for i in {1..25}; do caesar $i < first.plain; done
Ba isc fjy ndd hzbn
Cb jtd gkz oee iaco
Dc kue hla pff jbdp
Ed lvf imb qgg kceq
Fe mwg jnc rhh ldfr
Gf nxh kod sii megs
Hg oyi lpe tjj nfht
Ih pzj mqf ukk ogiu
Ji qak nrg vll phjv
Kj rbl osh wmm qikw
Lk scm pti xnn rjlx
Ml tdn quj yoo skmy
Nm ueo rvk zpp tlnz
On vfp swl aqq umoa
Po wgq txm brr vnpb
Qp xhr uyn css woqc
Rq yis vzo dtt xprd
Sr zjt wap euu yqse
Ts aku xbq fvv zrtf
Ut blv ycr gww asug
Vu cmw zds hxx btvh
Wv dnx aet iyy cuwi
Xw eoy bfu jzz dvxj
Yx fpz cgv kaa ewyk
Zy gqa dhw lbb fxzl

Ein normales Verschieben der Buchstaben führt also in keinem der 25 Möglichkeiten zu einem sinnvollen Ergebnis. Auch wenn der Text sehr kurz ist, führen wir zunächst eine Analyse der Buchstaben-Häufigkeiten durch.
Continue reading