def mprotect_X64(addr, size, prot=7, constraint=None): """ Call mprotect from X86-64 arch Args must be on registers (rdi, rsi, rdx): Sizes are (unsigned long, size_t, unsigned long) rax must be 10 """ if (constraint is None): constraint = Constraint() # Set the registers args = [[Analysis.n2r('rdi'), addr], [Analysis.n2r('rsi'), size], [Analysis.n2r('rdx'), prot], [Analysis.n2r('rax'), 10]] perms = permutations(args) for perm in perms: chain = pop_multiple(perm, constraint) if (chain): break if (not chain): info("Failed to set registers for the mprotect syscall") return [] # Syscall syscalls = search.syscall(constraint) if (not syscalls): info("Failed to find a syscall gadget") return [] else: chain += syscalls[0] info("Success") return chain
def mprotect_X86(addr, size, prot=7, constraint=None): """ Call mprotect from X86 arch Args must be on the stack: int mprotect(void *addr, size_t len, int prot) args must be in registers (ebx, ecx, edx) eax must be 0x7d = 125 """ if (constraint is None): constraint = Constraint() # Set the registers args = [[Analysis.n2r('eax'), 0x7d], [Analysis.n2r('ebx'), addr], [Analysis.n2r('ecx'), size], [Analysis.n2r('edx'), prot]] perms = permutations(args) for perm in perms: chain = pop_multiple(perm, constraint) if (chain): break if (not chain): info("Failed to set registers for the mprotect syscall") return [] # Int 0x80 int80_gadgets = search.int80(constraint) if (not int80_gadgets): info("Failed to find an 'int 80' gadget") return [] else: chain += int80_gadgets[0] info("Success") return chain
def load(args): if (len(args) > 0): filename = args[0] msg = string_bold( "Extracting gadgets from file") + " '" + filename + "'" if (len(args) > 1): msg += " (Ignoring extra arguments '" msg += ', '.join(args[1:]) msg += "')" info_colored(msg + '\n') else: print( string_bold("\n\tMissing argument.\n\tType 'load help' for help")) # Cleaning the data structures Gadget.reinit() Database.reinit() Analysis.reinit() SearchHelper.reinit() if (generate_opcodes.generate(filename)): BinaryScanner.set_binary(filename) Database.generated_gadgets_to_DB() Database.simplifyGadgets() Database.gadgetLookUp.fill()
def set_arch(arch): global ARCH if( arch in Analysis.supportedArchs ): ARCH = arch Analysis.setArch(arch) print("Now working under architecture: " + arch) else: print("Architecture '" + arch + "' is not supported. Available architectures are: " + ','.join(Analysis.supportedArchs))
def default_config(): global ARCH global PATH_ROPGADGET global DEFAULT_ARCH global DEFAULT_PATH_ROPGADGET ARCH = DEFAULT_ARCH PATH_ROPGADGET = DEFAULT_PATH_ROPGADGET LIMIT = DEFAULT_LIMIT Analysis.setArch(ARCH)
def set_arch(arch, quiet=False): global ARCH if (arch in Analysis.supportedArchs): ARCH = arch Analysis.setArch(arch) if (not quiet): notify("Now working under architecture: " + arch) else: if (not quiet): notify("Architecture '" + arch + "' not supported. Available architectures: " + ','.join(Analysis.supportedArchs))
def load_config(): global ARCH global PATH_ROPGADGET try: f = open(config_file, "r" ) ARCH = f.readline()[:-1] PATH_ROPGADGET = f.readline()[:-1] f.close() except: if( os.path.isfile(config_file)): print("Couldn't load custom configuration, using the default one") default_config() Analysis.setArch(ARCH)
def check_binaryType(filename): """ Checks the binary type of the file Precondition: the file exists ! """ INTEL_strings = ["x86", "x86-64", "X86", "X86-64", "Intel", "80386"] ELF32_strings = ["ELF 32-bit"] ELF64_strings = ["ELF 64-bit"] PE32_strings = ["PE32 "] PE64_strings = ["PE32+"] output = from_file(os.path.realpath(filename)) if ([sub for sub in INTEL_strings if sub in output]): if ([sub for sub in ELF32_strings if sub in output]): notify("ELF 32-bits detected") Analysis.setFiletype("ELF") return "X86" elif ([sub for sub in ELF64_strings if sub in output]): notify("ELF 64-bits detected") Analysis.setFiletype("ELF") return "X86-64" elif ([sub for sub in PE32_strings if sub in output]): notify("PE 32-bits detected") Analysis.setFiletype("PE") return "X86" elif ([sub for sub in PE64_strings if sub in output]): notify("PE 64-bits detected") Analysis.setFiletype("PE") return "X86-64" else: notify("Unknown binary type") return None else: notify("Unknown architecture") return None
def hasPossibleNormalRet(self): """ Checks if the gadget can return normaly under certain conditions ! Returns a pair (True, condition) (False, None) """ if (self.sort != GadgetSort.REGULAR): False # Check ip = SSAReg( Analysis.regNamesTable[Analysis.ArchInfo.ip], self.graph.lastMod[Analysis.regNamesTable[Analysis.ArchInfo.ip]]) sp_num = Analysis.n2r(Analysis.ArchInfo.sp) for dep in self.dep.regDep.get(ip, []): dep[0] = dep[0].simplify() if (isinstance(dep[0], MEMExpr)): addr = dep[0].addr (isInc, inc) = addr.isRegIncrement(sp_num) # Normal ret if the final value of the IP is value that was in memory before the last modification of SP ( i.e final_IP = MEM[final_sp - size_of_a_register ) if (isInc and self.spInc and inc == (self.spInc - (Analysis.ArchInfo.bits / 8))): return (True, dep[1]) return (False, None)
def __init__(self, num, addr, raw): """ (raw) is the raw string of the instructions of the gadget """ # irsb is an array of BARF instructions # ins is an array of Assembly instructions try: (irsb, ins) = Analysis.getIR(raw, addr) except Exception as e: raise GadgetException(str(e.msg)) # Some strings representations self.asmStr = "; ".join(str(i) for i in ins) self.hexStr = "\\x" + "\\x".join("{:02x}".format(ord(c)) for c in raw) # Initializing the memory in Z3 for this gadget memorySMT = Array("MEM", BitVecSort(REGSIZE.size), BitVecSort(8)) self.addr = addr # int # Get the string for the address, depends on the architecture size self.addrStr = '0x' + format( addr, '0' + str(Analysis.ArchInfo.bits / 4) + 'x') self.graph = Graph() self.regCount = { } # Keys are integers, values are integers. regCount[2] = 0 <=> R2_0 have appeared but R2_1 not yet self.spInc = None # How much have Stack Pointer been incremented by self.num = num # Identifier or the gadget self.normalRet = None # True iff the gadgets ends up by a normal ret; instruction self.nbInstr = 0 # Number of REIL instructions of this gadget self.dep = None self.valuesTable = {} # Used dinamically when building graph # Building graph and computing the dependencies self.buildGraph(irsb) self.getDependencies()
def load_config(): global ARCH global PATH_ROPGADGET global LIMIT # Check if the ROPGenerator director exists if (not os.path.isdir(ROPGENERATOR_DIRECTORY)): try: os.system('mkdir ' + ROPGENERATOR_DIRECTORY) except: pass try: f = open(ROPGENERATOR_CONFIG_FILE, "r") ARCH = f.readline()[:-1] PATH_ROPGADGET = f.readline()[:-1] LIMIT = int(f.readline()[:-1], 10) f.close() #info_colored("Loaded configuration\n") except: info_colored( "Couldn't load custom configuration, using the default one\n") default_config() Analysis.setArch(ARCH)
def default_config(): global ARCH global PATH_ROPGADGET ARCH = "X86_64" PATH_ROPGADGET = "usr/bin/ROPgadget" Analysis.setArch(ARCH)
def set_filetype(filetype): global FILETYPE if (filetype in Analysis.supportedFiletypes): FILETYPE = filetype Analysis.setFiletype(filetype)
def __init__(self, num, addr, raw): """ (raw) is the raw string of the instructions of the gadget """ # irsb is an array of BARF instructions # ins is an array of Assembly instructions if (raw in analyzed_raw_to_gadget): self._copy_gadget(num, addr, analyzed_raw_to_gadget[raw]) else: # Check for 'int 0x80' gadgets if (raw == '\xcd\x80'): self.num = num self.sort = GadgetSort.INT80 self.asmStr = 'int 0x80' self.hexStr = '\\xcd\\x80' self.addr = addr self.addrStr = '0x' + format( addr, '0' + str(Analysis.ArchInfo.bits / 4) + 'x') self.dep = GadgetDependencies() return # Check for 'syscall' gadgets elif (raw == '\x0f\x05'): self.num = num self.sort = GadgetSort.SYSCALL self.asmStr = 'syscall' self.hexStr = '\\x0f\\x05' self.addr = addr self.addrStr = '0x' + format( addr, '0' + str(Analysis.ArchInfo.bits / 4) + 'x') self.dep = GadgetDependencies() return # Build regular gadget try: (irsb, ins) = Analysis.getIR(raw, addr) except Analysis.AnalysisException as e: raise GadgetException(str(e)) self.sort = GadgetSort.REGULAR self.duplicate = None # If the gadget is a copy of another gadget, then self.duplicate = pointer to the original gadget ! # Some strings representations self.ins = ins # List of instructions self.asmStr = "; ".join(str(i) for i in ins) self.hexStr = "\\x" + "\\x".join("{:02x}".format(ord(c)) for c in raw) self.addr = addr # int # Get the string for the address, depends on the architecture size self.addrStr = '0x' + format( addr, '0' + str(Analysis.ArchInfo.bits / 4) + 'x') self.regCount = { } # Keys are integers, values are integers. regCount[2] = 0 <=> R2_0 have appeared but R2_1 not yet self.spInc = None # How much have Stack Pointer been incremented by self.num = num # Identifier or the gadget self.ret = RetType.UNKNOWN # Type of the last instruction of the gadget (ret, call, ... ) self.retValue = None # (int) register to jmp to if ret is CALL_REG or JMP_REG self.nbInstr = 0 # Number of REIL instructions of this gadget self.dep = None self.valuesTable = {} # Used dinamically when building graph self.validPreConstraint = None # If the preconstraint is valid or not self.preConstraint = None # Building graph and computing the dependencies self.graph = Graph() self.buildGraph(irsb) self.getDependencies() analyzed_raw_to_gadget[raw] = self
from ropgenerator.Database import * import ropgenerator.Analysis as Analysis Analysis.setArch("X86_64") generated_gadgets_to_DB() fillGadgetLookUp() # Print gadgetLookUp for reg in gadgetLookUp[GadgetType.REGtoREG].keys(): print str(reg) + ":" for reg2 in gadgetLookUp[GadgetType.REGtoREG][reg].keys(): if (gadgetLookUp[GadgetType.REGtoREG][reg][reg2] != []): print "\n\t<-- " + Analysis.revertRegNamesTable[reg2] print "\n\tFrom gadget:\n " + gadgetDB[gadgetLookUp[ GadgetType.REGtoREG][reg][reg2][0]].asmStr + "\n\t" + gadgetDB[ gadgetLookUp[ GadgetType.REGtoREG][reg][reg2][0]].hexStr + '\n' for cst in gadgetLookUp[GadgetType.CSTtoREG][reg].keys(): if (gadgetLookUp[GadgetType.CSTtoREG][reg][cst] != []): print "\n\t<-- " + str(cst) print "\n\tFrom gadget:\n " + gadgetDB[gadgetLookUp[ GadgetType.CSTtoREG][reg][cst][0]].asmStr + "\n\t" + gadgetDB[ gadgetLookUp[ GadgetType.CSTtoREG][reg][cst][0]].hexStr + '\n' #for mem in gadgetLookUp[GadgetType.MEMtoREG][reg].keys(): # if( gadgetLookUp[GadgetType.MEMtoREG][reg][mem] != []): # print("\n\t<-- MEM[" + str(mem) + "]") # print( "\n\tFrom gadget:\n " + gadgetDB[gadgetLookUp[GadgetType.MEMtoREG][reg][mem][0]].asmStr + "\n\t" + gadgetDB[gadgetLookUp[GadgetType.MEMtoREG][reg][mem][0]].hexStr + '\n' ) exit()
#if( reg.ind == tmp.currentGadget.regCount[reg.reg] ): print "[-] %s_%d dependencies:" % (revertRegNamesTable[reg.num], reg.ind) [show_dep(x) for x in dep] # "\x50\xC7\x06\x00\x00\x00\x00\x5B\xC3" "\x10\x5b\x5d\x41\x5c\x48\x0f\x45\xc2\xc3" # "\x50\x83\xC1\x01\x89\x0E\x5B\xC3" # "\x50\x67\xC7\x46\x01\x00\x00\x00\x00\x5B\xC3" # \x89\xe5\xff\xd0 # \xff\x75\x9c\x48\x89\xf8\xc3 TEST FOR MEMORY DEPENDENCIES WITH EXPRESSION # \xb6\xd2\x0f\xb6\xc0\x29\xd0\xc3 TEST FOR STRANGE CAT40 # Boucle infinie 39\xc8\x19\xc0\x83\xd8\xff\x5e\x5b\xc3 asm = "\x50\x5B\x5D\xC3" Analysis.setArch("X86") #try: gadget = Gadget(0, 0, asm) Expr.nb_regs = Analysis.ssaRegCount - 1 gadget.printHex() gadget.printInstr() gadget.calculateSpInc() gadget.calculateRet() Analysis.printRegTranslation() gadget.getDependencies().printRegDeps() print "MEMORY DEPENDENCIES" gadget.getDependencies().printMemDeps() print "ESP INC " + str(gadget.spInc) #except Exception as e: