PlaidCTF 2011 – 21 – Key leak – 450 pts

This is my writeup for the twenty-first challenge in the PlaidCTF 2011 competition. The information for the challenge was:

“We have obtained the binary for AED’s internal data encryption service, running at
Obtain AED’s data encryption key.”

The binary for this level was available for download, so that it could be inspected in IDA Pro and debugged with GDB. Turns out it is executed through inetd, or some similar service. It reads its input data from stdin and writes to stdout, and does not contain any socket handling code by itself.

By analyzing the code in IDA Pro I noticed that snprintf() is called with 80 as its length argument. The problem with this is that the stack buffer it writes to is only 64 bytes large. This is not enough to overwrite the saved return address, we will however overwrite the FILE-pointer for a log file right before fwrite() and fclose() is called. I knew that the FILE-struct contains a pointer to an array of function pointers, and first wrote an exploit that used this to achieve code execution. Since the buffer we control is much smaller than the FILE-struct it was a bit tricky to get right, but I finally ended up with this piece of code to achieve code execution on my own system with ASLR deactivated:

Note that I overwrite the FILE-pointer with the address to my buffer minus 18. This is to make sure I am able to control the _vtable_offset variable and make fwrite() use the function pointer I’m placing in the beginning of the buffer. It is also critical that the word that happens to be at this stack address is a negative number (e.g most significant bit set), to avoid a crash due to dereferencing a value out of my control.

If you want to try this on your own system, deactivate ASLR with sysctl kernel.randomize_va_space=0 (as root) and determine the buffer address with:

If your libc is stripped from symbols, you can disassemble system() to find the do_system() function pointer. Example:

This depends on two addresses though, the address to the buffer and the offset to the libc internal do_system() function. Although it’s certainly possible, it could potentially take a pretty long time to bruteforce both of these values when ASLR is active and unfortunately this is the case on where the keyleak server resides. So, let’s figure out another way to exploit this bug.

Reading the description for this mission we learn that we only need to obtain the encryption key used by the program, we don’t actually need code execution. So, let’s see how the key is used by the program and if there is some way we could retrieve it without actually executing code or getting a shell.

The file descriptor to the key file has not yet been opened when the vulnerability is triggered, so finding a way to directly dump the contents of the key file seems unlikely. However, this piece of code indicates that we may do something else that might be useful:

A buffer is read from file descriptor 0 = stdin = the socket descriptor in this case. Then the key is read from the key file descriptor. If we overflow the FILE-pointer with the address of stdin we can close this descriptor, which will make the next call to open() to reuse file descriptor 0. The next call to open() opens the key file in this case, which means that the key will be read into usr_buf (user input buffer). Since this read() will consume everything in the keyfile, the read() into key_buf will result in an empty string.

So, how would this help us? Well, analyzing the rest of the code it derives an AES encryption key from the contents of the keyfile combined with a 32 byte random salt.

The key would in this case be an empty string. :)

Then it continues with generating a random IV for initializing the AES-256 cipher along with the key.

It finishes off by encrypting the user input buffer (containing the real key), and then writing the salt, the iv and the encrypted buffer to stdout.

So, if we manage to close stdin we will get the real key encrypted with a key we will be able to determine by using the known salt, iv and an empty string as key.

Since ASLR is used we had to use bruteforce to find the stdin pointer. Only 12 bits of the glibc base is randomized, and empirically it seems as if some addresses are much more likely to be used than others. The most effective way to bruteforce is therefore to use a static “guess”, based on the address taken from a previous execution. Since we had not yet realized that the a5 box where we already had shell access through SSH used the same glibc version as the a9 box, we used our PC Rouge exploit to upload the keyleak program and the following small library:

By loading this library with LD_PRELOAD when executing keyleak we get to know the address of stdin for this particular execution attempt, and can use this value to bruteforce with.

To perform the bruteforce I developed the following script:

This is the output from a sample execution:

The first 32 bytes is the salt used when deriving the encryption key. This is followed by the 16 bytes IV buffer that is used when initializing AES, and finally by 32 bytes representing the encrypted key.

To get the plaintext key we can now feed this into the following program, originally developed by Kaliman while I worked on the stdin bruteforce script:

PlaidCTF 2011 – 20 – C++ upgrade – 300 pts

This is my writeup for the twentieth challenge in the PlaidCTF 2011 competition. The information for the challenge was:
“They have an update for the vulnerable C++ program trying to fix the bug.
However, the coders at AED suck and introduced another stupid mistake.
Get a shell (and the key, too.)

Since this challenge is about exploiting a C++ program, I immediately think vtable overwrite. Not surprisingly, I’m right. :) For those of you not familiar with how C++ code looks at the assembly level I can tell you that it can be quite a mess to reverse-engineer, due to lots of indirection. When calling virtual member functions, e.g. functions that may be overridden by classes that inherit from a base class, a vtable (virtual table) is used to determine what function to call. The vtable is simply a pointer to an array of function pointers, with each offset into the array representing a different virtual function, stored in the beginning of the object.

Even though this may make things slightly less straight forward when debugging and reverse-engineering, it can actually be quite handy for an exploit developer such as myself. Let’s say we have a heapbased overflow in an application with a reasonably secure malloc() implementation (e.g. most ones on mainstream desktop/server operating systems nowadays). In the good old days we could easily turn a heapbased overflow into a write-4-anywhere primitive by overwriting malloc chunk headers.

Nowadays we have to deal with a lot of integrity checks, such as the safe unlink() that ensures that p->next->prev == p && p->prev->next == p when taking a chunk p off its current free chunk list. Small chunks are usually stored in a single-linked list instead, which makes this kind of check impossible. :) With all the heap integrity checks and exploit mitigation mechanisms of today we are usually better off using an application dependent attack than trying to defeat all of them though.

In this case, we have two classes (Awesomeness and EpicFailure), inheriting from the same base class with one virtual function. It just so happens that before the call to this virtual function there is an overflow due to a sprintf() to a buffer in the Awesomeness-object. There is also another overflow, due to a strcpy() to a buffer in the EpicFailure object but this will not be needed. This is the decompiled code of the relevant function:

Note that the data is also copied into a static global buffer (buf_in_bss), this will come very much in handy due to the nature of a vtable overflow. Remember that a vtable pointer is actually a pointer to an array of function pointers? That means we will have to overwrite it with not just the pointer to our shellcode, but to a pointer that at a certain offset (in this case zero) contains the pointer to our shellcode. We have an extra level of indirection, which makes attacker controlled data at fixed addresses very useful.

Anyway. Let’s see what happens after the overflow. First, in the main() function:

Then in the decompiled EpicFailure_Report() function:

Since the EpicFailure object is allocated after the Awesomeness object, the sprintf() overflow will overwrite the vtable pointer in the EpicFailure object, we can use the call via failObj->vtbl to control EIP by now. To do this we simply need to overflow the vtable pointer with the address to buf_in_bss+strlen(“Uploading… [“), put the address to buf_in_bss+strlen(“Uploading… [“)+4 in the beginning of the first command line argument and the address of something we want to be executed right after it.

The executable has NX enabled, but since the box does not have any hardware NX support we can still execute code in the .bss segment for instance, so in this case we can simply put our shellcode in the buf_in_bss buffer as well. My final exploit looks like this:

For completeness, I also solved it without relying on being able to execute code in the .bss segment. In this case I had to bruteforce the libc-base and call an internal function called by system(), that contains the command line to be executed in the eax register.

PlaidCTF 2011 – 19 – Another small bug – 250 pts

This is my writeup for the nineteenth challenge in the PlaidCTF 2011 competition. The information for the challenge was:

“This time, let’s attack /opt/pctf/z2/exploitme.

Using IDA Pro I can see that the program takes one command line argument, which is interpreted as an unsigned integer representing the number of bytes to read from stdin into a 512 byte buffer. There is a length check that is meant to ensure that we don’t pass more than 512 as the length argument. However, it also checks the return value of a function that is supposed to log the error.

Examining the log_error() function (named by me) we see that the logfile is /home/z2/logs/assert.log, and that the function returns zero if the file could not be opened. If we can somehow get fopen() to fail, that would mean the length check in the main() function becomes ineffective.

Normally, I would accomplish this by using

to set the maximum number of open file descriptors before executing the vulnerable program, in this case we don’t even need that though. :D Turns out the /home/z2/logs directory does not exist, and thus the fopen() will always fail. Since the buffer that is read into is located on the stack, we end up with a vanilla stackbased buffer overflow.

No stack canaries are used, and the executable does not even have NX enabled. The only hurdles we need to overcome are that the stack is randomized and that the binary is statically linked (so we can’t jump to system() in libc). To deal with this, I chose to use a return-to-text based attack. For completeness I chose to make two variants of my exploit, one that relies on .bss being executable and one that would work with full NX too.

My first exploit simply returns into read(), with the stack set up to read from file descriptor 0 (stdin) to the .bss segment, and then return into that buffer. It relies on the following addresses, easily retrieved from the binary using IDA Pro:

  • 0x80489d8 – read()
  • 0x804b510 – .bss

My second exploit returns into mmap() to map a writable and executable buffer at a fixed location, then into an address with six pops and a ret instruction to go past the mmap() arguments on the stack and return into read() just as in the previous exploit. This relies on the address of:

  • 0x8049abc – mmap()
  • 0x8048529 – pop * 6 + ret
  • 0x80489d8 – read()

This is the source of my second exploit:

Note the call to sleep between the exploit buffer and the shellcode. This is to make sure that only the exploit buffer is read by the fgets(), and the shellcode by the call to read() that I set up.

PlaidCTF 2011 – 18 – A small bug – 250 pts

This is my writeup for the eighteenth challenge in the PlaidCTF 2011 competition. The information for the challenge was:
“Get access to the key using /opt/pctf/z1/exploitme.

/opt/pctf/z1/exploitme is an SGID binary, which is executed with the privileges of the z1key group. Using IDA Pro to analyze the code I quickly spot an exploitable race condition. The tempnam() function is called to generate a temporary filename in /tmp/chal_XXXXXX, where XXXXXX is a random string. To make sure that such a file does not already exist, stat() is used. Then fopen() is used to create the file and write the string given as a command line argument to it.

This means that if we are able to create a symbolic link from the filename generated by tempnam() to a file we want to create or overwrite before the vulnerable application before the call to fopen(), we are able to create a file owned by the z1key group. So, let’s log in the server and see what this allows us to do:

Ah, perfect. The /opt/pctf/z1key/cron.d directory is writable to by the z1key group, and any filename ending with ‘.sh’ will be interpreted as a shellscript and executed once a minute. The key we need is stored in /opt/pctf/z1key/key, so let’s use the vulnerability to execute something like ‘mail z1_201 < /opt/pctf/z1key/key' to mail us the key. We don't want to copy it to /tmp or something like that, since that would mean other teams would be able to read it as well. z1_201 is our personal team account for this challenge. In this case, IDA Pro was actually quite superfluous. The bug would have been obvious just by running the application:

By using strace, for instance, we would have seen that the data written to the temporary file is our command line argument and the level can be easily completed as follows:

PlaidCTF 2011 – 08 – The App Store! – 250 pts

This is my writeup for the eighth challenge in the PlaidCTF 2011 competition. The information for the challenge was:

“We found the mobile phone that’s left in one of the office.
Out of all applications, The Color Game App seemed suspicious.

We believe the solution to this game is the password of the user for the computer next to it.
Solve it! and get the password!

Key is the color sequence of the buttons in all lower case with no spaces [e.g. redyellowbluegreenred]

These are the screenshot of the game:

This challenge consisted of an iPhone application, compiled for x86 so it can be used with the iPhone Simulator included with the iOS SDK. To analyze the code I used IDA Pro and for dynamically analyzing in runtime I used GDB, attaching to it after I’ve started it with the iPhone Simulator.

With IDA Pro I started with analyzing the viewDidLoad() method for the reverseMeViewController object. Scattered throughout the function are calls to the addObject() method of the NSMutableArray object named holyHandGrenadeOfAntioch. The objects added to the array are of type CFConstantStringClassReference and the strings that are added are, in order:
Blue, Green, Yellow, Blue, Red, Red, Red, Blue, Purple, Yellow, Green, Orange, Blue, Blue

By listing the cross references to the holyHandGrenadeOfAntioch object I find the reverseMeViewController.sheepFucker() method, which compares the contents of holyHandGrenadeofAntioch array with the contents of another array named donkeyFucker, and by listing the cross references to the donkeyFucker object I find that it is referenced in the following methods:

  • allDayHomeBoy
  • myLifeBeLike
  • weAreTheKnightsWhoSayNi
  • blameGalgara
  • bitch
  • brooooooooo

These are the handlers that are called when the addRed/addYellow/etc buttons are pressed in the applications, and by analyzing them in IDA I can see that they add the following strings to the donkeyFucker object:

  • allDayHomeBoy – Blue
  • myLifeBeLike – Green
  • weAreTheKnightsWhoSayNi – Yellow
  • blameGalgara – Purple
  • bitch – Red
  • brooooooooo – Orange

Now, a hasty assumption would be that the strings added to the array equals the actual colors that are seen in the GUI. In this case our key would be:

Of course, this is not the case. We have a little bit of work to do still, and I chose to take the easy route of simply using GDB and setting a breakpoint on each of the button press handlers.

First, we start the application in the iPhone Simulator:

Second, we attach to the process in GDB and set our breakpoints:

I now simply press each button in order (red, yellow, green, purple, blue, orange) and see which handler is called for which color:

This gives me the following mapping between handler and color:

  • allDayHomeBoy – Red
  • myLifeBeLike – Yellow
  • weAreTheKnightsWhoSayNi – Green
  • blameGalgara – Purple
  • bitch – Blue
  • brooooooooo – Orange

Combined with the knowledge of which string is added to the donkeyFucker array in each of these handlers, I can now map a string in the array to the actual color in the GUI:

  • Blue -> Red
  • Green -> Yellow
  • Yellow -> Green
  • Purple -> Purple
  • Red -> Blue
  • Orange -> Orange

Applying this to the list of strings in the holyHandGrenadeOfAntioch array we get:
Blue, Green, Yellow, Blue, Red, Red, Red, Blue, Purple, Yellow, Green, Orange, Blue, Blue
Red, Yellow, Green, Red, Blue, Blue, Blue, Red, Purple, Green, Yellow, Orange, Red, Red

Trying this in the emulator, we get a picture of a happy face. :)

Thus, our key is:

PlaidCTF 2011 – 06 – Fun with Numb3rs – 100 pts

This is my writeup for the sixth challenge in the PlaidCTF 2011 competition. The information for the challenge was:

“Uh oh..
This door is protected with number scroll authenticator. There’s “powered by .NETv4″ sign.
Find out the combination and get the key!”

The application interface consists of three horisontal scrollbars that can be set to values between 0 and 255. Since this was a .NET executable I was able to use a tool called .NET Reflector to decompile it back to its C# source code representation. After examining the decompiled source a bit I found this function, that is obviously responsible for controlling whether the scrollbar numbers are correct or not:

As you can see, the i and j scrollbars can be set to any value between 0 and 255 but h must be above 0x4d (e.g 78-255). This gives us 256*256*(256-78) = 11665408 combinations to test. With a small C-program I can find the correct combination in the blink of an eye.

When using this combination I get the following code:

And with that, the challenge is solved. :)

PlaidCTF 2011 – 04 – Here, There Be Dragons – 300 pts

This is my writeup for the fourth challenge in the PlaidCTF 2011 competition. The information for the challenge was:

“After breaking into the AED network, we stumbled across a router with custom software loaded. Intrigued by this discovery, we sent in a team and extracted the software.
Reverse engineer this strange code, and report back.”

The first step is obviously to determine the format of the file, which I simply used the “file” command for.

The file is a MIPS executable, and due to the following message within it it seems likely that it corresponds to a Cisco 3725 router image:

“Welcome to PPP IOS for C3725!”

Although this challenge certainly could be solved by pure static reversing, it will save a lot of time if we could actually run the code. Since I didn’t have a Cisco router laying around for the task, I used an emulator called Dynamips.

Dynamips has no builtin debugging facilities, but thanks to Sebastian Muñis and Alfredo Ortega of Groundwork Technologies there is a patch available that implements a GDB stub to allow for debugging with GDB, IDA Pro and other debuggers with support for the GDB remote protocol.

For the initial analysis of the binary I used IDA Pro, and could quickly pinpoint the code of interest. Using a combination of static reversing with IDA and debugging with GDB and Dynamips I could determine that the password is actually a numeric PIN, and once the correct PIN is entered, the password required to solve the challenge is decrypted and written to the terminal.

Note that we need a GDB with MIPS support to be able to use GDB for debugging. I used one compiler with mips-idt-elf as its target.

Debugging was extremely slow due to the fact that breakpoints did not seem to work. When a breakpoint was reached I got the following message in the emulator:

It didn’t stop executing though.. So, I used GDB scripting to single-step to the instruction I wanted to break at instead:

To not have to step through the entire boot process I let it execute until the password prompt before breaking out into the debugger with ^C.

Using this technique I simply let it execute until the address where the PIN entered is compared with the expected PIN and extracted the correct PIN from there. Then I could boot up the image again, enter the correct PIN and get the password.

After solving the challenge I came up with a much faster technique, by simply patching the code where I want to break at with an eternal loop. Example below:

I now switch to the console where I’m running the emulator, and enter 12345 as my PIN:

The emulator will now hang on my eternal loop, so I switch back to the debugger and press ^C:

The v1 register contains the PIN I entered (12345), and v0 the expected one (134217728 = 0x8000000). Now I only need to enter the correct PIN to get the password.