def init_impossible_REGtoREG(env): global INIT_LMAX, INIT_MAXDEPTH global baseAssertion # DEBUG #try: startTime = datetime.now() i = 0 impossible_count = 0 for reg1 in sorted(Arch.registers()): reg_name = Arch.r2n(reg1) if (len(reg_name) < 6): reg_name += " " * (6 - len(reg_name)) elif (len(reg_name) >= 6): reg_name = reg_name[:5] + "." for reg2 in Arch.registers(): i += 1 charging_bar(len(Arch.registers() * len(Arch.registers())), i, 30) if (reg2 == reg1 or reg2 == Arch.ipNum()): continue _search(QueryType.REGtoREG, reg1, (reg2, 0), env, n=1) if (env.checkImpossible_REGtoREG(reg1, reg2, 0)): impossible_count += 1 cTime = datetime.now() - startTime # Get how many impossible path we found impossible_rate = int(100 * (float(impossible_count) / float( (len(Arch.registers()) - 1) * len(Arch.registers())))) notify('Optimization rate : {}%'.format(impossible_rate)) notify("Computation time : " + str(cTime))
def init_impossible_REGtoREG(env): global INIT_LMAX, INIT_MAXDEPTH global baseAssertion try: startTime = datetime.now() i = 0 impossible_count = 0 for reg1 in sorted(Arch.registers()): reg_name = Arch.r2n(reg1) if (len(reg_name) < 6): reg_name += " " * (6 - len(reg_name)) elif (len(reg_name) >= 6): reg_name = reg_name[:5] + "." for reg2 in Arch.registers(): i += 1 charging_bar(len(Arch.registers() * len(Arch.registers())), i, 30) if (reg2 == reg1 or reg2 == Arch.ipNum()): continue _search(QueryType.REGtoREG, reg1, (reg2, 0), env, n=1) if (env.checkImpossible_REGtoREG(reg1, reg2, 0)): impossible_count += 1 cTime = datetime.now() - startTime # Get how many impossible path we found impossible_rate = int(100 * (float(impossible_count) / float( (len(Arch.registers()) - 1) * len(Arch.registers())))) notify('Optimization rate : {}%'.format(impossible_rate)) notify("Computation time : " + str(cTime)) except: print("\n") fatal("Exception caught, stopping Semantic Engine init process...\n") fatal("Search time might get very long !\n") env = SearchEnvironment(INIT_LMAX, Constraint(), baseAssertion, INIT_MAXDEPTH)
def getGadgets(filename): """ Returns a list of gadgets extracted from a file Precondition: the file exists Returns ------- list of pairs (addr, asm) if succesful None if failure """ ropgadget = "ROPgadget" notify("Executing ROPgadget as: " + ropgadget ) try: p = subprocess.Popen([ropgadget,"--binary",filename,"--dump", "--all"],stdout=subprocess.PIPE) except Exception as e: error("Could not execute '" +ropgadget+ " --binary " + filename + " --dump --all'") print("\tError message is: " + str(e)) print("\n\t(Maybe check/update your config with the 'config' command,\n\t or make sure you have the last ROPgadget version installed)") return None # Get the gadget list # Pairs (address, raw_asm) first = True count = 0 res = [] for l in p.stdout.readlines(): if("0x" in l): arr = l.split(' ') addr = arr[0] raw = b16decode(arr[-1].upper().strip()) res.append((int(addr,16), raw)) count += 1 notify("Finished : %d gadgets generated" % (count)) return res
def getPlatformInfo(filename): """ Checks the binary type of the file Precondition: the file exists ! Effects: set the Arch.currentBinType variable Return : the architecture """ 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") Arch.currentBinType = Arch.BinaryType.X86_ELF return Arch.ArchX86 elif ([sub for sub in ELF64_strings if sub in output]): notify("ELF 64-bits detected") Arch.currentBinType = Arch.BinaryType.X64_ELF return Arch.ArchX64 elif ([sub for sub in PE32_strings if sub in output]): notify("PE 32-bits detected") Arch.currentBinType = Arch.BinaryType.X86_PE return Arch.ArchX86 elif ([sub for sub in PE64_strings if sub in output]): notify("PE 64-bits detected") Arch.currentBinType = Arch.BinaryType.X64_PE return Arch.ArchX64 else: notify("Unknown binary type") Arch.currentBinType = Arch.BinaryType.UNKNOWN return None else: return None
def remove(arch): if (not shellcodes[arch]): error("No shellcodes to remove for architecture " + arch) return list_shellcodes(arch) print("") choice = '' ok = False sys.stdout.write('\t' + string_ropg('> ') + 'Select a shellcode to remove:\n') while (not ok): choice_input = prompt(u" > ") try: choice = int(choice_input) ok = remove_shellcode(arch, choice) if (not ok): print(string_special("\tError. Invalid choice")) except: ok = False print("") notify('Shellcode removed')
def build_dshell(shellcode, constraint, assertion, address, limit, lmax): """ Returns a PwnChain() instance or None """ # Build exploit ################# res = PwnChain() #Find address for the payload if (not address): # Get the .bss address # TODO notify("Getting delivery address for shellcode") address = getSectionAddress('.bss') addr_str = ".bss" if (not address): verbose("Couldn't find .bss address") return [] else: addr_str = hex(address) if (not limit): limit = address + Arch.minPageSize() # Deliver shellcode notify("Building chain to copy shellcode in memory") verbose("{}/{} bytes available".format(lmax * Arch.octets(), lmax * Arch.octets())) (shellcode_address, STRtoMEM_chain) = STRtoMEM(shellcode, address, constraint, assertion, limit=limit, lmax=lmax, addr_str=addr_str, hex_info=True, optimizeLen=True) address = shellcode_address addr_str = hex(address) if (not STRtoMEM_chain): verbose("Could not copy shellcode into memory") return None # Building mprotect notify("Building mprotect() chain") # Getting page to make executable # Arg of mprotect MUST be a valid multiple of page size over_page_size = address % Arch.minPageSize() page_address = address - over_page_size length = len(shellcode) + 1 + over_page_size flag = 7 lmax2 = lmax - len(STRtoMEM_chain) verbose("{}/{} bytes available".format(lmax2 * Arch.octets(), lmax * Arch.octets())) if (lmax2 <= 0): return None if (Arch.currentArch == Arch.ArchX86): mprotect_chain = build_mprotect32(page_address, length, flag, constraint.add(Chainable(ret=True)), assertion, clmax=lmax2 - 2, optimizeLen=True) elif (Arch.currentArch == Arch.ArchX64): mprotect_chain = build_mprotect64(page_address, length, flag, constraint.add(Chainable(ret=True)), assertion, clmax=lmax2 - 2, optimizeLen=True) else: mprotect_chain = None verbose("mprotect call not supported for architecture {}".format( Arch.currentArch.name)) return None if (not mprotect_chain): return None verbose("Done") # Jump to shellcode notify("Searching chain to jump to shellcode") verbose("{}/{} bytes available".format( (lmax2 - len(mprotect_chain)) * Arch.octets(), lmax * Arch.octets())) jmp_shellcode_chains = search(QueryType.CSTtoREG, Arch.ipNum(), address, constraint, assertion, clmax=lmax - len(STRtoMEM_chain) - len(mprotect_chain), optimizeLen=True) if (not jmp_shellcode_chains): verbose("Couldn't find a jump to the shellcode") return None verbose("Done") notify("Done") # Build PwnChain res and return res.add(mprotect_chain, "Call mprotect({},{},{})".format(hex(page_address), length, flag)) res.add(STRtoMEM_chain, "Copy shellcode to {}".format(addr_str)) res.add(jmp_shellcode_chains[0], "Jump to shellcode (address {})".format(addr_str)) return res
def build(pair_list): """ Takes a list of pairs (addr, raw_asm) corresponding to gagets (their address and their intructions as a byte string) Fills the 'gadgets' and 'db' global structures ;) """ def sigint_handler(signal, frame): global sigint sigint = True def timeout_handler(signum, frame): global sigalarm sigalarm = True signal.alarm(0) raise TimeOutException('Timeout') global gadgets, db, sigint gadgets = [] raw_to_gadget = dict() sigint = False original_sigint_handler = signal.getsignal(signal.SIGINT) signal.signal(signal.SIGINT, sigint_handler) signal.signal(signal.SIGALRM, timeout_handler) info(string_bold("Creating gadget database\n")) startTime = datetime.now() success = i = 0 # Create the gadgets list for (addr, raw) in pair_list: charging_bar(len(pair_list) - 1, i, 30) if (sigint): break if (raw in raw_to_gadget): gadgets[raw_to_gadget[raw]].addrList.append(addr) success += 1 else: try: signal.alarm(1) gadget = Gadget([addr], raw) signal.alarm(0) success += 1 gadgets.append(gadget) raw_to_gadget[raw] = len(gadgets) - 1 except (GadgetException, TimeOutException) as e: signal.alarm(0) if (isinstance(e, GadgetException)): log("Gadget ({}) : ".format('\\x'+'\\x'\ .join("{:02x}".format(ord(c)) for c in raw)) + str(e)) i += 1 # Find syscalls # TODO # Getting time cTime = datetime.now() - startTime signal.signal(signal.SIGINT, original_sigint_handler) if (sigint): print("\n") fatal( "SIGINT ended the analysis prematurely, gadget database might be incomplete\n" ) sigint = False notify("Gadgets analyzed : " + str(len(pair_list))) notify("Successfully translated : " + str(success)) notify("Computation time : " + str(cTime)) # Create the database db = Database(gadgets)