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 __init__(self, view: BinaryView): self.view = view super().__init__() addr_size = self.view.address_size self.mem = { 1: Array("mem1", BitVecSort(addr_size * 8), BitVecSort(8)), 2: Array('mem2', BitVecSort(addr_size * 8), BitVecSort(16)), 4: Array('mem4', BitVecSort(addr_size * 8), BitVecSort(32)), 8: Array('mem8', BitVecSort(addr_size * 8), BitVecSort(64)), 16: Array('mem16', BitVecSort(addr_size * 8), BitVecSort(128)) }
def __init__(self, var, address_size): super(ByteSwapModeler, self).__init__() if (not isinstance(var, MediumLevelILInstruction) or var.operation != MediumLevelILOperation.MLIL_VAR_SSA): raise TypeError('var must be an MLIL_VAR_SSA operation') self.address_size = address_size self._memory = Array('Memory', BitVecSort(address_size * 8), BitVecSort(8)) self.solver = Solver() self.visited = set() self.to_visit = list() self.byte_values = dict() self.byte_vars = set() self.var = var self.function = var.function
def __init__(self, tx_id, starting_calldata=None): """ Constructor for Calldata :param tx_id: unique value representing the transaction the calldata is for :param starting_calldata: byte array representing the concrete calldata of a transaction """ self.tx_id = tx_id if starting_calldata: self._calldata = [] self.calldatasize = BitVecVal(len(starting_calldata), 256) self.concrete = True else: self._calldata = Array("{}_calldata".format(self.tx_id), BitVecSort(256), BitVecSort(8)) self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id), 256) self.concrete = False self.starting_calldata = starting_calldata or []
def prove_adversarial_property_z3(a_pace, b_pace, min_a, max_b, n_iterations): ''' Using z3 to probe the formula checking ReLu(sk * w) <= ylim[1] while sk <= sklim :param invariant_property: maximum value for sk :param weight: the weight between sk and the output :param ylim: max output :return: True if for every sk <= sklim implies that ReLu(sk * w) <= ylim ''' from math import log2, ceil num_bytes = ceil(log2(n_iterations)) + 1 print('n_iterations', n_iterations, '\nnum_bytes', num_bytes) assert n_iterations <= 2**num_bytes # if the bit vec is 32 z3 takes to long a_invariants = Array('a_invariants', BitVecSort(num_bytes), RealSort()) b_invariants = Array('b_invariants', BitVecSort(num_bytes), RealSort()) i = BitVec('i', num_bytes) n = BitVec('n', num_bytes) s = Solver() s.add(a_invariants[0] == min_a) s.add(b_invariants[0] == max_b) s.add(n == BitVecVal(n_iterations, num_bytes)) # The invariant s.add(ForAll(i, a_invariants[i] >= a_invariants[0] + BV2Int(i) * a_pace)) s.add(ForAll(i, b_invariants[i] <= b_invariants[0] + BV2Int(i) * b_pace)) # s.add(ForAll(i, a_invariants[i] >= a_invariants[0] + BV2Int(i * BitVecVal(a_pace, num_bytes)))) # s.add(ForAll(i, b_invariants[i] <= b_invariants[0] + BV2Int(i * BitVecVal(b_pace, num_bytes)))) # NOT the property to prove s.add(a_invariants[n] < b_invariants[n]) t = s.check() if t == sat: print("z3 result:", s.model()) return False else: print('proved adversarial property using z3') return True
def GetSortFromType(typ): if typ == 'Int': return IntSort() elif typ == 'Bool': return BoolSort() elif isinstance(typ, list): if (len(typ) != 2 or typ[0] != 'BitVec'): raise SynthException('Unknown Type %r' % (typ)) else: intName, size = typ[1] return BitVecSort(size) else: raise SynthException('Unknown Type %r' % (typ))
def __init__(self, tx_id, starting_calldata=None): """ Constructor for Calldata :param tx_id: unique value representing the transaction the calldata is for :param starting_calldata: byte array representing the concrete calldata of a transaction """ self.tx_id = tx_id if starting_calldata is not None: self._calldata = [] self.calldatasize = BitVecVal(len(starting_calldata), 256) self.concrete = True else: self._calldata = Array("{}_calldata".format(self.tx_id), BitVecSort(256), BitVecSort(8)) self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id), 256) self.concrete = False if self.concrete: for calldata_byte in starting_calldata: if type(calldata_byte) == int: self._calldata.append(BitVecVal(calldata_byte, 8)) else: self._calldata.append(calldata_byte)
def makeZ3Var(v): t = v.varType name = v.varName if t.startswith('INSTANCE:'): s = t[9:] if s == 'BYTE': return z3.Array(name, BitVecSort(32), z3.BitVecSort(8)) elif s == 'SHORT': return z3.Array(name, BitVecSort(32), z3.BitVecSort(16)) elif s == 'INT': return z3.Array(name, BitVecSort(32), z3.BitVecSort(32)) elif s == 'LONG': return z3.Array(name, BitVecSort(32), z3.BitVecSort(64)) elif s == 'FLOAT': return z3.Array(name, BitVecSort(32), Float) elif s == 'DOUBLE': return z3.Array(name, BitVecSort(32), Double) elif s == 'CHAR': return z3.Array(name, BitVecSort(32), z3.BitVecSort(16)) else: raise Exception("unsupported type {}".format(t)) elif t == 'BYTE': return z3.BitVec(name, 8) elif t == 'SHORT': return z3.BitVec(name, 16) elif t == 'INT': return z3.BitVec(name, 32) elif t == 'LONG': return z3.BitVec(name, 64) elif t == 'FLOAT': return z3.FP(name, Float) elif t == 'DOUBLE': return z3.FP(name, Double) elif t == 'CHAR': return z3.BitVec(name, 16) else: raise Exception("unsupported type {}".format(t))
def declare_type(self, elem_type: Type): len_elem_type = len(elem_type) if len_elem_type > 0: s = BitVecSort(ceil(log(len(elem_type), 2))) elem_type.add_engine_object(s)
def make_load(src, size): mem = Array('mem', BitVecSort(32), BitVecSort(8)) load_bytes = [mem[src + i] for i in range(0, size)] return Concat(*load_bytes)
# useful str collections triplet_dna_codons: List[CodonRef] = [ ''.join(codon_list) for codon_list in itertools.product(dNTPs, repeat=3) ] triplet_rna_codons: List[CodonRef] = [ ''.join(codon_list) for codon_list in itertools.product(rNTPs, repeat=3) ] aminoacids += ["0"] # adds NULL # useful z3 Sorts NucleotideEnumSort, z3_enum_nucleotides = EnumSort("Nucleotides", [f"d{n}" for n in dNTPs]) triplet_z3_enum_nucleotides = list( itertools.product(z3_enum_nucleotides, repeat=3)) NucleotideBitVecSort = BitVecSort(3) z3_bitvec_nucleotides = [ BitVec((2**i) - 1, NucleotideBitVecSort) for i in range(4) ] triplet_z3_bitvec_nucleotides = list( itertools.product(z3_bitvec_nucleotides, repeat=3)) CodonEnumSort, z3_enum_codons = EnumSort("Codons", triplet_dna_codons) AminoEnumSort, z3_enum_aminos = EnumSort("Amino Acids", aminoacids) AminoBitVecSort = BitVecSort(21) z3_bitvec_aminos = [BitVec((2**i) - 1, AminoBitVecSort) for i in range(22)] # z3amino definitions def get_start(aminos: Sequence[AminoRef] = z3_enum_aminos) -> AminoRef:
def original_variable(self, type, expr, instance): return Array(self.original_variable_name(type, expr, instance), BitVecSort(32), BitVecSort(8))
def env_variable(self, type, expr, instance, name): return Array(self.env_variable_name(type, expr, instance, name), BitVecSort(32), BitVecSort(8))
def output_variable(type, name, instance): s = '{}!output!{}!{}'.format(type, name, instance) if type == 'long': return Array(s, BitVecSort(32), BitVecSort(8)) else: return Array(s, BitVecSort(32), BitVecSort(8))
def env_variable(expr, instance, name): pattern = 'int!choice!{}!{}!{}!{}!{}!env!{}' s = pattern.format(expr[0], expr[1], expr[2], expr[3], instance, name) return Array(s, BitVecSort(32), BitVecSort(8))
def original_variable(type, expr, instance): pattern = '{}!choice!{}!{}!{}!{}!{}!original' s = pattern.format(type, expr[0], expr[1], expr[2], expr[3], instance) return Array(s, BitVecSort(32), BitVecSort(8))
def angelic_variable(self, type, expr, instance): return Array(self.angelic_variable_name(type, expr, instance), BitVecSort(32), BitVecSort(8))
def output_variable(self, type, name, instance): return Array(self.output_variable_name(type, name, instance), BitVecSort(32), BitVecSort(8))