Monday, June 3, 2013

Codegate 2013 :: Misc #4 (300 points)

This was the 4th challenge under the misc category which was worth 300 points. A zipped file was provided for this challenge with the following hints:
The zipped file contained a single binary file with no extension. TrID was deployed to identify the extracted file based on its binary signature and was found to be a Adobe PDF file. The file was subsequently renamed with .pdf extension to view its contents using Adobe PDF Reader.

Only two words (! Confidential Documents !) were displayed when the PDF file was viewed with Adobe PDF Reader. More efforts were required to look further into the PDF specification which encapsulated a complete description of the fixed-layout flat document, including the text, fonts, graphics, and other information needed to display it. 

The 1st key was found very easily within object 12. 1st_key(nn@LiC!oU$)

Hints for the 2nd key were discovered within object 5.

Hint #1 mentioned the 2nd key is made up of strings contained in three objects. Hint #2 stated the length of the 2nd key is 14. After scanning through the PDF specification, objects 6, 7, and 8 were found to be likely to contain text strings. The following line was amended to replace the digit 5 with 6, 7, and 8, to display contents of each of the objects in turn.

Object 6 :: PpPDdD[

Object 7 :: F_F

Object 8 :: ]ile

With the above strings concatenated, the 2nd_key was obtained! (PpPDdD[F_F]ile) strlen = 14



Careful examination of the data stream within object 11 was needed for the 3rd key. 1101 bytes of data were extracted and saved to a new binary file. The data were then uncompressed using PHP gzuncompress(), displayed, and found to be another PDF file.

PHP Script:

PDF Specification:

The next lead came from the Javascript contained within object 7. Some modifications were made to the script in order to view the alert which read “Decrypt_ME“. The cipher was then changed to “673B672B3E663C666F2B37390D362061″, a string contained within the extracted PDF specification, and the 3rd key was revealed. 3rd_key=4n4ly5i5

HTML with Javascript:

Captured the flag with the 3 keys combined! 300 points in the bag!! Yay!!!
Flag: nn@LiC!oU$_PpPDdD[F_F]ile_4n4ly5i5


Cheers,
Braeburn Ladny

Codegate 2013 :: Misc #3 (200 points)

The 3rd challenge under the Misc category, with a reward of 200 points, got underway with a binary that was identified as a “Wireshark PCAP Next Generation Dump File Format (Little Endian)” file by TrID.

2 hints were given for this challenge:
  1. [Misc3(200) Hint] You can solve the question off-line.
  2. [Misc3(200) Hint] Find out document.
The objective was to find the document in question from the 7161 captured network packets. Thankfully, generating the list of HTTP objects (File > Export Objects > HTTP) and saving them to a local directory was a breeze with Wireshark, and a total of 59 files were exported for analysis.

Sample list of files exported:

When the above selected file was viewed in Adobe PDF Reader, it showed the official rules for Codegate YUT Challenge. However on closer examination in notepad, the PDF specification revealed the file had several incremental updates contained therein, evident by the presence of several “%%EOF” and updated objects content. The key was revealed after the last update was deleted from the PDF specification. Flag captured! 200 points in the bag!! Yay!!!


Cheers,
Braeburn Ladny

Codegate 2013 :: Misc #2 (200 points)

This was the second challenge under the misc category which was worth 200 points. Two files were provided, an encoded key and a source php file. The challenge was to write a decoder function to decode the encoded key.

Contents of source.php:
Several points were gathered from the encoder function:
  1. $enc_tab, an array, comprised of 91 items.
  2. $var1 contained the (shifted) ASCII value of the input character being processed.
  3. $var2 contained the number of bits to be processed.
  4. $var3 contained the working value of $var1.
  5. If $var1 was between 89 and 8191, and $var2 was more than 13, its value would be shifted right by 13 places, otherwise its value would be shifted right by 14 places. 2 characters would be picked from $enc_tab based on the quotient and remainder from the division operation.
With these points in mind, the decoder function was written to be:
Flag captured! 200 points in the bag!! Yay!!!


Cheers,
Braeburn Ladny

Codegate 2013 :: Web #5 (500 points)

This was the fifth challenge under the web category which was worth 500 points. The challenge kicked off with a note that read “connect with mobile”. Connecting to the website with a stock desktop browser showed the following “mobile only” text.


In came the User Agent Switcher browser extension that switched the user agent to “iPhone 4″, deceived this restriction and gained access to the site. Oh yea!


The site was actually a game simulator where you could create your own character by giving it a name. Each character started off with 150 points to be assigned to its 3 attributes (strength, dexterity and intelligence) depending on your preference. I named my character “wolf”.


Examination of the source code revealed two Javascripts and one of them (main.js) contained obfuscated code.

Contents of main.js:

The obfuscated code was easily deobfuscated by http://jsbeautifier.org/ :)

Line 18 of the above code revealed how URLs for each of the 3 pages (home.html, introduce.html, get_tag.html) were formed. The magic embedded within index.php produced wonders when the script was fed with those parameters – the source code was displayed on the screen! Repeated this step for the php pages (simulator.php, simulator_ok.php) and gathered several valuable hints to this challenge.

Contents of simulator.php:
  1. Line 15: if ($_POST['name'] == “GM”) die(“you can not view&save with ‘GM’”);
    There was a restriction with using “GM” as the character name. GM probably stands for Game Master.
  2. Line 17: $db = sqlite_open(“/var/game_db/gamesim_”.$_SESSION['scrap'].”.db”);
    The path to the character database file!
  3. Line 94: memo : <input type=’text’ name=’memo’ value=’<?php if (isset($row[0])) echo gzuncompress($row['memo.memo']); ?>’ maxlength=32 />
    Data contained within memo.memo must be uncompressed.
The search for /var/game_db/gamesim_GM.db was conducted and it was discovered to be an SQLite 2.1 database.


After the SQLite database file was extracted from the response, the next step was to write a script to read the contents from it. Recall from hint #3 above, memo.memo must be uncompressed in order to recover its original data.

Script to read database contents:

Key found! 500 points in the bag. Yay!


Cheers,
Braeburn Ladny

Codegate 2013 :: Web #3 (300 points)

This was the third challenge under the web category which was worth 300 points. The challenge began with a letter addressed to Sherlock Holmes.
The objective of this challenge was to play the role of Sherlock Holmes and to figure out who and when the person asked the hacker group to hack “Hound Co.,Ltd.”.

Examination of the site revealed there was a suspicious Javascript file secret.js which was the first lead gathered for this challenge. However the code was clearly obfuscated as shown below. 

Contents of secret.js:
The obfuscated code was easily deobfuscated by http://jsbeautifier.org/ :)
Line 8 of this Javascript exposed the hidden php file, d56b699830e77ba53855679cb1d252da.php, which was revealed as a popup after the “Grey” logo was clicked for 10 times. In fact this was the login form. The challenge would be to find the login credentials to gain access to the restricted area.

Candy: md5(login) = d56b699830e77ba53855679cb1d252da

Examination of the site did not show any obvious sign of possible SQL injection flaw. Do you know of any tools that can assist you to look for such flaws?



There are several tools that can automate the process of detecting and exploiting SQL injection flaws and sqlmap, an open source penetration testing tool, is the tool widely used for this purpose.

Command used to identify time-based blind sqli with parameter “question”:
Subsequently commands were issued to identify the databases, tables and table entries:
Put the passwords through md5 decrypter to be decrypted:
Logged in with the credentials for victor and solved the mystery! 300 points in the bag. Yay!

Cheers,
Braeburn Ladny

Codegate 2013 :: Web #2 (200 points)

This was the second challenge under the web category which was worth 200 points. It began with a short note from the organizer that read – “One Time Password..?” and a hyperlink to a Ca$h website where Captain Teemo was on duty.


The Ca$h website included the option to generate a One Time Password (OTP) that was needed during login. Option to download the (zipped) source code for the website was also available.

Contents of the zipped file:
  • index.html – Website index page
  • jquery-1.8.3.js – JQuery file
  • main.js – JQuery file
  • images – Folder containing css and image files
  • home.php – Homepage containing some description for the website
  • login.php – Login page
  • login_ok.php – Check the login credentials submitted
  • otp.php – Display the OTP and its validity period
  • otp_util.php – OTP generation page

Contents of “login_ok.php”:
Contents of “otp.php”:
Contents of “otp_util.php”:
From login_ok.php, it appears you need to submit a password value that matches the value generated by make_otp() and “127.0.0.1″ as the ID value in order to capture the flag for this challenge. A closer look at make_otp() reveals the OTP value is a sha1 hash of a string that is formed by concatenating $time (integer value of the current time divided by 20), $user (“127.0.0.1″), and $seed (md5 hash of the flag file contents concatenate with the md5 hash of the user-agent header) together.

One Time Password (Valid for 20 secs)

There are 2 obstacles to overcome. Let’s examine them in details here:
  1. $_SERVER["REMOTE_ADDR"]The IP address from which you are viewing the current page.
    Are you able to spoof this to be “127.0.0.1″?
  2. $_SERVER['HTTP_USER_AGENT']Contents of the User-Agent: header from the current request, if there is one. This is a string denoting the user agent being which is accessing the page.
    Are you able to match whatever string value used by the organizer?
Take a moment to think about overcoming these 2 obstacles and whether there is an alternative approach to this challenge.


  1. $_SERVER["REMOTE_ADDR"] – Even though it is possible to spoof this element with “127.0.0.1″, chances are you will not receive the response as the IP address is used in the IP protocol to route packets.
  2. $_SERVER['HTTP_USER_AGENT'] – It’s anybody’s guess what string was used by the organizer. It may be empty or random.
The 2 obstacles certainly look difficult to overcome. Another approach lies in line 10 of login_ok.php where $_POST["ps"] is compared against $password to determine if there is a match. Comparison between two strings will result in an error when one of the strings supplied is an array. This attack is known as array injection.

Array Injection PHP Script:
When the script (login_ok.php) received this POST request, it ran into an error, rendered the strcpy defunct and echoed the code within the scope of the if statement, together with the contents of the flag file! 200 points in the bag. Yay!

Flag Captured:

Cheers,
Braeburn Ladny

Codegate 2013 :: Web #1 (100 points)

This was the first challenge under the web category which was worth 100 points. It began with a short note from the organizer that read – “Let’s swimming!” and a hyperlink to a member login page which included the option to download the (zipped) source code for the website.


Contents of the zipped file:
  • login.php_files – Folder containing css and image files
  • db_schema.sql – Database schema file
  • login.php.htm – Member login page
  • login_check.php – PHP page to check the ID & password entered against the database entry

Contents of “db_scheme.sql”:

Contents of “login_check.php”:

In order to capture the flag for this challenge, you will need to gain access as “admin” so that the contents of “flag.txt” will be read and displayed.

The ID ($id) and password ($ps) values that are submitted to the form will be passed through the mysql_real_escape_string() function to escape special characters. A whirlpool hash for the password value will be calculated thereafter.

It is important to note that when the 3rd parameter for hash() is set to TRUE, the function outputs raw binary data as oppose to lowercase hexits when the parameter is set to FALSE. What this means is that you should not bother to perform bruteforce against the stored password value of ‘f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f’ cos it’s fruitless to do so.

The objective is to carefully craft a password value that will create a hash value that can nullify the user_ps parameter and gain admin access! How can you achieve that objective? Take some time to think about this before reading on.



Well to achieve that, you need to make use of type conversion during SQL expression evaluation. With type conversion, in particular string conversion to integer, you need to ensure hash() outputs a string value that matches this format (string1′=’string2). When $ps = string1′=’string2, the SQL statement becomes (select * from users where user_id=’$id’ and user_ps=’string1′=’string2′)

SQL expression evaluation will try to convert string1 and string2 to integer but as they are not integers, they will be cast to 0. Doing an equal comparison between two zeroes will evaluate to TRUE, thus making the latter part of the SQL statement to be TRUE and return all data associated with “admin”. The next step is to create a script to compute passwords that can satisfy the format for this attack to be successful.

Passwords Generation Script:

Passwords Generated:

Using admin and 4075629 as the login credentials will grant you access as admin and have the flag revealed! 100 points in the bag. Yay!

Flag Captured:

Cheers,
Braeburn Ladny

Codegate 2013 :: Binary #1 (100 points)

The 1st challenge under the binary category, worthy of 100 points, kicked off with a binary executable given to participants. Through the use of PEiD, the binary was identified to be a “Microsoft Visual C# / Basic .NET” file. Execution of the binary showed it was a simulation program for a door lock.


As no hint was given for the challenge, the next step would be to put the binary through .NET Reflector to decompile and analyse the code. Out of the 13 objects listed in the object browser, 12 were system-related objects. All focus was on the only remaining object “Crack_Test”.


Although Crack_Test contained several methods, there was one particular method that stood out from the rest – void TransFormable(string).

As observed in line 5 & 7, if the two strings matched, a message box would be shown with a decrypted string which might be the flag for this challenge. Gathering data and function code used for decryption within TransFormable() became the next step towards the goal. 

With the above information gathered, a simple PHP was written to perform the decryption based on Rijndael cipher.

And the flag was captured! 100 points in the bag!!  Yay!

Cheers,
Braeburn Ladny

Sunday, June 2, 2013

ebCTF 2013 Teaser - Dice Game (100pts)

Yesterday De Eindbazen organised a preview of their CTF and they called it a teaser. :D

To be honest, all the challenges are quite fun but the "Teaser" lasted only 8hrs and most of my team are busy.
I didn't solve this during the 8hrs as i was busy as well. I've got time this morning to start looking at it and "Oh boy". It's definitely good challenges.

Given Hints:
Challenge BIN100 “Dice Game”

Beat our dice game and get the flag.

This is the backup of the original file:
ebCTF-Teaser-BIN100-Dice.zip

Required Tools:
IDA Pro
Protection iD
ASM OPCodes Reference

Initial Analysis:
Usually before i start to reverse any binary, i would normally checked using PiD on whether is the binary packed.

Figure 1: Using ProtectioniD to scan for packer

The results showed that it's most probably not packed by any known packers.

Now let's start to run the application and see what does it do.

Figure 2: Initial startup of Dice Game.exe

Ok, it seems to want us to roll a 3. But usually such binaries which require us to get certain numbers or sequence will not be easy. Let's load it up with IDA Pro and further analyse it.
If we look carefully at the "Strings subview", we can guess that the sequence of this dice game is to get 3-1-3-3-7 based on the screenshot below.

Figure 3: Strings subview from IDA Pro

Ok, let's check the CFG (Control Flow Graph) on where are the checks for 3-1-3-3-7

Further Analysis:
Ok, i've found my 1st check at loc_4018B5 as shown here.

Figure 4: 1st Check for 3

Since the chances of getting a 3 is 1 out of 6. What you can do is simply patched the instruction from "JNZ" to "JZ" and do it for the rest of the checks.
You can use IDA Pro's "Edit->Patch Program->Change Bytes" feature to do that.
After you are done, simply do "Edit->Patch Program->Apply Patches to Input File..." and save it.

Then finally, run the newly patched .exe and you should get this.

Figure 5: Final flag

The flag for this challenge is ebCTF{64ec47ece868ba34a425d90044cd2dec}

cheers
0x4a61636f62

Saturday, June 1, 2013

Reversing.kr - Easy Keygen (100pts)

You can register and download this file here.
http://reversing.kr/download.php?n=2
Alternatively, i've uploaded a copy of it here:
Easy_KeygenMe.zip

Given Hints:
ReversingKr KeygenMe


Find the Name when the Serial is 5B134977135E7D13


Required Tools:
IDA Pro

Initial Analysis:
Let's load the binary with IDA Pro.
You will see something like the image below.


It seems to me that the username is 8 characters and there is an int array containing 16,32 & 48.
Let's move further down the CFG (Control-Flow Graph) and analyse further and we get something like this.


It's probably clearer now that every character in the user's supplied username is being XOR-ed with the int array.
Since the given hints is to find the Name when the Serial is 5B134977135E7D13 and we know that every character is being XOR-ed with the int array.
Let's XOR-ed back the given serial to find the username.

Conclusion:
From the information which we have gathered so far. Our pseudo code will look something like this.
int iNum[3] = {16,32,48};
int iCounter = 0;
int i=0;
char dest[3];
char *szSerial = "5B134977135E7D13";
char *szUserName;

szUserName = (char*)calloc(9,sizeof(char));
for( i=0; i<strlen(szSerial); iCounter++, i+=2 ){
if( iCounter==3 ){
iCounter = 0;
}
strncpy_s( dest, _countof(dest), &szSerial[i], 2);
dest[2] = '\0';
sprintf_s(szUserName, 9,"%s%c", szUserName, strtol(dest, NULL, 16)^iNum[iCounter]);
}
printf("Original username: %s\n", szUserName);

Eventually, you will see what is the original username that will match 5B134977135E7D13 is "K3yg3nm3"

I hope that it's a simple to understand solution.

cheers
0x4a61636f62