Esempio n. 1
0
    def test_badbytes(self):
        r = Ropper()

        badbytes = "adfd"
        gadgets = r.searchGadgets(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0x1ADFD)

        badbytes = "52f8"
        gadgets = r.searchPopPopRet(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        self.assertNotEqual(gadgets[0].lines[0][0], 0x52F8)

        badbytes = "b1c7"
        gadgets = r.searchJmpReg(self.file, ["rsp"])
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0xB1C7)

        with self.assertRaises(RopperError):
            badbytes = "b1c"
            gadgets = ropper.filterBadBytes(gadgets, badbytes)

        with self.assertRaises(RopperError):
            badbytes = "qwer"
            gadgets = ropper.filterBadBytes(gadgets, badbytes)
Esempio n. 2
0
    def test_badbytes(self):
        r = Ropper()

        badbytes = 'adfd'
        gadgets = r.searchGadgets(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0x1adfd)

        badbytes = '52f8'
        gadgets = r.searchPopPopRet(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        self.assertNotEqual(gadgets[0].lines[0][0], 0x52f8)

        badbytes = 'b1c7'
        gadgets = r.searchJmpReg(self.file, ['rsp'])
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0xb1c7)

        with self.assertRaises(RopperError):
            badbytes = 'b1c'
            gadgets = ropper.filterBadBytes(gadgets, badbytes)

        with self.assertRaises(RopperError):
            badbytes = 'qwer'
            gadgets = ropper.filterBadBytes(gadgets, badbytes)
Esempio n. 3
0
    def test_badbytes(self):
        r = Ropper()

        badbytes = 'adfd'
        gadgets = r.searchGadgets(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0x1adfd)

        badbytes = '52f8'
        gadgets = r.searchPopPopRet(self.file)
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        self.assertNotEqual(gadgets[0].lines[0][0], 0x52f8)

        badbytes = 'b1c7'
        gadgets = r.searchJmpReg(self.file, ['rsp'])
        gadgets = ropper.filterBadBytes(gadgets, badbytes)
        gadget = gadgets[0]
        self.assertNotEqual(gadget.lines[0][0], 0xb1c7)

        with self.assertRaises(RopperError):
            badbytes = 'b1c'
            gadgets = ropper.filterBadBytes(gadgets, badbytes)

        with self.assertRaises(RopperError):
            badbytes = 'qwer'
            gadgets = ropper.filterBadBytes(gadgets, badbytes)
Esempio n. 4
0
    def __searchGadgets(self, binary):
        r = Ropper(self.__cprinter)
        gadgets = r.searchGadgets(binary, depth=self.__options.depth, gtype=GadgetType[self.__options.type.upper()])
        binary.loaded = True
        binary.gadgets = gadgets
        self.__gadgets[binary] = ropper.filterBadBytes(gadgets, self.__options.badbytes)
        if not self.__options.all:
            self.__gadgets[binary] = ropper.deleteDuplicates(self.__gadgets[binary])

        return self.__gadgets[binary]
Esempio n. 5
0
    def __searchGadgets(self, binary):
        r = Ropper(self.__searchGadgetCallback)
        gadgets = r.searchGadgets(binary, instructionCount=self.__options.inst_count, gtype=GadgetType[self.__options.type.upper()])
        binary.loaded = True
        binary.gadgets = gadgets
        self.__gadgets[binary] = ropper.filterBadBytes(gadgets, self.__options.badbytes)
        if not self.__options.all:
            self.__cprinter.printInfo('deleting double gadgets...')
            self.__gadgets[binary] = ropper.deleteDuplicates(self.__gadgets[binary], self.__printProgress)

        return self.__gadgets[binary]
Esempio n. 6
0
    def __searchGadgets(self, binary):
        r = Ropper(self.__cprinter)
        gadgets = r.searchGadgets(binary, instructionCount=self.__options.inst_count, gtype=GadgetType[self.__options.type.upper()])
        binary.loaded = True
        binary.gadgets = gadgets
        self.__gadgets[binary] = ropper.filterBadBytes(gadgets, self.__options.badbytes)
        if not self.__options.all:
            self.__cprinter.printInfo('deleting double gadgets...')
            self.__gadgets[binary] = ropper.deleteDuplicates(self.__gadgets[binary], self.__printProgress)

        return self.__gadgets[binary]
Esempio n. 7
0
    def test_gadgets_pe(self):
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 4800)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase, gadget.address)
        self.assertEqual(gadget.imageBase, 0x4ad00000)
        self.file.imageBase = 0x0
        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        self.assertEqual(gadget.imageBase, 0x4ad00000)
Esempio n. 8
0
    def test_search(self):
        r = Ropper()

        gadgets = r.searchGadgets(self.file)

        found_gadgets = self.file.arch.searcher.search(gadgets, "mov [rax]")
        self.assertEqual(len(found_gadgets), 1)

        found_gadgets = self.file.arch.searcher.search(gadgets, "mov [r?x]")
        self.assertEqual(len(found_gadgets), 5)

        found_gadgets = self.file.arch.searcher.search(gadgets, "mov [r?x%]")
        self.assertEqual(len(found_gadgets), 7)
Esempio n. 9
0
    def test_search(self):
        r = Ropper()

        gadgets = r.searchGadgets(self.file)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [rax]')
        self.assertGreater(len(found_gadgets), 5)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x]')
        self.assertGreater(len(found_gadgets), 25)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x%]')
        self.assertGreater(len(found_gadgets), 70)
Esempio n. 10
0
    def test_search(self):
        r = Ropper()

        gadgets = r.searchGadgets(self.file)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [rax]')
        self.assertEqual(len(found_gadgets), 8)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x]')
        self.assertEqual(len(found_gadgets), 31)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x%]')
        self.assertEqual(len(found_gadgets), 83)
Esempio n. 11
0
    def test_search(self):
        r = Ropper()

        gadgets = r.searchGadgets(self.file)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [rax]')
        self.assertEqual(len(found_gadgets), 8)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x]')
        self.assertEqual(len(found_gadgets), 31)

        found_gadgets = self.file.arch.searcher.search(gadgets, 'mov [r?x%]')
        self.assertEqual(len(found_gadgets), 83)
Esempio n. 12
0
    def test_gadgets_pe(self):
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 1300)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase, gadget.address)
        self.assertEqual(gadget.imageBase, 0x00008000)
        self.file.imageBase = 0x0
        Gadget.IMAGE_BASES['test-binaries/ls-arm'] = self.file.imageBase
        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        Gadget.IMAGE_BASES[self.file.fileName] = self.file.imageBase
        self.assertEqual(gadget.imageBase, 0x00008000)
Esempio n. 13
0
    def test_gadgets_pe(self):
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 1900)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase, gadget.address)
        self.assertEqual(gadget.imageBase, 0x00400000)
        self.file.imageBase = 0x0
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase

        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase
        self.assertEqual(gadget.imageBase, 0x00400000)
Esempio n. 14
0
    def test_gadgets_pe(self):
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 1300)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase,
                         gadget.address)
        self.assertEqual(gadget.imageBase, 0x00008000)
        self.file.imageBase = 0x0
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase
        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase
        self.assertEqual(gadget.imageBase, 0x00008000)
Esempio n. 15
0
    def __searchGadgets(self, binary):
        r = Ropper(self.__cprinter)
        gadgets = r.searchGadgets(
            binary,
            depth=self.__options.depth,
            gtype=GadgetType[self.__options.type.upper()])
        binary.loaded = True
        binary.gadgets = gadgets
        self.__gadgets[binary] = ropper.filterBadBytes(gadgets,
                                                       self.__options.badbytes)
        if not self.__options.all:
            self.__gadgets[binary] = ropper.deleteDuplicates(
                self.__gadgets[binary])

        return self.__gadgets[binary]
Esempio n. 16
0
    def test_gadgets(self):
        self.assertEqual(self.file.arch, PPC)
        self.assertEqual(self.file.type, Type.ELF)
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 1400)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase, gadget.address)
        self.assertEqual(gadget.imageBase, 0x10000000)
        self.file.imageBase = 0x0
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase

        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        Gadget.IMAGE_BASES[self.file.checksum] = self.file.imageBase

        self.assertEqual(gadget.imageBase, 0x10000000)
Esempio n. 17
0
    def test_gadgets(self):
        self.assertEqual(self.file.arch, PPC)
        self.assertEqual(self.file.type, Type.ELF)
        ropper = Ropper()
        gadgets = ropper.searchGadgets(self.file)

        gadget = gadgets[0]
        self.assertGreater(len(gadgets), 1400)
        self.assertEqual(gadget.lines[0][0] + self.file.imageBase, gadget.address)
        self.assertEqual(gadget.imageBase, 0x10000000)
        self.file.imageBase = 0x0
        Gadget.IMAGE_BASES[self.file.fileName] = self.file.imageBase

        self.assertEqual(gadget.imageBase, 0x0)
        self.file.imageBase = None
        Gadget.IMAGE_BASES[self.file.fileName] = self.file.imageBase

        self.assertEqual(gadget.imageBase, 0x10000000)
Esempio n. 18
0
    def test_database(self):
        r = Ropper()

        db = './testdb.db'
        if os.path.exists(db):
            os.remove(db)

        dao = GadgetDAO(db)

        gadgets = r.searchGadgets(self.file)

        dao.save(gadgets)
        self.assertTrue(os.path.exists(db))

        loaded_gadgets = dao.load(self.file)
        self.assertEqual(len(gadgets), len(loaded_gadgets))
        self.assertEqual(gadgets[0].lines[0][0], loaded_gadgets[0].lines[0][0])

        os.remove(db)
Esempio n. 19
0
    def test_database(self):
        r = Ropper()

        db = "./testdb.db"
        if os.path.exists(db):
            os.remove(db)

        dao = GadgetDAO(db)

        gadgets = r.searchGadgets(self.file)

        dao.save(gadgets)
        self.assertTrue(os.path.exists(db))

        loaded_gadgets = dao.load(self.file)
        self.assertEqual(len(gadgets), len(loaded_gadgets))
        self.assertEqual(gadgets[0].lines[0][0], loaded_gadgets[0].lines[0][0])

        os.remove(db)
Esempio n. 20
0
    def __searchGadgets(self, binary):
        r = Ropper(self.__searchGadgetCallback)
        gadgets = r.searchGadgets(binary, instructionCount=self.__options.inst_count, gtype=GadgetType[self.__options.type.upper()])
        binary.loaded = True

        if self.__options.cfg_only:
            if isinstance(binary, PE):
                optHeader = binary._binary.imageNtHeaders.header.OptionalHeader
                characteristics = optHeader.DllCharacteristics
                cfgFlag = ImageDllCharacteristics.CONTROL_FLOW_GUARD
                if characteristics & cfgFlag == cfgFlag:
                    # do some filtering here
                    self.__cprinter.printInfo('deleting CFG invalid gadgets...')
                    gadgets = ropper.cfgFilterGadgets(gadgets, callback=self.__printCfgFilterProgress)

        binary.gadgets = gadgets
        self.__gadgets[binary] = ropper.filterBadBytes(gadgets, self.__options.badbytes)
        if not self.__options.all:
            self.__cprinter.printInfo('deleting double gadgets...')
            self.__gadgets[binary] = ropper.deleteDuplicates(self.__gadgets[binary], self.__printProgress)

        return self.__gadgets[binary]
Esempio n. 21
0
class RopperService(object):

    ROPPER_FOLDER = os.path.expanduser('~') + os.path.sep + ".ropper/"
    CACHE_FOLDER = os.path.expanduser('~') + os.path.sep + ".ropper/cache/"
    CACHE_FILE_COUNT = 16

    def __init__(self, options={}, callbacks=None):
        super(RopperService, self).__init__()
        self.__options = Options(options, self.__optionChanged)
        if callbacks and hasattr(callbacks, '__gadgetSearchProgress__'):
            self.__ropper = Ropper(callback=callbacks.__gadgetSearchProgress__)
        else:
            self.__ropper = Ropper()
        self.__files = []
        self.__callbacks = callbacks
        if self.__options.color:
            cstr.COLOR = self.__options.color
        Gadget.DETAILED = self.__options.detailed

    @property
    def ropper(self):
        return self.__ropper

    @property
    def options(self):
        return self.__options

    @property
    def files(self):
        return list(self.__files)

    def __optionChanged(self, option, oldvalue, newvalue):
        if hasattr(self, '_%s_changed' % option):
            func = getattr(self, '_%s_changed' % option)
            func(newvalue)

    def __prepareGadgets(self, file, gadgets, type=None):

        gadgets = self.__filterBadBytes(gadgets)
        gadgets = self.__filterCfg(file, gadgets, type)
        if not self.__options.all:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__deleteDoubleGadgetsProgress__'):
                callback = self.__callbacks.__deleteDoubleGadgetsProgress__
            gadgets = deleteDuplicates(gadgets, callback)
        return gadgets

    def __filterBadBytes(self, gadgets):
        if self.__options.badbytes:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__filterBadBytesGadgetsProgress__'):
                callback = self.__callbacks.__filterBadBytesGadgetsProgress__
            gadgets = filterBadBytes(gadgets, self.options.badbytes, callback)
        return gadgets

    def __filterCfg(self, file, gadgets, type):
        if self.__options.cfg_only and type==Type.PE:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__filterCfgGadgetsProgress__'):
                callback = self.__callbacks.__filterCfgGadgetsProgress__
            gadgets = cfgFilterGadgets(file.loader, gadgets, callback)
        return gadgets

    def __getCacheFileName(self, file):
        return "%s_%s_%d_%s_%d" % (file.loader.checksum, str(file.arch), self.options.inst_count,str(self.options.type), sys.version_info.major)

    def __saveCache(self, file):
        cache_file = None
        try:
            temp = RopperService.CACHE_FOLDER
            if not os.path.exists(temp):
                os.makedirs(temp)

            cache_file = temp + os.path.sep + self.__getCacheFileName(file)
            count = RopperService.CACHE_FILE_COUNT
            if not isWindows() and len(file.allGadgets) > 1000:
                if os.path.exists(cache_file):
                    os.remove(cache_file)

                length = len(file.allGadgets)

                step = int(length / count)
                for i in range(count-1):
                    gadgets = file.allGadgets[i*step: (i+1)*step]
                    with open(cache_file+'_%d' % (i+1),'wb') as f:
                        f.write(encode(repr(gadgets).encode('ascii'),'zip'))

                gadgets = file.allGadgets[(count-1)*step:]
                with open(cache_file+'_%d' % (count),'wb') as f:
                    f.write(encode(repr(gadgets).encode('ascii'),'zip'))
                return

            with open(cache_file,'wb') as f:
                f.write(encode(repr(file.allGadgets).encode('ascii'),'zip'))
        except BaseException as e:
            print(e)
            if cache_file:
                for i in range(1, RopperService.CACHE_FILE_COUNT+1):
                    if os.path.exists(cache_file+'_%d' % i):
                        os.remove(cache_file+'_%d' % i)


    def __loadCachePerProcess(self, fqueue, gqueue):
        nan=0
        while True:
            cacheFileName = fqueue.get()
            if cacheFileName is None:
                fqueue.task_done()
                break
            if os.path.exists(cacheFileName):
                with open(cacheFileName,'rb') as f:
                    data = f.read()
                    gqueue.put(eval(decode(data,'zip')))
            else:
                gqueue.put([])
            fqueue.task_done()


    def __loadCache(self, file):
        mp = False
        nan= 0
        processes = []
        single = False
        cache_file = None
        try:
            temp = RopperService.CACHE_FOLDER
            cache_file = temp + os.path.sep + self.__getCacheFileName(file)

            if not os.path.exists(cache_file):
                if not os.path.exists(cache_file+'_%d' % 1):
                    return
                else:
                    if isWindows():
                        raise RopperError('Cache has to be cleared.')
                    mp = True and multiprocessing.cpu_count()>1
            else:
                single = True
            if self.__callbacks and hasattr(self.__callbacks, '__message__'):
                self.__callbacks.__message__('Load gadgets from cache')
            if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                        self.__callbacks.__gadgetSearchProgress__(None, [], 0)
            if not mp:
                all_gadgets = []
                if single:
                    with open(cache_file,'rb') as f:
                        data = f.read()
                        all_gadgets.extend(eval(decode(data,'zip')))
                        if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                            self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, 1.0)
                else:
                    for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                        if os.path.exists(cache_file+'_%d' % i):
                            with open(cache_file+'_%d' % i,'rb') as f:
                                data = f.read()
                                all_gadgets.extend(eval(decode(data,'zip')))
                                if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                                    self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, float(i)/RopperService.CACHE_FILE_COUNT)
                return all_gadgets

            else:
                count = min(multiprocessing.cpu_count(),RopperService.CACHE_FILE_COUNT)

                gqueue = multiprocessing.Queue()
                fqueue = multiprocessing.JoinableQueue()
                for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                    fqueue.put(cache_file+'_%d' % i)
                all_gadgets = []
                for i in range(count):
                    p=multiprocessing.Process(target=self.__loadCachePerProcess, args=(fqueue, gqueue))
                    p.start()
                    processes.append(p)

                for i in range(count):
                    fqueue.put(None)

                for i in range(RopperService.CACHE_FILE_COUNT):
                    gadgets = gqueue.get()
                    all_gadgets.extend(gadgets)
                    if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                        self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, float(i+1)/RopperService.CACHE_FILE_COUNT)

                return sorted(all_gadgets, key=Gadget.simpleInstructionString)
        except KeyboardInterrupt:
            if mp:
                for p in processes:
                    if p and p.is_alive():
                        p.terminate()
        except BaseException as e:
            if mp:
                for p in processes:
                    if p and p.is_alive():
                        p.terminate()
            if cache_file:
                for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                    if os.path.exists(cache_file+'_%d' % i):
                        os.remove(cache_file+'_%d' % i)


    def _badbytes_changed(self, value):
        for f in self.__files:
            if f.loaded:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _all_changed(self, value):
        for f in self.__files:
            if f.loaded:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _color_changed(self, value):
        cstr.COLOR = value

    def _detailed_changed(self, value):
        Gadget.DETAILED = value

    def _cfg_only_changed(self, value):
        for f in self.__files:
            if f.loaded and f.type == Type.PE:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _type_changed(self, value):
        for f in self.__files:
            if f.loaded:
                self.loadGadgetsFor(f.name)

    def _inst_count_changed(self, value):
        for f in self.__files:
            if f.loaded:
                self.loadGadgetsFor(f.name)

    def _getFileFor(self, name):
        for file in self.__files:
            if file.loader.fileName == name:
                return file

        return None

    def clearCache(self):
        temp = RopperService.CACHE_FOLDER
        if os.path.exists(temp):
            import shutil
            shutil.rmtree(temp)


    def getFileFor(self, name):
        return self._getFileFor(name)

    def addFile(self, name, bytes=None, arch=None, raw=False):
        if self._getFileFor(name):
            raise RopperError('file is already added: %s' % name)

        if arch:
            arch=getArchitecture(arch)

        loader = Loader.open(name, bytes=bytes, raw=raw, arch=arch)
        file = FileContainer(loader)
        self.__files.append(file)

    def removeFile(self, name):
        for idx, fc in enumerate(self.__files):
            if fc.loader.fileName == name:
                del self.__files[idx]

    def asm(self, code, arch='x86', format='hex'):
        if format not in ('hex', 'string', 'raw'):
            raise RopperError('Invalid format: %s\n Valid formats are: hex, string, raw' % format)
        format = Format.HEX if format=='hex' else Format.STRING if format=='string' else Format.RAW
        return self.ropper.assemble(code, arch=getArchitecture(arch), format=format)

    def disasm(self, opcode, arch='x86'):
        return self.ropper.disassemble(opcode, arch=getArchitecture(arch))

    def searchPopPopRet(self, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchPopPopRet(file.loader)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchPopPopRet(fc.loader)

        return self.__filterBadBytes(to_return)

    def searchJmpReg(self, regs=['esp'],name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchJmpReg(file.loader, regs)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchJmpReg(fc.loader, regs)

        return self.__filterBadBytes(to_return)

    def searchOpcode(self, opcode, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchOpcode(file.loader, opcode)
        else:
            fc = self.getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchOpcode(fc.loader, opcode)

        return self.__filterBadBytes(to_return)

    def searchInstructions(self, code, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchInstructions(file.loader, code)
        else:
            fc = self.getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchInstructions(fc.loader, code)

        return self.__filterBadBytes(to_return)

    def analyseGadgets(self, fileObject):
        gadgets = fileObject.gadgets
        analyser = Analyser()
        cb = None
        lg = len(gadgets)
        if self.__callbacks and hasattr(self.__callbacks, '__analyseGadgetsProgress__'):
            cb = self.__callbacks.__analyseGadgetsProgress__
        for i,g in enumerate(gadgets):
            g.info = analyser.analyse(g)
            if cb:
                cb(g, float(i)/lg)
        if cb:
             cb(None, 1.0)
        self.__saveCache(fileObject)
        fileObject.analysed = True

    def loadGadgetsFor(self, name=None):

        def load_gadgets(f):
            gtype = None
            cache = False
            Gadget.IMAGE_BASES[f.loader.checksum] = f.loader.imageBase
            if self.options.type == 'rop':
                gtype = GadgetType.ROP
            elif self.options.type == 'jop':
                gtype = GadgetType.JOP
            elif self.options.type == 'sys':
                gtype = GadgetType.SYS
            elif self.options.type == 'all':
                gtype = GadgetType.ALL
            f.allGadgets = self.__loadCache(f)
            if f.allGadgets == None:
                cache = True
                f.allGadgets = self.__ropper.searchGadgets(f.loader, instructionCount=self.options.inst_count, gtype=gtype)

            if cache:
                self.__saveCache(f)
            f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)
            f.analysed = f.gadgets[0].info is not None if len(f.gadgets) > 0 else False
            #self._analyseGadgets(f.gadgets)


        if name is None:
            for fc in self.__files:
                load_gadgets(fc)
        else:
            for fc in self.__files:
                if fc.loader.fileName == name:
                    load_gadgets(fc)

    def printGadgetsFor(self, name=None):
        def print_gadgets(f):
            print(f.loader.fileName)
            for g in f.gadgets:
                if self.options.detailed:
                    print(g)
                else:
                    print(g.simpleString())

        if name is None:
            for f in self.__files:
                print_gadgets(f)
        else:
            for f in self.__files:
                if f.loader.fileName == name:
                    print_gadgets(f)

    def searchString(self, string='', name=None):

        def search(f, string):
            data = []
            if not string or string == '[ -~]{2}[ -~]*':
                string = '[ -~]{2}[ -~]*'
            else:
                string = f.arch.searcher.prepareFilter(string)
            sections = list(f.dataSections)
            string = string.encode('ascii') # python 3 compatibility
            for section in sections:
                b = bytes(bytearray(section.bytes))
                for match in re.finditer(string, b):
                    vaddr = f.imageBase + section.offset if f.imageBase != None else section.virtualAddress
                    data.append( (match.start() + vaddr , match.group()))
            return data

        to_return = {}
        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = search(file.loader, string)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)
            to_return[name] = search(fc.loader, string)

        return to_return

    def search(self, search, quality=None, name=None):
        if name:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            s = fc.loader.arch.searcher
            for gadget in s.search(fc.gadgets, search, quality):
                    yield(fc.name, gadget)
        else:
            for fc in self.__files:
                s = fc.loader.arch.searcher
                for gadget in s.search(fc.gadgets, search, quality):
                    yield(fc.name, gadget)

    def semanticSearch(self, search, stableRegs=[], name=None):
        count = 0
        if name:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            s = fc.loader.arch.searcher
            for gadget in s.semanticSearch(fc.gadgets, search, self.options.inst_count, stableRegs):
                if self.options.count_of_findings == 0 or self.options.count_of_findings > count:
                    yield(fc.name, gadget)
                else:
                    break
                count += 1
            self.__saveCache(fc)
        else:
            for fc in self.__files:
                s = fc.loader.arch.searcher
                for gadget in s.semanticSearch(fc.gadgets, search, self.options.inst_count, stableRegs):
                    if self.options.count_of_findings == 0 or self.options.count_of_findings > count:
                        yield(fc.name, gadget)
                    else:
                        break
                    count += 1
                self.__saveCache(fc)

    def searchdict(self, search, quality=None, name=None):
        to_return = {}
        for file, gadget in self.search(search, quality, name):
            l = to_return.get(file)
            if not l:
                l = []
                to_return[file] = l
            l.append(gadget)
        return to_return

    def disassAddress(self, name, address, length):
        fc = self.getFileFor(name)
        if not fc:
            raise RopperError('No such file opened: %s' % name)
        eSections = fc.loader.executableSections

        for section in  eSections:
            if section.virtualAddress <= address and section.virtualAddress + section.size > address:
                ropper = Ropper()


                g = ropper.disassembleAddress(section, fc.loader, address, address - (fc.loader.imageBase+section.offset), length)
                if not g:
                    raise RopperError('Cannot disassemble address: %s' % toHex(address))

                if length < 0:
                    length = length * -1
                return g.disassemblyString()
        return ''

    def createRopChain(self, chain, arch, options={}):
        callback = None
        if self.__callbacks and hasattr(self.__callbacks, '__ropchainMessages__'):
            callback = self.__callbacks.__ropchainMessages__

        b = []
        gadgets = {}
        for binary in self.__files:
            if str(binary.arch) == arch:
                gadgets[binary.loader] = binary.gadgets
                b.append(binary.loader)
        generator = RopChain.get(b, gadgets, chain, callback, unhexlify(self.options.badbytes))

        if not generator:
            raise RopperError('%s does not have support for %s chain generation at the moment. Its a future feature.' % (self.files[0].loader.arch.__class__.__name__, chain))

        return generator.create(options)

    def setImageBaseFor(self, name, imagebase):
        file = self._getFileFor(name)
        if not file:
            raise RopperError('No such file opened: %s' % name)
        file.loader.imageBase = imagebase
        Gadget.IMAGE_BASES[file.loader.checksum] = file.loader.imageBase
        if file.loaded and (self.options.badbytes or self.options.cfg_only and file.type == Type.PE):
            file.gadgets = self.__prepareGadgets(file, file.allGadgets, file.type)

    def setArchitectureFor(self, name, arch):
        file = self.getFileFor(name)
        if not file:
            raise RopperError('No such file opened: %s' % name)
        file.loader.arch = getArchitecture(arch)
        if file.loaded:
            self.loadGadgetsFor(name)

    def _setGadgets(self, name, gadgets):
        fc = self.getFileFor(name)
        if not fc:
            raise RopperError('No such file opened: %s' % name)
        fc.allGadgets = gadgets
        fc.gadgets = self.__prepareGadgets(fc, fc.allGadgets, fc.type)
Esempio n. 22
0
class RopperService(object):

    ROPPER_FOLDER = os.path.expanduser('~') + os.path.sep + ".ropper/"
    CACHE_FOLDER = os.path.expanduser('~') + os.path.sep + ".ropper/cache/"
    CACHE_FILE_COUNT = 16

    def __init__(self, options={}, callbacks=None):
        super(RopperService, self).__init__()
        self.__options = Options(options, self.__optionChanged)
        if callbacks and hasattr(callbacks, '__gadgetSearchProgress__'):
            self.__ropper = Ropper(callback=callbacks.__gadgetSearchProgress__)
        else:
            self.__ropper = Ropper()
        self.__files = []
        self.__callbacks = callbacks
        if self.__options.color:
            cstr.COLOR = self.__options.color
        Gadget.DETAILED = self.__options.detailed

    @property
    def ropper(self):
        return self.__ropper
    
    @property
    def options(self):
        return self.__options

    @property
    def files(self):
        return list(self.__files)
    
    def __optionChanged(self, option, oldvalue, newvalue):
        if hasattr(self, '_%s_changed' % option):
            func = getattr(self, '_%s_changed' % option)
            func(newvalue)

    def __prepareGadgets(self, file, gadgets, type=None):
        
        gadgets = self.__filterBadBytes(gadgets)
        gadgets = self.__filterCfg(file, gadgets, type) 
        if not self.__options.all:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__deleteDoubleGadgetsProgress__'):
                callback = self.__callbacks.__deleteDoubleGadgetsProgress__
            gadgets = deleteDuplicates(gadgets, callback)
        return gadgets

    def __filterBadBytes(self, gadgets):
        if self.__options.badbytes:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__filterBadBytesGadgetsProgress__'):
                callback = self.__callbacks.__filterBadBytesGadgetsProgress__
            gadgets = filterBadBytes(gadgets, self.options.badbytes, callback)
        return gadgets

    def __filterCfg(self, file, gadgets, type):
        if self.__options.cfg_only and type==Type.PE:
            callback = None
            if self.__callbacks and hasattr(self.__callbacks, '__filterCfgGadgetsProgress__'):
                callback = self.__callbacks.__filterCfgGadgetsProgress__
            gadgets = cfgFilterGadgets(file.loader, gadgets, callback)
        return gadgets

    def __getCacheFileName(self, file):
        return "%s_%s_%d_%s_%d" % (file.loader.checksum, str(file.arch), self.options.inst_count,str(self.options.type), sys.version_info.major)

    def __saveCache(self, file):
        cache_file = None
        try:
            temp = RopperService.CACHE_FOLDER
            if not os.path.exists(temp):
                os.makedirs(temp)

            cache_file = temp + os.path.sep + self.__getCacheFileName(file)
            count = RopperService.CACHE_FILE_COUNT
            if len(file.allGadgets) > 1000:
                if os.path.exists(cache_file):
                    os.remove(cache_file)

                length = len(file.allGadgets)
                
                step = int(length / count)
                for i in range(count-1):
                    gadgets = file.allGadgets[i*step: (i+1)*step]
                    with open(cache_file+'_%d' % (i+1),'wb') as f:
                        f.write(encode(repr(gadgets).encode('ascii'),'zip'))

                gadgets = file.allGadgets[(count-1)*step:]
                with open(cache_file+'_%d' % (count),'wb') as f:
                    f.write(encode(repr(gadgets).encode('ascii'),'zip'))
                return

            with open(cache_file,'wb') as f:
                f.write(encode(repr(file.allGadgets).encode('ascii'),'zip'))
        except BaseException as e:
            print(e)
            if cache_file:
                for i in range(1, RopperService.CACHE_FILE_COUNT+1):
                    if os.path.exists(cache_file+'_%d' % i):
                        os.remove(cache_file+'_%d' % i)


    def __loadCachePerProcess(self, fqueue, gqueue):
        nan=0
        while True:
            cacheFileName = fqueue.get()
            if cacheFileName is None:
                fqueue.task_done()
                break
            if os.path.exists(cacheFileName):
                with open(cacheFileName,'rb') as f:
                    data = f.read()
                    gqueue.put(eval(decode(data,'zip')))
            else:
                gqueue.put([])
            fqueue.task_done()


    def __loadCache(self, file):
        mp = False
        nan= 0
        processes = []
        single = False
        cache_file = None
        try:
            temp = RopperService.CACHE_FOLDER
            cache_file = temp + os.path.sep + self.__getCacheFileName(file)

            if not os.path.exists(cache_file):
                if not os.path.exists(cache_file+'_%d' % 1):
                    return
                else:
                    mp = True and multiprocessing.cpu_count()>1
            else: 
                single = True
            if self.__callbacks and hasattr(self.__callbacks, '__message__'):
                self.__callbacks.__message__('Load gadgets from cache')
            if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                        self.__callbacks.__gadgetSearchProgress__(None, [], 0)
            if not mp:
                all_gadgets = []
                if single:
                    with open(cache_file,'rb') as f:
                        data = f.read()
                        all_gadgets.extend(eval(decode(data,'zip')))
                        if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                            self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, 1.0)
                else:
                    for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                        if os.path.exists(cache_file+'_%d' % i):
                            with open(cache_file+'_%d' % i,'rb') as f:
                                data = f.read()
                                all_gadgets.extend(eval(decode(data,'zip')))
                                if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                                    self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, float(i)/RopperService.CACHE_FILE_COUNT)
                return all_gadgets
                
            else:
                count = min(multiprocessing.cpu_count(),RopperService.CACHE_FILE_COUNT)

                gqueue = multiprocessing.Queue()
                fqueue = multiprocessing.JoinableQueue()
                for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                    fqueue.put(cache_file+'_%d' % i)
                all_gadgets = []
                for i in range(count):
                    p=multiprocessing.Process(target=self.__loadCachePerProcess, args=(fqueue, gqueue))
                    p.start()
                    processes.append(p)

                for i in range(count):
                    fqueue.put(None)

                for i in range(RopperService.CACHE_FILE_COUNT):
                    gadgets = gqueue.get()
                    all_gadgets.extend(gadgets)
                    if self.__callbacks and hasattr(self.__callbacks, '__gadgetSearchProgress__'):
                        self.__callbacks.__gadgetSearchProgress__(None, all_gadgets, float(i+1)/RopperService.CACHE_FILE_COUNT)

                return sorted(all_gadgets, key=Gadget.simpleInstructionString)
        except KeyboardInterrupt:
            if mp:
                for p in processes:
                    if p and p.is_alive():
                        p.terminate()
        except BaseException as e:
            if mp:
                for p in processes:
                    if p and p.is_alive():
                        p.terminate()
            if cache_file:
                for i in range(1,RopperService.CACHE_FILE_COUNT+1):
                    if os.path.exists(cache_file+'_%d' % i):
                        os.remove(cache_file+'_%d' % i)


    def _badbytes_changed(self, value):
        for f in self.__files:
            if f.loaded:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _all_changed(self, value):
        for f in self.__files:
            if f.loaded:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _color_changed(self, value):
        cstr.COLOR = value

    def _detailed_changed(self, value):
        Gadget.DETAILED = value

    def _cfg_only_changed(self, value):
        for f in self.__files:
            if f.loaded and f.type == Type.PE:
                f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)

    def _type_changed(self, value):
        for f in self.__files:
            if f.loaded:
                self.loadGadgetsFor(f.name)

    def _inst_count_changed(self, value):
        for f in self.__files:
            if f.loaded:
                self.loadGadgetsFor(f.name)

    def _getFileFor(self, name):
        for file in self.__files:
            if file.loader.fileName == name:
                return file

        return None

    def clearCache(self):
        temp = RopperService.CACHE_FOLDER
        if os.path.exists(temp):
            import shutil
            shutil.rmtree(temp)


    def getFileFor(self, name):
        return self._getFileFor(name)
        
    def addFile(self, name, bytes=None, arch=None, raw=False):
        if self._getFileFor(name):
            raise RopperError('file is already added: %s' % name)

        if arch:
            arch=getArchitecture(arch)

        loader = Loader.open(name, bytes=bytes, raw=raw, arch=arch)
        file = FileContainer(loader)
        self.__files.append(file)

    def removeFile(self, name):
        for idx, fc in enumerate(self.__files):
            if fc.loader.fileName == name:
                del self.__files[idx]

    def asm(self, code, arch='x86', format='hex'):
        if format not in ('hex', 'string', 'raw'):
            raise RopperError('Invalid format: %s\n Valid formats are: hex, string, raw' % format)
        format = Format.HEX if format=='hex' else Format.STRING if format=='string' else Format.RAW
        return self.ropper.assemble(code, arch=getArchitecture(arch), format=format)

    def disasm(self, opcode, arch='x86'):
        return self.ropper.disassemble(opcode, arch=getArchitecture(arch))

    def searchPopPopRet(self, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchPopPopRet(file.loader)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchPopPopRet(fc.loader)

        return self.__filterBadBytes(to_return)

    def searchJmpReg(self, regs=['esp'],name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchJmpReg(file.loader, regs)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchJmpReg(fc.loader, regs)

        return self.__filterBadBytes(to_return)

    def searchOpcode(self, opcode, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchOpcode(file.loader, opcode)
        else:
            fc = self.getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchOpcode(fc.loader, opcode)

        return self.__filterBadBytes(to_return)

    def searchInstructions(self, code, name=None):
        to_return = {}

        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = self.__ropper.searchInstructions(file.loader, code)
        else:
            fc = self.getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)

            to_return[name] = self.__ropper.searchInstructions(fc.loader, code)

        return self.__filterBadBytes(to_return)

    def analyseGadgets(self, fileObject):
        gadgets = fileObject.gadgets
        analyser = Analyser()
        cb = None
        lg = len(gadgets)
        if self.__callbacks and hasattr(self.__callbacks, '__analyseGadgetsProgress__'):
            cb = self.__callbacks.__analyseGadgetsProgress__
        for i,g in enumerate(gadgets):
            g.info = analyser.analyse(g)
            if cb:
                cb(g, float(i)/lg)
        if cb:
             cb(None, 1.0)
        self.__saveCache(fileObject)
        fileObject.analysed = True

    def loadGadgetsFor(self, name=None):
        
        def load_gadgets(f):
            gtype = None
            cache = False
            Gadget.IMAGE_BASES[f.loader.checksum] = f.loader.imageBase
            if self.options.type == 'rop':
                gtype = GadgetType.ROP
            elif self.options.type == 'jop':
                gtype = GadgetType.JOP
            elif self.options.type == 'sys':
                gtype = GadgetType.SYS
            elif self.options.type == 'all':
                gtype = GadgetType.ALL    
            f.allGadgets = self.__loadCache(f)
            if f.allGadgets == None:
                cache = True
                f.allGadgets = self.__ropper.searchGadgets(f.loader, instructionCount=self.options.inst_count, gtype=gtype)
            
            if cache:
                self.__saveCache(f)
            f.gadgets = self.__prepareGadgets(f, f.allGadgets, f.type)
            f.analysed = f.gadgets[0].info is not None if len(f.gadgets) > 0 else False
            #self._analyseGadgets(f.gadgets)

         
        if name is None:
            for fc in self.__files:
                load_gadgets(fc)
        else:
            for fc in self.__files:
                if fc.loader.fileName == name:
                    load_gadgets(fc)
                
    def printGadgetsFor(self, name=None):
        def print_gadgets(f):
            print(f.loader.fileName)
            for g in f.gadgets:
                if self.options.detailed:
                    print(g)
                else:
                    print(g.simpleString())

        if name is None:
            for f in self.__files:
                print_gadgets(f)
        else:
            for f in self.__files:
                if f.loader.fileName == name:
                    print_gadgets(f)

    def searchString(self, string='', name=None):

        def search(f, string):
            data = []
            if not string or string == '[ -~]{2}[ -~]*':
                string = '[ -~]{2}[ -~]*'
            else:
                string = f.arch.searcher.prepareFilter(string)
            sections = list(f.dataSections)
            string = string.encode('ascii') # python 3 compatibility
            for section in sections:
                b = bytes(bytearray(section.bytes))
                for match in re.finditer(string, b):
                    vaddr = f.imageBase + section.offset if f.imageBase != None else section.virtualAddress
                    data.append( (match.start() + vaddr , match.group()))
            return data

        to_return = {}
        if not name:
            for file in self.__files:
                to_return[file.loader.fileName] = search(file.loader, string)
        else:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)
            to_return[name] = search(fc.loader, string)

        return to_return

    def search(self, search, quality=None, name=None):
        if name:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)
            
            s = fc.loader.arch.searcher
            for gadget in s.search(fc.gadgets, search, quality):
                    yield(fc.name, gadget)
        else:        
            for fc in self.__files:
                s = fc.loader.arch.searcher
                for gadget in s.search(fc.gadgets, search, quality):
                    yield(fc.name, gadget)

    def semanticSearch(self, search, stableRegs=[], name=None):
        count = 0
        if name:
            fc = self._getFileFor(name)
            if not fc:
                raise RopperError('No such file opened: %s' % name)
            
            s = fc.loader.arch.searcher
            for gadget in s.semanticSearch(fc.gadgets, search, self.options.inst_count, stableRegs):
                if self.options.count_of_findings == 0 or self.options.count_of_findings > count:
                    yield(fc.name, gadget)
                else:
                    break
                count += 1
            self.__saveCache(fc)
        else:        
            for fc in self.__files:
                s = fc.loader.arch.searcher
                for gadget in s.semanticSearch(fc.gadgets, search, self.options.inst_count, stableRegs):
                    if self.options.count_of_findings == 0 or self.options.count_of_findings > count:
                        yield(fc.name, gadget)
                    else:
                        break
                    count += 1
                self.__saveCache(fc)

    def searchdict(self, search, quality=None, name=None):
        to_return = {}
        for file, gadget in self.search(search, quality, name):
            l = to_return.get(file)
            if not l:
                l = []
                to_return[file] = l
            l.append(gadget)
        return to_return

    def disassAddress(self, name, address, length):
        fc = self.getFileFor(name)
        if not fc:
            raise RopperError('No such file opened: %s' % name)
        eSections = fc.loader.executableSections

        for section in  eSections:
            if section.virtualAddress <= address and section.virtualAddress + section.size > address:
                ropper = Ropper()


                g = ropper.disassembleAddress(section, fc.loader, address, address - (fc.loader.imageBase+section.offset), length)
                if not g:
                    raise RopperError('Cannot disassemble address: %s' % toHex(address))
                    
                if length < 0:
                    length = length * -1
                return g.disassemblyString()
        return ''
        
    def createRopChain(self, chain, arch, options={}):
        callback = None
        if self.__callbacks and hasattr(self.__callbacks, '__ropchainMessages__'):
            callback = self.__callbacks.__ropchainMessages__

        b = []
        gadgets = {}
        for binary in self.__files:
            if str(binary.arch) == arch:
                gadgets[binary.loader] = binary.gadgets
                b.append(binary.loader)
        generator = RopChain.get(b, gadgets, chain, callback, unhexlify(self.options.badbytes))

        if not generator:
            raise RopperError('%s does not have support for %s chain generation at the moment. Its a future feature.' % (self.files[0].loader.arch.__class__.__name__, chain))

        return generator.create(options)

    def setImageBaseFor(self, name, imagebase):
        file = self._getFileFor(name)
        if not file:
            raise RopperError('No such file opened: %s' % name)
        file.loader.imageBase = imagebase
        Gadget.IMAGE_BASES[file.loader.checksum] = file.loader.imageBase
        if file.loaded and (self.options.badbytes or self.options.cfg_only and file.type == Type.PE):
            file.gadgets = self.__prepareGadgets(file, file.allGadgets, file.type)

    def setArchitectureFor(self, name, arch):
        file = self.getFileFor(name)
        if not file:
            raise RopperError('No such file opened: %s' % name)
        file.loader.arch = getArchitecture(arch)
        if file.loaded:
            self.loadGadgetsFor(name)

    def _setGadgets(self, name, gadgets):
        fc = self.getFileFor(name)
        if not fc:
            raise RopperError('No such file opened: %s' % name)
        fc.allGadgets = gadgets
        fc.gadgets = self.__prepareGadgets(fc, fc.allGadgets, fc.type)