[TWCTF-2016: Web] Global Page Writeup

Standard

Challenge description: 
Welcome to TokyoWesterns’ CTF!


As I entered the challenge I faced a three items list – two links and a strikethrough word:.

I clicked the tokyo link, which was actually a GET request with a parameter named page in index.php. In response I got a page with PHP error and information from Wikipedia about Tokyo, printed in Hebrew – my mother tongue.

Warning: include(tokyo/en-US.php): failed to open stream: No such file or directory in /var/www/globalpage/index.php on line 41
Warning: include(): Failed opening ‘tokyo/en-US.php’ for inclusion (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/globalpage/index.php on line 41

First thing to come in mind is a LFI attack, but before making any reckless time-wasting moves, let’s first figure it all out. The page uses include() to, well, include the page “en-US.php” from folder named tokyo. The page wasn’t existed so an error was thrown. I tried pages like “en.php”, “he.php” and “jp.php” and they did exist. The page “ctf” displayed similar behaviors. Seems like all the pages display their information based on the user’s or the browser’s language.

The second thing I tested was the page’s reactions to different values. I tried the value “?page=flag” and it returned the expected error:

Warning: include(flag/en-US.php): failed to open stream: No such file or directory in /var/www/globalpage/index.php on line 41
Warning: include(): Failed opening ‘flag/en-US.php’ for inclusion (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/globalpage/index.php on line 41
Warning: include(flag/en.php): failed to open stream: No such file or directory in /var/www/globalpage/index.php on line 41
Warning: include(): Failed opening ‘flag/en.php’ for inclusion (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/globalpage/index.php on line 41

I then understood the page was trying to include the language file and every value that I’ll set to “page” will be a folder. I tested the page with the value “../../../etc/passwd” with and without a null-byte terminator but failed due to the sanitize of dots and slashes the page performs.

But how does the page know my language? It took me a while to figure it out. The page took my language settings from the “Accept-Language” field in the request’s header. I tried to change Accept-Language to something else using a Firefox plugin called Tamper Data and it worked! Any value I’ll put there will change the requested page. For example if I request “?page=Mega” and set Accept-Language to “beets” it would return the errors:

Warning: include(Mega/beets.php): failed to open stream: No such file or directory in /var/www/globalpage/index.php on line 41
Warning: include(): Failed opening ‘Mega/beets.php’ for inclusion (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/globalpage/index.php on line 41

I combined it all together to perform a well known LFI attack using php://filter. I set the parameter value to “php:” and the Accept-Language field to “/filter/convert.base64-encode/resource=index”. This function encodes the page with Base64 before including it. And indeed I got “index.php” encoded with base64. The decoded page looks like this:

As you can see on the top of the code there is an included page named “flag.php”. I changed the Accept-Language accordingly to “/filter/convert.base64-encode/resource=flag” and received the encoded page. Decode it to reveal the flag:

TWCTF{I_found_simple_LFI}

By the way, you can also solve it the “Curl” way:

 

megabeets_inline_logoEat Veggies.

[TWCTF-2016: Crypto] Twin Primes Writeup

Standard

Challenge description:
Decrypt it.
twin-primes.7z


We have 4 files in the archive:

  • encrypt.py – A Python script uses RSA algorithm to encrypt the flag
  • encryped – The encrypted message
  • key 1 – n, and e of one of the keys used in the encryption process
  • key 2 – n, and e of the other key used in the encryption process

Are you ready for your math lesson? Here we go.
After reading encrypt.py we know that:

  • n1 = p*q
  • n2 (p+2)(q+2)
  • p and q are twin primesi.e p is prime and p+is also prime; similar for q.

Now let’s turn the equation into an equation with one unknown and then solve it for the unknown.We can Isolate q to be twin-primes_1  and substitute q in the other equation. Now we have an equation in one unknown:twin-primes_2

Solve the equation and you’ll get: twin-primes_3

We need to solve this quadratic equation in order to find p and q. After that it will not be a problem to find the d’s and build the keys.
The rest is in the script:

 

[TWCTF-2016: PPC] Make a Palindrome! Writeup

Standard

Challenge description:

Your task is to make a palindrome string by rearranging and concatenating given words.

You have to connect to ppc1.chal.ctf.westerns.tokyo:31111(TCP) to answer the problem.

  • Time limit is 3 minutes.
  • The maximum number of words is 10.
  • There are 30 cases. You can get flag 1 on case 1. You can get flag 2 on case 30.
  • samples.7z Server connection examples.

This challenge was pretty simple. I used the given “example.py”  and added the following function to it:

Then I called it using the original script structure:

And the server returned the flag:
TWCTF{Hiyokko_Tsuppari}

The full script can be found here.

[TWCTF-2016: Web] Rescue Data 1: deadnas Writeup

Standard

Challenge description:

Today, our 3-disk NAS has failed. Please recover flag.
deadnas.7z


We are given an archive containing 3 files:

3 Disk NAS and one has failed? This challenge is obviously about RAID 5. I was asked to find a way to recover the failed disk and there is no simpler way than just XOR disk0 with disk2 and recreate the original disk1. If you are right now in your “WTF?!” mode you better go read about RAID 5 until you understand how it works.

I used simple software called XorFiles.

XorFiles

I then used OSForensics to rebuild the RAID:

OSForensics

Mounted the output file:

OSForensics2

And accessed the new drive. The flag and a cute cat was waiting for me there.

GlobalPage_Flag

* I know you tried using mdadm and ReclaiMe. Poor you.

[TWCTF-2016: Reverse] Reverse Box Writeup

Standard

Guest post by Shak.

Challenge description
$ ./reverse_box ${FLAG}
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a
reverse_box.7z


This challenge is a binary which expects one argument and then spits out a string. We get the output of the binary for running it with the flag. Let’s fiddle with that for start.

The binary probably prints a hex value replacing each character. It is also clear that it is a unique value for each character. we must be dealing with some kind of substitution cipher. After running it again with the exact same argument, we get a different output, so the substitution is also randomized somehow.

Jumping into the binary, we are presented with 2 important functions which i named main and calculate.

The main function is pretty straightforward. It is responsible for checking whether we run the binary with an argument, calling the calculate function, and finally printing the result. Looking the result printing format we can see that we were right with the result being in a hexadecimal format.

Next we’ll deal with the calculate function.

It is not at all as straightforward as our main, but basically it randomizes a variable, does some memory operations and returns some random value. For now, let’s try debugging the binary without fully understanding calculate.

The binary iterates the characters in our input and executes the following assembly for printing the result.

Arriving at this set of instructions, the eax register is holding a character from our input. What is then passed for printf function is an element from an array in [esp+1Ch] at the eax location (line 1). So this array holds our result. Let’s further examine it and see what it’s all about. Jumping that location on the stack we encounter a 268 Bytes array of hex values, we will save the array to a binary file called array for later.

After running the binary a couple of times, we can understand that the array is also randomized somehow. Maybe it has something to do with the random value that the calculate function is returns. Running the binary a couple of times more, we see that the second element of the array is always equal to the random number from calculate. So, the binary must have a base array which is then manipulates somehow with the random value. The second element in the base array must be a zero if every time the manipulation occurs we get the random number. Let’s try and understand what kind of manipulation the binary performs. We will do that by loading the binary array to a python script, then we will get the base array by performing the assumed manipulation on our saved array elements with the known random value from our execution of the binary, and finally comparing the process to another binary run with a different random value for verification. The first option will be adding the random value to the base array value. It works for the second element, but comparing this process to another binary run does not work. The second guess will be that the binary is XORing the random value with the base array element which will also allow the second array element to be equal to the random value. Bingo, this works. Now all we have to do is get the base array using our saved array and the random value for that binary run. Next thing we will have to consider is the flag structure which is TWCTF{….}. We can calculate what was the random value when they run the flag through the binary and finally check where was every hex value from the flag result and get the original output by getting the char representation for the location.

et voilà, the flag is TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}.

[TWCTF-2016: PWN] judgement Writeup

Standard

Guest post by Shak.

Challenge description:
Host : pwn1.chal.ctf.westerns.tokyo
Port : 31729
judgement


Let’s check the binary. The following function is reading the flag from a local file on the server, so this binary will not reveal the flag, but further examining it might.

Next we can see the main function which gets our input and compares it to the flag.

What it also does, is printing our input with no formatting (line 15), which means we can use printf format to read data from the stack. First of all, let’s check if this will work by trying to print the second value from the stack as a string

It works, but no luck there. I wrote a simple python script that will print the first 300 values from the stack and search for the flag:

And indeed we get it: