diff --git a/ropper/arch.py b/ropper/arch.py index 6d27fe9..bb79b96 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): @@ -429,8 +447,6 @@ def _initGadgets(self): ] - - class ArchitectureArm64(Architecture): def __init__(self): diff --git a/ropper/rop.py b/ropper/rop.py index 6c5722d..2eb80a0 100644 --- a/ropper/rop.py +++ b/ropper/rop.py @@ -454,19 +454,28 @@ 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) - - for i in disassembler.disasm(code_str, codeStartAddress): - if re.match(ending[0], i.bytes): + instrs = list(disassembler.disasm(code_str, codeStartAddress+gadget.imageBase)) + for i, inst in enumerate(instrs): + + if re.match(ending[0], inst.bytes): hasret = True - if hasret or i.mnemonic not in arch.badInstructions: - gadget.append( - i.address, i.mnemonic,i.op_str, bytes=i.bytes) + reset_gadget = False + if i != len(instrs)-1: + for ending2 in arch.endings_re[GadgetType.ROP]: + if ending2[0].match(inst.bytes): + # anything before this (including this instr) isn't part of this gadget + reset_gadget = True + break + if reset_gadget: + gadget = Gadget(binary, section, arch) + continue + + 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 and not arch.hasBranchDelaySlot) or i.mnemonic in arch.badInstructions: + if (hasret and not arch.hasBranchDelaySlot) or inst.mnemonic in arch.badInstructions: break