diff --git a/ropper/arch.py b/ropper/arch.py index 6d27fe9..af89f85 100644 --- a/ropper/arch.py +++ b/ropper/arch.py @@ -30,7 +30,7 @@ from ropper.common.enum import Enum from ropper.common.error import NotSupportedError from ropper.search import Searcher, Searcherx86, SearcherARM, SearcherMIPS -from re import compile +import re from capstone import * from . import gadget try: @@ -72,6 +72,7 @@ def __init__(self, arch, mode, addressLength, align, endianess=Endianess.LITTLE, self._align = align self._endings = {} + self._endings_re = None self._badInstructions = [] self._categories = {} self._maxInvalid = 1 @@ -137,7 +138,13 @@ def addressLength(self): @property def endings(self): return self._endings - + + @property + def endings_re(self): + if not self._endings_re: + self._endings_re = {key: [(re.compile(x), y) for x, y in value] for key, value in self.endings.items()} + return self._endings_re + @property def badInstructions(self): return self._badInstructions @@ -202,8 +209,8 @@ def pprs(self): def _initGadgets(self): super(ArchitectureX86, self)._initGadgets() - self._endings[gadget.GadgetType.ROP] = [(b'\xc3', 1), # ret - (b'\xc2[\x00-\xff]{2}', 3)] # ret xxx + self._endings[gadget.GadgetType.ROP] = [(b'[\xc3|\xcb]', 1), # ret + (b'[\xc2|\xca][\x00-\xff]{2}', 3)] # ret xxx self._endings[gadget.GadgetType.SYS] = [(b'\xcd\x80', 2), # int 0x80 (b'\x0f\x05',2), # syscall @@ -383,11 +390,16 @@ def __init__(self, endianess=Endianess.LITTLE): def _initGadgets(self): super(ArchitectureArm, self)._initGadgets() - self._endings[gadget.GadgetType.ROP] = [(b'[\x01-\xff]\x80\xbd\xe8', 4)] # pop {[reg]*,pc} - self._endings[gadget.GadgetType.JOP] = [(b'[\x10-\x1e]\xff\x2f\xe1', 4), # bx - (b'[\x30-\x3e]\xff\x2f\xe1', 4), # blx + self._endings[gadget.GadgetType.ROP] = [((b'[\x00-\xff][\x80-\xff]' + # pc + any reg + b'[\xbd\xfd]' + # u=1, s=0, w=1, l=1, Rn=1101 (sp) + b'[\xe8\xe9]'), 4)] # e=undconditional, 8/9=opcode+pre/post indexing bit set to anything + self._endings[gadget.GadgetType.JOP] = [(b'[\x10-\x19\x1e]{1}\xff\x2f\xe1', 4), # bx + (b'[\x30-\x39\x3e]{1}\xff\x2f\xe1', 4), # blx (b'[\x00-\x0f]\xf0\xa0\xe1', 4), # mov pc, - (b'\x01\x80\xbd\xe8', 4)] # ldm sp! ,{pc} + # ldm anything not sp into pc + ((b'[\x00-\xff][\x80-\xff]' + # pc + any reg + b'[\x10-\x1c\x1e\x30-\x3c\x3e\x50-\x5c\x5e\x70-\x7c\x7e\x90-\x9c\x9e\xb0-\xbc\xbe\xd0-\xdc\xde\xf0-\xfc\xfe]' + # u=0/1, s=0/1, w=0/1, l=1, Rn=anything but sp or pc + b'[\xe8\xe9]'), 4)] # e=undconditional, 8/9=opcode+pre/post indexing bit set to anything class ArchitectureArmBE(ArchitectureArm): @@ -401,11 +413,17 @@ def __init__(self): def _initEndianess(self, endianess): super(ArchitectureArmBE, self)._initEndianess(endianess) - self._endings[gadget.GadgetType.ROP] = [(b'\xe8\xbd\x80[\x01-\xff]', 4)] # pop {[reg]*,pc} - self._endings[gadget.GadgetType.JOP] = [(b'\xe1\x2f\xff[\x10-\x1e]', 4), # bx - (b'\xe1\x2f\xff[\x30-\x3e]', 4), # blx + self._endings[gadget.GadgetType.ROP] = [((b'[\xe8\xe9]' + # e=unconditional, 8/9=opcode+pre/post indexing bit set to anything + b'[\xbd\xfd]' + # u=1, s=0/1, w=1, l=1, Rn=1101 (sp) + b'[\x80-\xff][\x00-\xff]'), 4)] # pc + any reg + self._endings[gadget.GadgetType.JOP] = [(b'\xe1\x2f\xff[\x10-\x19\x1e]{1}', 4), # bx + (b'\xe1\x2f\xff[\x30-\x39\x3e]{1}', 4), # blx (b'\xe1\xa0\xf0[\x00-\x0f]', 4), # mov pc, - (b'\xe8\xdb\x80\x01', 4)] # ldm sp! ,{pc} + # ldm anything not sp into pc + ((b'[\xe8\xe9]' + # e=unconditional, 8/9=opcode+pre/post indexing bit set to anything + b'[\x10-\x1c\x1e\x30-\x3c\x3e\x50-\x5c\x5e\x70-\x7c\x7e\x90-\x9c\x9e\xb0-\xbc\xbe\xd0-\xdc\xde\xf0-\xfc\xfe]' + # u=0/1, s=0/1, w=0/1, l=1, Rn=anything but sp or pc + b'[\x80-\xff][\x00-\xff]'), 4)] # pc + any reg + class ArchitectureArmThumb(Architecture): @@ -423,14 +441,12 @@ def __init__(self): def _initGadgets(self): super(ArchitectureArmThumb, self)._initGadgets() - self._endings[gadget.GadgetType.ROP] = [(b'[\x00-\xff]\xbd', 2)] # pop {[regs]*,pc} + self._endings[gadget.GadgetType.ROP] = [(b'[\x80-\xff]\xbd', 2)] # pop {[regs]*,pc} self._endings[gadget.GadgetType.JOP] = [(b'[\x00-\x7f]\x47', 2), # bx (b'[\x80\x88\x90\x98\xa0\xa8\xb0\xb8\xc0\xc8\xd0\xd8\xe0\xe8\xf0\xf8]\x47', 2) # blx ] - - class ArchitectureArm64(Architecture): def __init__(self): diff --git a/ropper/rop.py b/ropper/rop.py index 6c5722d..0ed752d 100644 --- a/ropper/rop.py +++ b/ropper/rop.py @@ -454,22 +454,33 @@ def __gatherGadgetsByEnding(self, code, arch, fileName, sectionName, offset, end def __createGadget(self, arch, code_str, codeStartAddress, ending, binary=None, section=None): gadget = Gadget(binary, section, arch) hasret = False - if codeStartAddress == 0x0000000001b34d74: - print("found") disassembler = self.__getCs(arch) + on_delay_slot = False + for inst in disassembler.disasm(code_str, codeStartAddress+gadget.imageBase): + if on_delay_slot: + gadget.append(inst.address-gadget.imageBase, inst.mnemonic,inst.op_str, bytes=inst.bytes) + break - for i in disassembler.disasm(code_str, codeStartAddress): - if re.match(ending[0], i.bytes): + if re.match(ending[0], inst.bytes): hasret = True + + if hasret or inst.mnemonic not in arch.badInstructions: + gadget.append(inst.address-gadget.imageBase, inst.mnemonic,inst.op_str, bytes=inst.bytes) + + if hasret: + if arch.hasBranchDelaySlot: + on_delay_slot = True + continue + else: + break - if hasret or i.mnemonic not in arch.badInstructions: - gadget.append( - i.address, i.mnemonic,i.op_str, bytes=i.bytes) - - if (hasret and not arch.hasBranchDelaySlot) or i.mnemonic in arch.badInstructions: + if i.mnemonic in arch.badInstructions: break - - + + for rop_endings in arch.endings_re[GadgetType.ROP]: + if rop_endings[0].match(inst.bytes): + # anything before this (including this instr) isn't part of this gadget, go back and try again + return None, -1 leng = len(gadget) if hasret and leng > 0: