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 __init__(self, addr_list, raw): """ addr_list = list of addresses of the gadget (if duplicate gadgets) raw = raw string of gadget asm """ # Check the type of the gadget # Check for 'int 0x80' gadgets if( raw == '\xcd\x80' and Arch.currentIsIntel()): self.type = GadgetType.INT80 self.asmStr = 'int 0x80' self.hexStr = '\\xcd\\x80' self.addrList = addr_list self.nbInstr = self.nbInstrREIL = 1 self.semantics = Semantics() return # Check for 'syscall' gadgets elif( raw == '\x0f\x05' and Arch.currentIsIntel()): self.type = GadgetType.SYSCALL self.asmStr = 'syscall' self.hexStr = '\\x0f\\x05' self.addrList = addr_list self.nbInstr = self.nbInstrREIL = 1 self.semantics = Semantics() return # Translate raw assembly into REIL # Then compute the Graph and its semantics try: (irsb, ins) = Arch.currentArch.asmToREIL(raw) except Arch.ArchException as e: raise GadgetException(str(e)) try: self.graph = REILtoGraph(irsb) self.semantics = self.graph.getSemantics() except GraphException as e: raise GadgetException("(In {}) - ".format('; '.join(str(i) for i in ins)) + str(e)) self.type = GadgetType.REGULAR # Possible addresses self.addrList = addr_list # String representations self.asmStr = '; '.join(str(i) for i in ins) self.hexStr = '\\x' + '\\x'.join("{:02x}".format(ord(c)) for c in raw) # Length of the gadget self.nbInstr = len(ins) self.nbInstrREIL = len(irsb) # List of modified registers # And of memory-read accesses self._modifiedRegs = [] self._memoryReads = [] for reg_num in list(set([reg.num for reg in self.semantics.registers.keys()])): # Check if there is an empty semantics if( not self.getSemantics(reg_num)): #self.semantics.registers.pop(reg) log("Gadget ({}) : empty semantics for {}"\ .format(self.asmStr, Arch.r2n(reg_num))) self._modifiedRegs.append(reg_num) continue # Get modified reg if ((SSAExpr(reg_num,0) != self.getSemantics(reg_num)[0].expr) ): self._modifiedRegs.append(reg_num) # Get memory reads for pair in self.getSemantics(reg_num): self._memoryReads += [m[0] for m in pair.expr.getMemAcc()] self._modifiedRegs = list(set(self._modifiedRegs)) # SP Increment if( self.type != GadgetType.REGULAR ): self.spInc = None else: sp_num = Arch.spNum() if( not sp_num in self.graph.lastMod ): self.spInc = 0 else: sp = SSAReg(sp_num, self.graph.lastMod[sp_num]) if( len(self.semantics.get(sp)) == 1 ): (isInc, inc) = self.semantics.get(sp)[0].expr.isRegIncrement(sp_num) if( isInc ): self.spInc = inc else: self.spInc = None else: self.spInc = None # Return type self.retType = RetType.UNKNOWN self.retValue = None if( self.type == GadgetType.REGULAR ): ip_num = Arch.n2r(Arch.currentArch.ip) ip = SSAReg(ip_num, self.graph.lastMod[ip_num]) sp_num = Arch.n2r(Arch.currentArch.sp) if( self.spInc != None ): for p in self.semantics.get(ip): if( p.cond.isTrue()): if( isinstance(p.expr, MEMExpr)): addr = p.expr.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 inc == (self.spInc - (Arch.currentArch.octets)) ): self.retType = RetType.RET self.retValue = p.expr elif( isinstance(p.expr, SSAExpr )): self.retValue = p.expr # Try to detect gadgets ending by 'call' if( ins[-1]._mnemonic[:4] == "call"): self.retType = RetType.CALL else: self.retType = RetType.JMP