VolgaCTF 2013 – ppc 200

volgactf 2013 - ppc 200 - task description

Die Challenge (ppc 200) spricht von einer verdächtigen Nachricht, die uns in Form dieser Datei übersandt wird. “File” meldet, dass die Datei nur aus “Daten” besteht, aber ein erster Blick hinein zeigt uns:

volgactf 2013 - ppc 200 - file encoding

Die Datei beginnt mit den Worten “reverse all” und scheint offenbar von uns zu verlangen, den Inhalt komplett umzudrehen. Dies tun wir auch mit folgendem kleinen Python-Skript:

#!/usr/bin/python

import sys

revstr = "reverse all\x00\x00"

file = open(sys.argv[1]).read()

if file[0:len(revstr)] == revstr:
  file = file[:len(revstr):-1]
  print file

Nach Anwendung auf die Datei und erneuter Betrachtung im Texteditor, finden wir folgenden neuen Dateianfang vor:

volgactf 2013 - ppc 200 - base16 encoding

Dieses Mal soll der Inhalt der Datei offensichtlich mit Base16 dekodiert werden. Auch das setzen wir mit einem Skript, diesmal mit Perl, um:

#!/usr/bin/perl

open(FILE, $ARGV[0]);
@file = <FILE>;
close(FILE);

for ($i=11; $i<=length($file[0]); $i+=2) {
  $double = substr($file[0], $i, 2);
  print chr(hex($double));
}


Erneut werfen wir nach Anwendung des Skriptes einen Blick in die Datei:

volgactf 2013 - ppc 200 - base85 / ascii85 encoding

Wieder “reverse all” und dahinter bereits erkennbar, eine Base85 (auch ASCII85) Kodierung. In diesem Moment stellte ich mir die Frage, ob ein automatisiertes Skript, dass alles selbst erkennen und umsetzen würde vielleicht angebrachter wäre. Der weitere Verlauf, sowie kleinere Probleme bei der Umsetzung in einer vordefinierten Programmiersprache, führten jedoch dazu, jede Operation in ein separates Skript zu implementieren und diese anschließend manuell nacheinander auszuführen.

Nach zweifachem Umdrehen des Textes, war es demnach an der Zeit die Base85 / ASCII85 Dekodierung umzusetzen, was in diesem Skript realisiert wurde – damit es nicht langweilig wird in PHP 🙂 Der Quellcode ist hierbei dem cryptool von ollej entnommen!

#!/usr/bin/php
<?php

//ASCII85/Base85 decode <http://en.wikipedia.org/wiki/Ascii85>
function ascii85decode($str) {
  $newstring = '';
  $whiteSpace = array("\x00","\x09","\x0A","\x0C","\x0D","\x20");
  $str = str_replace('<~','',$str);
  $str = str_replace($whiteSpace,'',$str);
  if(substr($str,-2)!='~>') {
    return '';
  }
  $str = substr($str,0,(strlen($str)-2));
  $dataLength = strlen($str);
  for($i=0; $i<$dataLength; $i+=5) {
    $b = 0;
    if(substr($str,$i,1)=="z") {
      $i -= 4;
      $newstring .= pack("N",0);
      continue;
    }
    $c = substr($str,$i,5);
    if(strlen($c)<5) {
      break;
    }
    $c = unpack('C5',$c);
    $value=0;
    for($j=1; $j<=5; $j++) {
      $value += (($c[$j]-33)*pow(85,(5-$j)));
    }
    $newstring .= pack("N",$value);
  }
  if($i<$dataLength) {
    $value = 0;
    $chunk = substr($str,$i);
    $partialLength = strlen($chunk);
    for($j=0; $j<(5-$partialLength); $j++){
      $chunk .= 'u';
    }
    $c = unpack('C5',$chunk);
    for($j=1; $j<=5; $j++) {
      $value += (($c[$j]-33)*pow(85,(5-$j)));
    }
    $foo = pack("N",$value);
    $newstring .= substr($foo,0,($partialLength-1));
  }
  return $newstring;
}

$data = substr(file_get_contents("$argv[1]"), 11);
$res = ascii85decode($data);
print $res;

?>

Nachdem auch dieser Schritt gegangen wurde, finden wir folgendes am Anfang der Datei:

volgactf 2013 - ppc 200 - replace

Dieses mal müssen also Buchstaben in der Datei mit jeweils anderen ersetzt werden! Auch hierfür schreiben wir ein Perl-Skript:

#!/usr/bin/perl -w

open(FILE, $ARGV[0]);
@input = <FILE>;
close(FILE);

# replace G,g,p,h,K,L,o,q,P,S,O,x,Z
#       ->L,Z,K,o,S,O,G,h,x,q,P,g,p^@^@

foreach $line (@input) {
  for ($i=0;$i<length($line);$i++) {
    $char = substr($line, $i, 1);
    if ($char eq "L") { print "G"; next; }
    if ($char eq "Z") { print "g"; next; }
    if ($char eq "K") { print "p"; next; }
    if ($char eq "o") { print "h"; next; }
    if ($char eq "S") { print "K"; next; }
    if ($char eq "O") { print "L"; next; }
    if ($char eq "G") { print "o"; next; }
    if ($char eq "h") { print "q"; next; }
    if ($char eq "x") { print "P"; next; }
    if ($char eq "q") { print "S"; next; }
    if ($char eq "P") { print "O"; next; }
    if ($char eq "g") { print "x"; next; }
    if ($char eq "p") { print "Z"; next; }
    print $char;
  }
}

close(FILE);

Nach weiteren vier Schritten stoßen wir auf diesen neuen Header:

volgactf 2013 - ppc 200 - base32 encoding

Demnach ist diese Datei nun mit Base32 kodiert und muss entsprechend mit diesem dafür entwickelten Perl-Skript dekodiert werden:

#!/usr/bin/perl

use MIME::Base32 qw( RFC );

open(FILE, $ARGV[0]);
@file = <FILE>;
close(FILE);

$enc = $file[0];
substr($enc, 0, 11) = "";
$decoded = MIME::Base32::decode($enc);

print $decoded;

Nach etlichen weiteren Schritten taucht gelegentlich noch eine Base64 Kodierung auf, die aber problemlos mit dem Linux Konsolenwerkzeug “base64” dekodiert werden kann.

Gefühlte 100 Schritte (insgesamt circa 40) später, stoßen wir auf die letzte Kodierung:

rup0rt@lambda:~/VolgaCTF2013/ppc200# cat next40.txt 
base64encTDByZW1fbHAkdW1fZDAxMHJfJGkrXy9cbWUr

rup0rt@lambda:~/VolgaCTF2013/ppc200# vi next40.txt 

rup0rt@lambda:~/VolgaCTF2013/ppc200# base64 -d next40.txt 
L0rem_lp$um_d010r_$i+_/\me+

Die Lösung lautet somit “L0rem_lp$um_d010r_$i+_/\me+“.

Leave a Reply

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