EKOPARTY CTF 2016 Write Up

Me and my colleagues have been participating in a bunch of Capture the Flag (CTF) events lately.

If you don’t know what CTFs are, they’re basically Information Security related contests where the participants must extract certain pieces of texts called “flags” from a bunch of computer-related puzzles in order to earn points. Usually, these puzzles are presented to the participants in a jeopardy-like format where the solution to each puzzle correspond to a certain amount of points for the participant (or team) skilled enough to extract the hidden flag. The puzzles are frequently sorted into categories which normally include Web, Reverse Engineering, and Exploitation. As with any contest, the individuals who gather the highest amount of points emerge victorious.

The latest one that we have joined was held by the Ekoparty Security Conference this last October 27-29, 2016.

We weren’t really planning on winning anything as we were mostly in it for the learning experience, and, I admit, that I’ve learned a lot of Information Security tricks (such as exploiting certain version of the Linux Kernel, buffer overflow attacks, tracking down a hidden Tor service using it’s SSH fingerprint, etc.) from these Capture the Flag events.

I usually didn’t author Write Ups for any of the CTF events that I have participated in before, but I believe that it would be a good idea to finally start doing so as engaging in the authorship of these write ups may help me preserve the important knowledge that I have gained from participating in these various CTF events.

Do note that I’ll only be writing about the puzzles that I have been able to solve in the CTF sponsored by the conference mentioned above. Also, please do note that my solutions may not necessarily be the best ones.

Table of Contents

Reversing 50 (F#ck)

[ Back to Table of Contents ] | [ CTF Time Write Up ]

ctf-ekoparty-2016-rev-50

A wild inappropriately named reverse engineering challenge appears!

The attachment contains a single Windows executable file named FlagGenerator.exe. Upon closer inspection (via a text editor), one would see that the executable is a .NET assembly.

Requirements

Process

  1. Open the FlagGenerate.exe file with ILSpy
    ctf-ekoparty-2016-rev-50-fig-1
  2. View the decompilation for FlagGenerator/-/Program
    ctf-ekoparty-2016-rev-50-fig-2
  3. Create a Visual Studio Project
  4. Add the FSharp.Core assembly to the References of your project
    ctf-ekoparty-2016-rev-50-fig-3
  5. Copy all of the imports in the decompilation to your project
    ctf-ekoparty-2016-rev-50-fig-4
  6. Copy the entire Program class to your project
    ctf-ekoparty-2016-rev-50-fig-5
  7. Replace all instances of teArr@9 to teArrat9 (or any other valid name) to suppress some of the syntax errorsBefore
    ctf-ekoparty-2016-rev-50-fig-6After
    ctf-ekoparty-2016-rev-50-fig-7
  8. Replace entire main method with a call to Program.get_flag(“t#hs_siht_kc#f”) and and print of its return valueBefore
    ctf-ekoparty-2016-rev-50-fig-8After
    ctf-ekoparty-2016-rev-50-fig-9
  9. Run the program, copy the output, and pass it as an argument to FlagGenerator.exe
    ctf-ekoparty-2016-rev-50-fig-10
    ctf-ekoparty-2016-rev-50-fig-11
  10. The flag is EKO{f#ck_this_sh#t}

Reversing 100 (Old times)

[ Back to Table of Contents ] | [ CTF Time Write Up ]

ctf-ekoparty-2016-rev-100

The attachment contains a single iSeries (AS400) Save File (SAVF). The challenge is pretty straightforward. You just need to explore the contents of the SAVF file using an appropriate viewer application in order to find the flag. For this challenge, I opted to use Julian Wong‘s ViewSavF program.

Requirements

Process

  1. Open the SAVF file using ViewSavF
  2. Go to Library/Part1/EKOPARTY(PF)/CHALLENGE1 and you will find the flag there
    ctf-ekoparty-2016-rev-100-fig-1
  3. The flag is EKO{0ld_t1m3s_n3v3r_c0m3_b4ck}

Pwning 25 (Ultra baby)

[ Back to Table of Contents ] | [ CTF Time Write Up ]

ctf-ekoparty-2016-pwn-25

The attachment contains an ELF binary named ultrababy. This binary is similar to one being hosted as a service on the socket provided in the challenge’s description. The only difference between the two is that the binary included in the attachment contains a pseudo flag rather than the actual flag. This was probably done so that you can’t just look inside the binary strings of the attachment in order to find the flag. This setup forces you to actually attack the service being run on the provided socket.

Requirements

Process

  1. Once you download the REC Decompiler, you will need to setup some additional things in the environment. The first one would be to create an output folder directly under the extracted RecStudioWin folder. Note that I’m using the Windows version of REC Decompiler if it wasn’t obvious.
    ctf-ekoparty-2016-pwn-25-fig-1
  2. Next, you will need to get the ultrababy binary in a place where the RecCLI.exe program will be easily be able to access it. In my case, I simply moved ultrababy binary inside the bin folder – right beside the RecCLI.exe program.
    ctf-ekoparty-2016-pwn-25-fig-2
  3. Open a Command Prompt window and navigate to the bin folder of your copy of REC Studio, and then execute RecCLI.exe ultrababy ultrababy.c
    ctf-ekoparty-2016-pwn-25-fig-3
  4. The decompilation results for the ultrababy ELF binary will appear inside the output folder you created earlier. The file name should be ultrababy.c.
    ctf-ekoparty-2016-pwn-25-fig-4
  5. Open the file using your favourite text editor and navigate to the segment shown below. This is the only segment which will be of interest to us.
    ctf-ekoparty-2016-pwn-25-fig-5
  6. We want to be able to call the Flag function located at memory address 0x000007F3. This function will print the flag directly onto the screen. If you’re wondering why we can’t just grab the flag right there, it’s because that’s only a pseudo flag. The real flag is on the binary running as a service on the socket specified in the description of the puzzle. This is still some pretty useful information however, as it tells us how our exploitation target operates.
  7. Look at the main function. Specifically, look the at the call to the _v16 function (it’s the last one)
  8. Notice that _v16 isn’t really a function. It’s a variable. What happens there is that the program calls the function whose address is stored inside the _v16 variable
  9. If you look at the initialisation of the _v16 variable, you will find that it is assigned the value of 0x7E0. This is the address of the Bye function. If we could change the value of _v16 from 0x7E0 to 0x7F3, then we would be able to call the Flag function which in turn will print the flag onto the screen.
  10. Our point of attack shall be the read function. What this function does is that it reads some string from the Standard Input (user input) and places the string onto the specified buffer (which in this case is the _v40 variable). This function does not perform any bounds checking, so if we place an input that is larger than the size of the _v40 buffer, the extra input will overflow onto the _v16 variable. This will allow us to overwrite the contents of the _v16 variable and call the Flag function.
  11. At this point, we have no idea how big the _v40 buffer is, so we’re going to have to find out. To do this, we just feed an increasing number of characters into the Standard Input of the ultrababy program until we get a Segmentation Fault.
    ctf-ekoparty-2016-pwn-25-fig-6
  12. Once we get a Segmentation Fault, we will know how big the _v40 buffer is. In this case, the program broke at 25 characters. This means that the _v40 buffer is 24 bytes long. It broke at 25 characters because we accidentally wrote over the first byte of the _v16 variable, and, as we remember, this variable is used by the program to call some function. If we place an invalid address there, the program will result in a Segmentation Fault.
  13. We now know how big the _v40 buffer is (24 bytes), and we also know the address of the Flag function (0x7F3). The only thing we need to do now is to formulate a specially crafted input that we will feed into the Standard Input of the ultrababy program in order to overwrite the _v16 variable with the value of 0x7F3.
  14. For this task, we will use the echo command in Linux and pipe its output to the Standard Input of an ultrababy instance, but this time, we’re going to pipe it into the ultrababy instance running as a service on the socket provided in the description of the puzzle.
  15. The command that we will use is echo -n -e "AAAAAAAAAAAAAAAAAAAAAAAA\xf3\x07\x00\x00. The -n flag tells the echo command not to append an extra newline at the end of the string it will output. This is important because we need to be exact with the data that we will feed into the ultrababy service. The -e flag tells echo that it shall interpret backslash escaped characters. This is important because we want the \xf3\x07\x00\x00 part of the data we’re feeding into the echo command to be transformed into the appropriate byte values (i.e. we want \xf3 to be transformed into a byte with the value of 0xf3 rather than a literal “\xf3” string). We’re feeding the address in reverse order because addresses are commonly stored in little-endian format. This means that the higher part of the address is in a higher memory location and the lower part of the address is in a lower memory location. Meanwhile, strings are stored in such a way that the first character is in a lower memory location and the last character is in a higher memory location. This means that the lower part of the _v16 variable will be written first, hence the reverse order of our input.
  16. Lastly, we simply pipe our echo command into a netcat command which connects to the ultrababy service, and then we’ll have our flag.
    ctf-ekoparty-2016-pwn-25-fig-7
  17. The flag is EKO{Welcome_to_pwning_challs_2k16}

FBI 100 (Find me)

[ Back to Table of Contents ] | [ CTF Time Write Up ]

ctf-ekoparty-2016-fbi-100

This challenge requires the participants to find the IP address of an anonymous hidden service accessible via the Tor network. This would be easy if we were in your ordinary internet environment, but in the Tor network, you can’t really do an nslookup or dig. The participants will have to find other ways to pinpoint the location of the service. Luckily, there is indeed a way, and it has something to do with searching for the banner of the service using one of my favourite search engines: Shodan.

Requirements

Process

  1. Install Tor on your Linux machine. In my case, I simply did a sudo apt install tor because I used a Lubuntu Virtual Machine.
  2. Register a Shodan account and acquire your API key. It should be under your Account Overview.
  3. Clone SSH Key Scanner using git (git clone https://github.com/0x27/ssh_keyscanner.git)
  4. Open the keyscanner.py file inside the cloned repository directory
  5. Change the value of the SHODAN_API_KEY variable to your own Shodan API key
  6. Run torify python keyscanner.py -i ekosshlons2uweke.onion
    ctf-ekoparty-2016-fbi-100-fig-1
  7. What keyscanner.py does is: it acquires a colon-separated MD5 hash of the SSH service’s public key called an “SSH Fingerprint” and then it searches Shodan for a banner containing that fingerprint. You can alternatively extract the SSH fingerprint of the service manually using nmap and search for it in Shodan.
    ctf-ekoparty-2016-fbi-100-fig-2
  8. The flag is EKO{52.73.16.127}

Web 150 (Carder)

[ Back to Table of Contents ] | [ CTF Time Write Up ]

ctf-ekoparty-2016-web-150

This is the last challenge that I was able to answer in the CTF event. This is a pretty straightforward challenge. You just need to provide three valid credit card numbers to the form presented in the page referred to by the description of the puzzle. You will have to do this in fifteen seconds or less so you have to prepare your “fast hands” game.

Requirements

  • Python

Process

  1. Upon clicking the link presented in the description of the puzzle, you will be taken to a page asking for valid numbers for Visa, Master Card, and American Express credit cards. You have to provide the numbers within 15 seconds. The time frame validation is checked both at the client and server side so you can’t just change the HTML in the page after the time period has expired.
    ctf-ekoparty-2016-web-150-fig-1
  2. The page already provides you with the first and last four digits of the credit card numbers that you need to provide. You just need to fill in the missing numbers in the middle. The next step will be determining how long the missing numbers are. Luckily for us, the form already tells us how many numbers are missing. This detail is important because once we start brute forcing for the appropriate numbers, we need to know how many zeroes we have to pad to our iterator. This will make sense in a while so please bear with me.
    ctf-ekoparty-2016-web-150-fig-2
  3. Create a new Python script file and save it as creditcard.py. This is the file where we’ll be writing our brute force script.
  4. Paste the following function into creditcard.py
    def cardLuhnChecksumIsValid(card_number):
        """ checks to make sure that the card passes a luhn mod-10 checksum """
    
        sum = 0
        num_digits = len(card_number)
        oddeven = num_digits & 1
    
        for count in range(0, num_digits):
            digit = int(card_number[count])
    
            if not (( count & 1 ) ^ oddeven ):
                digit = digit * 2
            if digit > 9:
                digit = digit - 9
    
            sum = sum + digit
    
        return ( (sum % 10) == 0 )

    See: Python Luhn checksum for credit card validation (Python recipe)

  5. The code above essentially returns True if you give it a valid credit card number, and False if you give it an invalid credit card number
  6. Next. we’ll declare a jobs array right after the declaration of the cardLuhnChecksumIsValid function. This will contain the prefix and suffix of the numbers that we need to brute force as well as the length of the missing pieces in between those numbers.
    # list format: [missing_len, prefix, suffix]
    jobs = [
        [5], [8], [7]
    ]

    For each array element in our jobs array, the first element shall be the length of the missing digits of the numbers, the second element shall be the prefix of the numbers provided by the web page, and the third element shall be the suffix of the numbers provided by the web page. I initialise the first element of each array with the length of the missing pieces of the numbers based on the information that we have gathered in step 2. As you can see from the lengths that I have provided, the first array will be representing the Visa number, the second array will be representing the Master Card number, and the third array will be representing the American Express number. I leave out the prefix and suffix fields because we’ll have to take those as inputs from the user. Unfortunately, we can’t just hard code the prefix and suffix values because they change every time you refresh the puzzle’s web page.

  7. We will want to be able to quickly provide the prefix and suffix values to the program. Typing them in one by one just won’t do given the 15 seconds time window the puzzle provides us with, so that’s why we will want to be able to highlight and copy the values from the web page and then paste them into the program’s Standard Input. After highlighting the form in the web page, hitting Ctrl+C and pasting into a text editor, I can see that our program will be encountering the data in the following form:
    4556
    rest of your number
    1231
    Mastercard
    5242
    rest of your number
    3250
    American Express
    3423
    rest of your number
    0249
  8. As we can see in the form of the data that we will be providing to our program, we’re going to have to ignore the lines containing rest of your number and the card names.
  9. Right after the declaration of the jobs array, add the following lines of code:
    index = 0
    for index in range(0, 10 + 1):
        line = raw_input()
        if index == 0 or index == 2:
            jobs[0].append(line.strip())
        if index == 4 or index == 6:
            jobs[1].append(line.strip())
        if index == 8 or index == 10:
            jobs[2].append(line.strip())
        index += 1

    This will read the prefix of the numbers in lines 0, 4, and 8. Meanwhile, suffix number will be read from lines 2, 6, and 10.

  10. Next, we’ll be doing the actual brute forcing of the numbers. Go ahead and paste the following lines of code at the bottom of the segment where we acquire the user’s inputs.
    for job in jobs:
        length, prefix, suffix = job
        for i in range(0, int(math.pow(10, length))):
            iteration = str(i).zfill(length)
            number = prefix + iteration + suffix
            if cardLuhnChecksumIsValid(number):
                print iteration
                break

    So, what we’re doing here is that we go over all the jobs inside of our jobs array, and then for each job, we acquire the length, prefix, and suffix of the current job, and then we iterate over all the numbers in the number space based on the length of the missing digits of the credit card number we are currently brute forcing. For each iteration, we pad our iterator with zeroes until the desired length is reached, and then we formulate the final credit card number to test by prepending and appending the prefix and suffix values respectively. After that, we check if the number is valid by using the cardLuhnChecksumIsValid function. If the credit card number is invalid, we simply move on to the next iteration. If the credit card number is valid, we print the valid onto the Standard Output, and then move on to the next credit card number to brute force.

  11. Let’s test our script.
    ctf-ekoparty-2016-web-150-fig-3
    The highlighted parts are the output, and the rest is the input pasted from the web page. Make sure you hit the Enter key after pasting the input. The script can usually calculate valid credit card numbers in under 2 seconds. I use a high-end gaming rig so it might be a bit different for you.
  12. Copying text from the Command Prompt window is difficult given the time constraint of the puzzle so we would want to have that output somewhere easier to copy from, hence, I piped the program’s output into a text file and opened that file using Notepad. For faster execution, write a batch script like the following:
    python creditcard.py > creditcard.txt
    notepad creditcard.txt
  13. Now prepare the Doritos and Mountain Dew because we’re gonna be doing some real MLG Quick Scoping action here. If you fail, start from this step again.
    ctf-ekoparty-2016-web-150-fig-4
  14. Run the batch script I asked you to create earlier but don’t do anything yet once creditcard.py has begun executing
  15. Make sure that the web browser viewing the puzzle page is windowed. Move it right beside the Command Prompt window that the batch script is executing on. This will allow us to quickly copy from the web page and paste into the creditcard.py script.
    ctf-ekoparty-2016-web-150-fig-5
  16. Now refresh the page and quickly copy the information that we need from the web page like this:
    ctf-ekoparty-2016-web-150-fig-6
  17. After that, quickly paste into the Command Prompt window running the batch script like this. In Windows 10, you just need to right-click. It might be a lot harder in older versions of Windows.
    ctf-ekoparty-2016-web-150-fig-7
  18. Hit enter, and a Notepad window containing the numbers you need will pop up.
    ctf-ekoparty-2016-web-150-fig-8
  19. Now paste those values into the puzzle web page before the timer runs out. Make sure you play your best Eurobeat track while doing this so you can attack those input fields at incredibly high speeds.
    ctf-ekoparty-2016-web-150-fig-9
  20. Once you succeed, you’ll end up with something like the image below. If you fail, do as they say and “git gud“.
    ctf-ekoparty-2016-web-150-fig-10
  21. The flag is EKO{abda121daf4c4a7ba3e765b041a2f186}
  22. Download the source code for creditcard.py here

This concludes my write up for the Ekoparty Security Conference‘s CTF for 2016. I didn’t expect this article to become a meme show in the end, but I guess my nature got the better of me. Anyway, I hope you enjoyed the article.

Until next time!