예제 #1
0
    def create_function_chain(self, goal, end_address=None):
        """This method returns a ROP chain that will call a function"""
        self.logger.info(
            "Creating function chain for %s(%s) and finishing with a return to %s",
            goal.name,
            ",".join([hex(x) if type(x) != str else x
                      for x in goal.arguments]),
            hex(end_address) if end_address != None else end_address)

        # Holds the ROP chain generated throughout the function
        chain = ""

        # Resolve any string arguments to where we're going to write those arguments too
        argument_strings = {}
        for i in range(len(goal.arguments)):
            arg = goal.arguments[i]
            if type(arg) == str:
                # TODO search the loaded memory for a string in case we're lucky and it already exists in memory
                address = self.get_writable_memory(len(arg))
                argument_strings[arg] = address
                goal.arguments[i] = address

        # Split the arguments into a register and stack arguments
        register_values, stack_arguments = self.split_arguments(
            goal.arguments, end_address)

        # Get a chain to set all the registers
        first_address = goal.address
        if len(register_values) != 0:
            chain, first_address = self.gadget_list.create_load_registers_chain(
                goal.address, self.sp, register_values)
            if chain == None:
                return None, None

        # Add the function's address (and the LR gadget to set the gadget after this function if this architecture requires it)
        if 'lr' not in self.arch.registers and end_address != None:
            chain += utils.ap(end_address, self.arch)

        # Add the stack arguments
        for arg in stack_arguments:
            chain += utils.ap(arg, self.arch)

        # Write any string arguments to memory
        for arg, address in argument_strings.items():
            arg_chain, first_address = self.create_write_memory_chain(
                arg, address, first_address, "\x00")
            chain = arg_chain + chain

        return (chain, first_address)
예제 #2
0
  def create_execve_chain(self, goal):
    """This function returns a ROP chain implemented for a ExecveGoal.  It first writes the arguments for execve, then calls
      execve"""
    argument_addresses = []
    for arg in goal.arguments:
      argument_addresses.append(self.get_writable_memory(len(arg)))
    argv_address = self.get_writable_memory(self.alignment)

    function_goal = go.FunctionGoal(goal.name, goal.address, [argument_addresses[0], argv_address, 0])
    function_chain, next_address = self.create_function_chain(function_goal, 0x4444444444444444)

    chain = ""
    for i in range(len(argument_addresses)):
      packed_args_address = utils.ap(argument_addresses[i], self.arch)
      argv_chain, next_address = self.create_write_memory_chain(packed_args_address, argv_address, next_address, "\x00")
      argv_address += len(packed_args_address)
      chain = argv_chain + chain

    null_chain, next_address = self.create_write_memory_chain("\x00", argv_address, next_address, "\x00")
    chain = null_chain + chain

    for i in range(len(goal.arguments)):
      arg_chain, next_address = self.create_write_memory_chain(goal.arguments[i], argument_addresses[i], next_address, "\x00")
      chain = arg_chain + chain

    return (chain + function_chain), next_address
예제 #3
0
    def chain_gadgets(self):
        """This function returns a ROP chain implemented for the given goals."""
        chain = ""
        next_address = 0x4444444444444444
        for i in range(len(self.goals) - 1, -1, -1):
            goal = self.goals[i]
            if type(goal) == go.FunctionGoal:
                goal_chain, next_address = self.create_function_chain(
                    goal, next_address)
                self.logger.debug(
                    "Function call to %s's first gadget is at 0x%x", goal.name,
                    next_address)
            elif type(goal) == go.ExecveGoal:
                goal_chain, next_address = self.create_execve_chain(goal)
            elif type(goal) == go.ShellcodeAddressGoal:
                goal_chain, next_address = self.create_shellcode_address_chain(
                    goal)
            elif type(goal) == go.ShellcodeGoal:
                goal_chain, next_address = self.create_shellcode_chain(goal)
            else:
                raise RuntimeError("Unknown goal in scheduler.")

            if goal_chain == None:
                raise RuntimeError("Unable to create goal: {}".format(goal))

            chain = goal_chain + chain

        return utils.ap(next_address, self.arch) + chain
예제 #4
0
    def create_execve_chain(self, goal):
        """This function returns a ROP chain implemented for a ExecveGoal.    It first writes the arguments for execve, then calls
            execve"""
        argument_addresses = []
        for arg in goal.arguments:
            argument_addresses.append(self.get_writable_memory(len(arg)))
        argv_address = self.get_writable_memory(self.alignment)

        function_goal = go.FunctionGoal(
            goal.name, goal.address, [argument_addresses[0], argv_address, 0])
        function_chain, next_address = self.create_function_chain(
            function_goal, 0x4444444444444444)

        chain = ""
        for i in range(len(argument_addresses)):
            packed_args_address = utils.ap(argument_addresses[i], self.arch)
            argv_chain, next_address = self.create_write_memory_chain(
                packed_args_address, argv_address, next_address, "\x00")
            argv_address += len(packed_args_address)
            chain = argv_chain + chain

        null_chain, next_address = self.create_write_memory_chain(
            "\x00", argv_address, next_address, "\x00")
        chain = null_chain + chain

        for i in range(len(goal.arguments)):
            arg_chain, next_address = self.create_write_memory_chain(
                goal.arguments[i], argument_addresses[i], next_address, "\x00")
            chain = arg_chain + chain

        return (chain + function_chain), next_address
예제 #5
0
  def create_function_chain(self, goal, end_address = None):
    """This method returns a ROP chain that will call a function"""
    self.logger.info("Creating function chain for %s(%s) and finishing with a return to %s", goal.name,
      ",".join([hex(x) if type(x)!=str else x for x in goal.arguments]), hex(end_address) if end_address != None else end_address)

    # Holds the ROP chain generated throughout the function
    chain = ""

    # Resolve any string arguments to where we're going to write those arguments too
    argument_strings = {}
    for i in range(len(goal.arguments)):
      arg = goal.arguments[i]
      if type(arg) == str:
        # TODO search the loaded memory for a string in case we're lucky and it already exists in memory
        address = self.get_writable_memory(len(arg))
        argument_strings[arg] = address
        goal.arguments[i] = address

    # Split the arguments into a register and stack arguments
    register_values, stack_arguments = self.split_arguments(goal.arguments, end_address)

    # Get a chain to set all the registers
    first_address = goal.address
    if len(register_values) != 0:
      chain, first_address = self.gadget_list.create_load_registers_chain(goal.address, self.sp, register_values)
      if chain == None:
        return None, None

    # Add the function's address (and the LR gadget to set the gadget after this function if this architecture requires it)
    if 'lr' not in self.arch.registers and end_address != None:
      chain += utils.ap(end_address, self.arch)

    # Add the stack arguments
    for arg in stack_arguments:
      chain += utils.ap(arg, self.arch)

    # Write any string arguments to memory
    for arg, address in argument_strings.items():
      arg_chain, first_address = self.create_write_memory_chain(arg, address, first_address, "\x00")
      chain = arg_chain + chain

    return (chain, first_address)
예제 #6
0
  def chain(self, next_address, input_values = None):
    chain = ""
    input_from_stack = self._is_stack_reg(self.inputs[0]) and input_values[0] != None

    # If our input value is coming from the stack, and it's supposed to come before the next PC address, add it to the chain now
    if input_from_stack and (self.ip_in_stack_offset == None or self.params[0] < self.ip_in_stack_offset):
      chain += self.params[0] * "L"
      chain += utils.ap(input_values[0], self.arch)

    if self.ip_in_stack_offset != None:
      chain += (self.ip_in_stack_offset - len(chain)) * "M"
      chain += utils.ap(next_address, self.arch)

    # If our input value is coming from the stack, and it's supposed to come after the next PC address, add it to the chain now
    if input_from_stack and self.ip_in_stack_offset != None and self.params[0] > self.ip_in_stack_offset:
      chain += (self.params[0] - len(chain)) * "N"
      chain += utils.ap(input_values[0], self.arch)

    chain += (self.stack_offset - len(chain)) * "O"
    return chain
예제 #7
0
파일: gadget.py 프로젝트: lxpe/rop_compiler
  def chain(self, next_address, input_values = None):
    chain = ""
    input_from_stack = self._is_stack_reg(self.inputs[0]) and input_values[0] != None

    # If our input value is coming from the stack, and it's supposed to come before the next PC address, add it to the chain now
    if input_from_stack and (self.ip_in_stack_offset == None or self.params[0] < self.ip_in_stack_offset):
      chain += self.params[0] * "L"
      chain += utils.ap(input_values[0], self.arch)

    if self.ip_in_stack_offset != None:
      chain += (self.ip_in_stack_offset - len(chain)) * "M"
      chain += utils.ap(next_address, self.arch)

    # If our input value is coming from the stack, and it's supposed to come after the next PC address, add it to the chain now
    if input_from_stack and self.ip_in_stack_offset != None and self.params[0] > self.ip_in_stack_offset:
      chain += (self.params[0] - len(chain)) * "N"
      chain += utils.ap(input_values[0], self.arch)

    chain += (self.stack_offset - len(chain)) * "O"
    return chain
예제 #8
0
    def chain(self, next_address, input_values=None):
        if (input_values is None) or input_values == (None, None):
            return "", self.address

        gtrue, gfalse = self.branches
        if gtrue.ip_in_stack_offset is None and gfalse.ip_in_stack_offset is None:
            chain = ""
        elif gtrue.ip_in_stack_offset is not None and gfalse.ip_in_stack_offset is not None:
            btrue, bfalse = input_values
            if gtrue.ip_in_stack_offset < gfalse.ip_in_stack_offset:
                gmax, gmin = (gfalse.ip_in_stack_offset,
                              gtrue.ip_in_stack_offset)
                bmax, bmin = (bfalse, btrue)
            else:
                gmax, gmin = (gtrue.ip_in_stack_offset,
                              gfalse.ip_in_stack_offset)
                bmax, bmin = (btrue, bfalse)

            chain = gmin * "P"
            chain += utils.ap(bmin, self.arch)
            chain += (gmax - len(chain)) * "O"
            chain += utils.ap(bmax, self.arch)
            chain += (self.stack_offset - len(chain)) * "I"

        else:
            if gtrue.ip_in_stack_offset is not None:
                br = input_values[0]
                ip_offset = gtrue.ip_in_stack_offset
            else:
                br = input_values[1]
                ip_offset = gfalse.ip_in_stack_offset
            if not type(br) in [int, long]:
                raise RuntimeError(
                    "For chaining JCC, int or long values are expected")

            chain = ip_offset * "P"
            chain += utils.ap(br, self.arch)
            chain += (self.stack_offset - len(chain)) * "O"

        return chain
예제 #9
0
  def chain(self, next_address, input_values):
    ip_added = False

    # if the registers and ip are on the stack, we have to intermingle them
    if self._is_stack_reg(self.inputs[0]):
      # Get the order to set the registers
      regs_to_params = []
      for i in range(len(self.outputs)):
        regs_to_params.append((self.params[i], self.outputs[i], i))
      regs_to_params.sort()

      chain = ""
      for param, reg, output_idx in regs_to_params:
        before_ip_on_stack = self.ip_in_stack_offset == None or param < self.ip_in_stack_offset

        # If our input value is coming from the stack, and it's supposed to come before the next PC address, add it to the chain now
        if before_ip_on_stack:
          chain += (param - len(chain)) * "P"
          chain += utils.ap(input_values[output_idx], self.arch)

        if self.ip_in_stack_offset != None and not ip_added and not before_ip_on_stack:
          chain += (self.ip_in_stack_offset - len(chain)) * "Q"
          chain += utils.ap(next_address, self.arch)
          ip_added = True

        # If our input value is coming from the stack, and it's supposed to come after the next PC address, add it to the chain now
        if not before_ip_on_stack:
          chain += (param - len(chain)) * "R"
          chain += utils.ap(input_values[output_idx], self.arch)

    # if the IP hasn't already been set, add it now
    if self.ip_in_stack_offset != None and not ip_added:
      chain += (self.ip_in_stack_offset - len(chain)) * "S"
      chain += utils.ap(next_address, self.arch)
    chain += (self.stack_offset - len(chain)) * "T"
    return chain
예제 #10
0
파일: gadget.py 프로젝트: lxpe/rop_compiler
  def chain(self, next_address, input_values):
    ip_added = False

    # if the registers and ip are on the stack, we have to intermingle them
    if self._is_stack_reg(self.inputs[0]):
      # Get the order to set the registers
      regs_to_params = []
      for i in range(len(self.outputs)):
        regs_to_params.append((self.params[i], self.outputs[i], i))
      regs_to_params.sort()

      chain = ""
      for param, reg, output_idx in regs_to_params:
        before_ip_on_stack = self.ip_in_stack_offset == None or param < self.ip_in_stack_offset

        # If our input value is coming from the stack, and it's supposed to come before the next PC address, add it to the chain now
        if before_ip_on_stack:
          chain += (param - len(chain)) * "P"
          chain += utils.ap(input_values[output_idx], self.arch)

        if self.ip_in_stack_offset != None and not ip_added and not before_ip_on_stack:
          chain += (self.ip_in_stack_offset - len(chain)) * "Q"
          chain += utils.ap(next_address, self.arch)
          ip_added = True

        # If our input value is coming from the stack, and it's supposed to come after the next PC address, add it to the chain now
        if not before_ip_on_stack:
          chain += (param - len(chain)) * "R"
          chain += utils.ap(input_values[output_idx], self.arch)

    # if the IP hasn't already been set, add it now
    if self.ip_in_stack_offset != None and not ip_added:
      chain += (self.ip_in_stack_offset - len(chain)) * "S"
      chain += utils.ap(next_address, self.arch)
    chain += (self.stack_offset - len(chain)) * "T"
    return chain
예제 #11
0
  def chain_gadgets(self):
    """This function returns a ROP chain implemented for the given goals."""
    chain = ""
    next_address = 0x4444444444444444
    for i in range(len(self.goals) - 1, -1, -1):
      goal = self.goals[i]
      if type(goal) == go.FunctionGoal:
        goal_chain, next_address = self.create_function_chain(goal, next_address)
        self.logger.debug("Function call to %s's first gadget is at 0x%x", goal.name, next_address)
      elif type(goal) == go.ExecveGoal:
        goal_chain, next_address = self.create_execve_chain(goal)
      elif type(goal) == go.ShellcodeAddressGoal:
        goal_chain, next_address = self.create_shellcode_address_chain(goal)
      elif type(goal) == go.ShellcodeGoal:
        goal_chain, next_address = self.create_shellcode_chain(goal)
      else:
        raise RuntimeError("Unknown goal in scheduler.")

      if goal_chain == None:
        raise RuntimeError("Unable to create goal: {}".format(goal))

      chain = goal_chain + chain

    return utils.ap(next_address, self.arch) + chain
예제 #12
0
 def chain(self, next_address, input_values = None):
   """Default ROP Chain generation, uses no parameters"""
   chain = self.ip_in_stack_offset * "I"
   chain += utils.ap(next_address, self.arch)
   chain += (self.stack_offset - len(chain)) * "J"
   return chain
예제 #13
0
파일: gadget.py 프로젝트: lxpe/rop_compiler
 def chain(self, next_address, input_values = None):
   """Default ROP Chain generation, uses no parameters"""
   chain = self.ip_in_stack_offset * "I"
   chain += utils.ap(next_address, self.arch)
   chain += (self.stack_offset - len(chain)) * "J"
   return chain
예제 #14
0
  def create_read_add_jmp_function_chain(self, address, offset, arguments, end_address):
    """This method creates a ROP chain that will read from a specified address, apply an offset, and then call that address with
      a set of provided arguments"""

    jump_gadget = arg_chain = arg_chain_address = None
    stack_arguments = []

    # First, look for all the needed gadgets
    original_offset = offset
    for jump_reg in self.get_all_registers():
      read_gadget = set_read_addr_gadget = None
      for addr_reg in self.get_all_registers():
        if addr_reg == jump_reg: continue

        # Find a gadget to read from memory
        read_gadget = self.gadget_list.find_gadget(ga.LoadMem, [addr_reg], [jump_reg])
        if read_gadget == None:
          continue

        # Then find a gadget that will let you set the address register for that read
        set_read_addr_gadget = self.gadget_list.find_load_stack_gadget(read_gadget.inputs[0], [jump_reg])
        if set_read_addr_gadget == None:
          continue
        break

      if set_read_addr_gadget == None or read_gadget == None:
        continue

      # Then find a gadget that will let you jump to that register
      jump_gadget = self.gadget_list.find_gadget(ga.Jump, [jump_reg])
      if jump_gadget == None:
        continue

      add_jump_reg_gadget = set_add_reg_gadget = None
      for add_reg in self.get_all_registers():
        offset = original_offset
        if add_reg == jump_reg: continue

        # Then find a gadget that will let you add to that register
        add_jump_reg_gadget = self.gadget_list.find_gadget(ga.AddGadget, [jump_reg, add_reg], [jump_reg])
        if add_jump_reg_gadget == None: # If we can't find an AddGadget, try finding a SubGadget and negating
          add_jump_reg_gadget = self.gadget_list.find_gadget(ga.SubGadget, [jump_reg, add_reg], [jump_reg])
          offset = -offset
          if add_jump_reg_gadget == None:
            continue

        # Next, find a gadget that will let you set what you're adding to that register
        set_add_reg_gadget = self.gadget_list.find_load_stack_gadget(add_reg, [jump_reg])
        if set_add_reg_gadget == None:
          continue
        break

      if add_jump_reg_gadget == None:
        continue

      # Split the arguments into a register and stack arguments
      register_values, stack_arguments = self.split_arguments(arguments, end_address)

      # Create a chain to set all the registers, while avoiding clobbering our jump register
      if len(register_values) != 0:
        arg_chain, arg_chain_address = self.gadget_list.create_load_registers_chain(jump_gadget.address, self.sp, register_values, [jump_reg])
      else:
        arg_chain, arg_chain_address = "", jump_gadget.address

      if arg_chain != None:
        break

    # Couldn't find all the necessary gadgets
    if arg_chain == None:
      return (None, None)

    self.print_gadgets("Found all necessary gadgets for reading the GOT and " +
      "calling a different function with 0x{:x} bytes argument gadgets:".format(len(arg_chain)),
      [set_read_addr_gadget, read_gadget, set_add_reg_gadget, add_jump_reg_gadget, jump_gadget])

    # Build the chain
    chain = set_read_addr_gadget.chain(read_gadget.address, [address - read_gadget.params[0]]) # set the read address
    chain += read_gadget.chain(set_add_reg_gadget.address)                                     # read the address in the GOT
    chain += set_add_reg_gadget.chain(add_jump_reg_gadget.address, [offset])                   # set the offset from the base to the target
    chain += add_jump_reg_gadget.chain(arg_chain_address)                                      # add the offset
    chain += arg_chain                                                                         # set the arguments for the function

    # Add the jump to the function, and the stack based return address (if this architecture uses it)
    chain += jump_gadget.chain()
    if 'lr' not in self.arch.registers and end_address != None:
      chain += utils.ap(end_address, self.arch)

    # Last, add the stack arguments
    for arg in stack_arguments:
      chain += utils.ap(arg, self.arch)

    return (chain, set_read_addr_gadget.address)
예제 #15
0
    def create_read_add_jmp_function_chain(self, address, offset, arguments,
                                           end_address):
        """This method creates a ROP chain that will read from a specified address, apply an offset, and then call that address with
            a set of provided arguments"""

        jump_gadget = arg_chain = arg_chain_address = None
        stack_arguments = []

        # First, look for all the needed gadgets
        original_offset = offset
        for jump_reg in self.get_all_registers():
            read_gadget = set_read_addr_gadget = None
            for addr_reg in self.get_all_registers():
                if addr_reg == jump_reg: continue

                # Find a gadget to read from memory
                read_gadget = self.gadget_list.find_gadget(
                    ga.LoadMem, [addr_reg], [jump_reg])
                if read_gadget == None:
                    continue

                # Then find a gadget that will let you set the address register for that read
                set_read_addr_gadget = self.gadget_list.find_load_stack_gadget(
                    read_gadget.inputs[0], [jump_reg])
                if set_read_addr_gadget == None:
                    continue
                break

            if set_read_addr_gadget == None or read_gadget == None:
                continue

            # Then find a gadget that will let you jump to that register
            jump_gadget = self.gadget_list.find_gadget(ga.Jump, [jump_reg])
            if jump_gadget == None:
                continue

            add_jump_reg_gadget = set_add_reg_gadget = None
            for add_reg in self.get_all_registers():
                offset = original_offset
                if add_reg == jump_reg: continue

                # Then find a gadget that will let you add to that register
                add_jump_reg_gadget = self.gadget_list.find_gadget(
                    ga.AddGadget, [jump_reg, add_reg], [jump_reg])
                if add_jump_reg_gadget == None:  # If we can't find an AddGadget, try finding a SubGadget and negating
                    add_jump_reg_gadget = self.gadget_list.find_gadget(
                        ga.SubGadget, [jump_reg, add_reg], [jump_reg])
                    offset = -offset
                    if add_jump_reg_gadget == None:
                        continue

                # Next, find a gadget that will let you set what you're adding to that register
                set_add_reg_gadget = self.gadget_list.find_load_stack_gadget(
                    add_reg, [jump_reg])
                if set_add_reg_gadget == None:
                    continue
                break

            if add_jump_reg_gadget == None:
                continue

            # Split the arguments into a register and stack arguments
            register_values, stack_arguments = self.split_arguments(
                arguments, end_address)

            # Create a chain to set all the registers, while avoiding clobbering our jump register
            if len(register_values) != 0:
                arg_chain, arg_chain_address = self.gadget_list.create_load_registers_chain(
                    jump_gadget.address, self.sp, register_values, [jump_reg])
            else:
                arg_chain, arg_chain_address = "", jump_gadget.address

            if arg_chain != None:
                break

        # Couldn't find all the necessary gadgets
        if arg_chain == None:
            return (None, None)

        self.print_gadgets(
            "Found all necessary gadgets for reading the GOT and " +
            "calling a different function with 0x{:x} bytes argument gadgets:".
            format(len(arg_chain)), [
                set_read_addr_gadget, read_gadget, set_add_reg_gadget,
                add_jump_reg_gadget, jump_gadget
            ])

        # Build the chain
        chain = set_read_addr_gadget.chain(
            read_gadget.address,
            [address - read_gadget.params[0]])  # set the read address
        chain += read_gadget.chain(
            set_add_reg_gadget.address)  # read the address in the GOT
        chain += set_add_reg_gadget.chain(
            add_jump_reg_gadget.address,
            [offset])  # set the offset from the base to the target
        chain += add_jump_reg_gadget.chain(arg_chain_address)  # add the offset
        chain += arg_chain  # set the arguments for the function

        # Add the jump to the function, and the stack based return address (if this architecture uses it)
        chain += jump_gadget.chain()
        if 'lr' not in self.arch.registers and end_address != None:
            chain += utils.ap(end_address, self.arch)

        # Last, add the stack arguments
        for arg in stack_arguments:
            chain += utils.ap(arg, self.arch)

        return (chain, set_read_addr_gadget.address)
예제 #16
0
 def chain(self, next_address, input_values=None):
     return utils.ap(self.address, self.arch)