def find_double_jumps(rop_finder, allow_double=True, allow_iret=True, verbose=False): """ Find gadgets that call a function and maintain control to jump to the next gadget. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :returns: Gadgets found. :rtype: list(mipsrop.RopGadget + mipsrop.DoubleGadget) """ gadgets = [] if allow_double: doubles = rop_finder.find_doubles() gadgets.extend(doubles.gadgets) if allow_iret: move_t9 = mipsrop.MipsInstruction('move', 't9', '[sav][012345678]') irets = rop_finder.find_instructions([move_t9], controllable_calls=False, overwrite_register=['ra']) gadgets.extend(irets.gadgets) if verbose: print 'Found %d gadgets to call sleep and maintain control' % len( gadgets) return gadgets
def find_epilogue(rop_finder, controlled_registers): """ Find epilogues that grant control of each register. Will only return epilogues that grant control over more registers than originally used. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :param controlled_registers: Registers controlled. :type controlled_registers: list(str) :returns: Gadgets found. :rtype: list(mipsrop.RopGadgets) """ epilogue = mipsrop.MipsInstruction('.*lw', 'ra') function_epilogue = [] for i in range(0, len(mipsropchain.REGISTERS)): control_registers = mipsropchain.REGISTERS[:i + 1] if all(reg in controlled_registers for reg in control_registers): continue epilogue_gadget = rop_finder.find_instructions( [epilogue], controllable_calls=False, overwrite_register=control_registers, preserve_register=mipsropchain.REGISTERS[i + 1:]) if epilogue_gadget.gadgets: function_epilogue.append(epilogue_gadget.gadgets[0]) return function_epilogue
def find_stack_finders(rop_finder, terminating, controllable, verbose): """ Find gadgets that move a stack pointer to a register. Movement to a0 is specifically ignored because the system gadget finder does that. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :param terminating: Return tail gadgets. :type terminating: bool :param controllable: Return controllable calls. :type controllable: bool :param verbose: Enable verbose output. :type verbose: bool :returns: Gadgets found. :rtype: list(mipsrop.RopGadget) """ sf_saved_reg = mipsrop.MipsInstruction('.*addiu', '[sva][012345678]', 'sp') stack_finders = rop_finder.find_instructions( [sf_saved_reg], terminating_calls=terminating, controllable_calls=controllable) if verbose: print 'Found %d gadgets to find shellcode on the stack.' % \ len(stack_finders.gadgets) return stack_finders.gadgets
def find_epilogue(rop_finder, controlled_registers): """ Find epilogues that grant control of each register. Ideal will return nine gadgets one that gives control of s0, one that gives control of s0 and s1, one that gives control of s0/s1/s2, etc. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :returns: Gadgets found. :rtype: list(mipsrop.RopGadgets) """ epilogue = mipsrop.MipsInstruction('.*lw', 'ra') function_epilogue = [] for i in range(0, len(mipsropchain.REGISTERS)): control_registers = mipsropchain.REGISTERS[:i + 1] if all(reg in controlled_registers for reg in control_registers): continue epilogue_gadget = rop_finder.find_instructions( [epilogue], controllable_calls=False, overwrite_register=control_registers, preserve_register=mipsropchain.REGISTERS[i + 1:]) if epilogue_gadget.gadgets: function_epilogue.append(epilogue_gadget.gadgets[0]) return function_epilogue
def find_system_calls(rop_finder, terminating, controllable, verbose): """ Find single gadget chains to call system with a controllable string in a0. :param rop_finder: MIPS rop finder class. :type rop_finder: mipsrop.MipsRop :param terminating: Return tail gadgets. :type terminating: bool :param controllable: Return controllable calls. :type controllable: bool :param verbose: Enable verbose output. :type verbose: bool :returns: Discovered gadgets :rtype: list(mipsrop.RopGadgets) """ system_call = mipsrop.MipsInstruction('.*addiu', 'a0', 'sp') stack_finders = rop_finder.find_instructions( [system_call], terminating_calls=terminating, controllable_calls=controllable) if verbose: print 'Found %d gadgets to call system.' % \ len(stack_finders.gadgets) return stack_finders.gadgets
def find_shellcode_jump(rop_finder, verbose): """ Find gadgets that call a register. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :returns: Gadgets found. :rtype: list(mipsrop.RopGadget) """ move_t9 = mipsrop.MipsInstruction('mov', 't9') call_register = rop_finder.find_instructions([move_t9]) if verbose: print 'Found %d gadgets to call shellcode.' % len( call_register.gadgets) return call_register.gadgets
def find_lia0_calls(rop_finder, vebose): """ Find calls the load a value smaller than 16 into $a0. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :returns: Gadgets found. :rtype: list(mipsrop.RopGadget) """ li_a0 = mipsrop.MipsInstruction('.*li', 'a0', '0x[0-9a-f]') small_value = rop_finder.find_instructions([li_a0]) if verbose: print 'Found %d gadgets to load a small value into a0' % \ len(small_value.gadgets) return small_value.gadgets
def find_stack_finders(rop_finder, verbose): """ Find gadgets that move a stack pointer to a register. :param rop_finder: Mips rop finder class. :type rop_finder: mipsrop.MipsRop :returns: Gadgets found. :rtype: list(mipsrop.RopGadget) """ sf_saved_reg = mipsrop.MipsInstruction('.*addiu', '[sva][012345678]', 'sp') stack_finder_gadgets = rop_finder.find_instructions( [sf_saved_reg], terminating_calls=False) if verbose: print 'Found %d gadgets to find shellcode on the stack.' % \ len(stack_finder_gadgets.gadgets) return stack_finder_gadgets.gadgets
def system_tail_two_jump(chain_builder, mips_rop): """ Search for chain that moves a stack string to a0 in a tail call. :param chain_builder: Initialized chain builder class. :type chain_builder: mipsropchain.ChainBuilder :param mips_rop: Mips rop finder class. :type mips_rop: mipsrop.MipsRop """ stack_finders = find_system_calls(mips_rop, True, False, verbose) chain_builder.add_gadgets('Find command on the stack from tail call', stack_finders) move_t9 = mipsrop.MipsInstruction('mov', 't9') call_register = mips_rop.find_instructions([move_t9], preserve_register='a0', terminating_calls=False) chain_builder.add_gadgets('Call system.', call_register.gadgets) chain_builder.generate_chain() chain_builder.gadgets = []
def find_move_a0(rop_finder, verbose): """ Find gadget that moves a register to a0. :param rop_finder: MIPS rop finder class. :type rop_finder: mipsrop.MipsRop :param verbose: Enable verbose output. :type verbose: bool :returns: Discovered gadgets :rtype: list(mipsrop.RopGadgets) """ move_a0_ins = mipsrop.MipsInstruction('.*move', 'a0', '[sva][012345678]') # System cannot be called from an epilogue. $gp is calculated based on the # call occurring from $t9. move_a0 = rop_finder.find_instructions([move_a0_ins], terminating_calls=False) if verbose: print 'Found %d gadgets to move a register to $a0.' % \ len(move_a0.gadgets) return move_a0.gadgets
# Find MIPS ROP gadgets for gaining control of more registers through function epilogues. #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Gadgets.Epilogue from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') registers = ['s0', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8'] min_reg = askChoice('Minimum Register', 'What is the lowest register you want to control?', ['Any'] + registers, 'Any') if min_reg == 'Any': min_reg = None if min_reg: print 'Searching for function epilogues that grant control of registers up to %s...' % min_reg epilogue = mipsrop.MipsInstruction('.*lw', 'ra') mips_rop = mipsrop.MipsRop(currentProgram) function_epilogue = mips_rop.find_instructions( [epilogue], overwrite_register=registers[:registers.index(min_reg) + 1], controllable_calls=False) function_epilogue.pretty_print()
# Find MIPS ROP gadgets that load a small value into a0. Useful for calling sleep. #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Gadgets.Li a0 from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') li_a0 = mipsrop.MipsInstruction('.*li', 'a0', '0x.*') mips_rop = mipsrop.MipsRop(currentProgram) sleep_calls = mips_rop.find_instructions([li_a0]) sleep_calls.pretty_print()
# Find MIPS ROP gadgets that perform an indirect return. (Call t9, return to ra.) #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Gadgets.Indirect Return from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') move_t9 = mipsrop.MipsInstruction('move', 't9', '[sav][012345678]') mips_rop = mipsrop.MipsRop(currentProgram) indirect_returns = mips_rop.find_instructions([move_t9], controllable_calls=False, overwrite_register=['ra']) indirect_returns.pretty_print()
# Find MIPS ROP gadgets near the beginning of functions that allow for stack pointer movement. #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Gadgets.Prologue from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') prologue = mipsrop.MipsInstruction('.*addiu', 'sp', 'sp', '-.*') mips_rop = mipsrop.MipsRop(currentProgram) function_prologue = mips_rop.find_instructions([prologue]) function_prologue.pretty_print()
# Find MIPS ROP gadgets for calling system with a user controlled argument. #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Gadgets.System Calls from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') set_a0 = mipsrop.MipsInstruction('.*addiu', 'a0', 'sp') mips_rop = mipsrop.MipsRop(currentProgram) system_rops = mips_rop.find_instructions([set_a0], 'a0', terminating_calls=False) system_rops.pretty_print()
import re from utils import mipsrop, utils utils.allowed_processors(currentProgram, 'MIPS') op1 = None op2 = None op3 = None search = askString('MIPS ROP Find', 'What instruction do you want to search for?') try: search = re.sub(' +', ' ', search) mnem, operands = search.split(' ', 1) operands = operands.replace(' ', '') operands = operands.split(',') op1, op2, op3 = operands + [None] * (3 - len(operands)) except ValueError: mnem = search if not mnem.startswith('.*'): mnem = '.*' + mnem search_ins = mipsrop.MipsInstruction(mnem, op1, op2, op3) mips_rop = mipsrop.MipsRop(currentProgram) indirect_returns = mips_rop.find_instructions([search_ins]) indirect_returns.pretty_print()
# Find MIPS ROP gadgets that put a stack address in a register. #@author fuzzywalls #@category TNS #@menupath TNS.Mips Rops.Stack Finder from utils import mipsrop sf_saved_reg = mipsrop.MipsInstruction('.*addiu', '[sva][012345678]', 'sp') mips_rop = mipsrop.MipsRop(currentProgram) stack_finders = mips_rop.find_instructions([sf_saved_reg]) stack_finders.pretty_print()