def detectMemAccess(self, reil_code, callstack, inputs, counter): pins = parse_reil(reil_code[-1]) ins = Instruction(pins, None) assert (ins.instruction in ["stm", "ldm"]) addr_op = ins.getMemReg() #print "op:", addr_op, ins.address val = getTypedValueFromCode(reil_code, callstack, inputs, self, addr_op) #print val if (val.isMem()): #if self.__isArgMem__(val, callstack.callstack[1]): # print "arg detected at", ins, "with", str(val) # self.access[counter] = self.__getArgMemAccess__(ins, val, callstack.callstack[1]) #else: #print val self.access[counter] = self.__getMemAccess__(ins, val) elif (val.isImm): self.access[counter] = self.__getGlobalMemAccess__( ins, int(val.name)) else: assert (0)
def __init__(self, params=dict()): self.num_threads = int( params["NUM_THREAD"]) if "NUM_THREAD" in params.keys( ) else NUM_THREADS self.num_stages = int( params["NUM_STAGES"]) if "NUM_STAGES" in params.keys( ) else NUM_STAGES self.stages = FIFOQueue(self.num_stages) self.stages.set_q_list([Instruction.empty_inst(0)] * self.num_stages) # Statistics self.committed_inst = Instruction() self.count_flushed_inst = 0 self.count_committed_inst = 0 self.num_of_flushes = 0 # Resources # TODO-? # Pointer to relevant units units self.thread_unit = None self.issue_unit = None self.fetch_unit = None self.generate_csv() # bp self.bp_en = params["BP_EN"] == "True" if "BP_EN" in params.keys( ) else BP_EN
def generate_csv(self): if EX_DUMP_TO_CSV: with open(EX_DUMP_CSV_PATH, 'w', newline='') as csv_file: report_writer = csv.writer(csv_file) if EX_DUMP_TO_CSV: empty = Instruction() header = empty.csv_list(header=True) report_writer.writerow(header)
def executeProgram(self, instructions: bytes): self.instructions = instructions self.PC = 0 instructionArr = [Instruction.ADC(), Instruction.ORA()] print("Running program: \n" + str(instructions)) while (self.PC >= 0 and self.PC < len(instructions)): print("Current instruction: " + str(self.PC) + " : " + str(int(instructions[self.PC]))) instructionArr[0].execute(instructions[self.PC], self)
def inst_typedef(instruction): if instruction[0] == '*': return None elif instruction[0] == 's': return Ins.InitialInstruction(instruction[0], instruction[4]) elif instruction[2] == ' ': return Ins.WriteInstruction(instruction[0], instruction[4], instruction[6:-1]) else: return Ins.ReadInstruction(instruction[0], instruction[4], instruction[2])
def getValueFromCode(inss, initial_values, op): assert (len(inss) > 0) # code should be copied and reversed inss.reverse() # counter is set counter = len(inss) ssa = SSA() smt_conds = SMT() # we will track op mvars = set([op]) ssa.getMap(mvars, set(), set()) for ins_str in inss: #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, None) # no memory and callstack are available ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) mvars = set(filter(lambda o: o.name <> "ebp", mvars)) smt_conds.add(condition.getEq()) counter = counter - 1 for iop in initial_values.keys(): if not (iop in ssa): del initial_values[iop] ssa_map = ssa.getMap(set(), set(), set(initial_values.keys())) eq = Eq(None, None) for iop in initial_values: smt_conds.add(eq.getEq(ssa_map[iop.name], initial_values[iop])) op.name = op.name + "_0" smt_conds.solve() return smt_conds.getValue(op)
def getValueFromCode(inss, initial_values, op): assert(len(inss) > 0) # code should be copied and reversed inss.reverse() # counter is set counter = len(inss) ssa = SSA() smt_conds = SMT() # we will track op mvars = set([op]) ssa.getMap(mvars, set(), set()) for ins_str in inss: #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, None) # no memory and callstack are available ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) mvars = set(filter(lambda o: o.name <> "ebp", mvars)) smt_conds.add(condition.getEq()) counter = counter - 1 for iop in initial_values.keys(): if not (iop in ssa): del initial_values[iop] ssa_map = ssa.getMap(set(), set(), set(initial_values.keys())) eq = Eq(None, None) for iop in initial_values: smt_conds.add(eq.getEq(ssa_map[iop.name],initial_values[iop])) op.name = op.name+"_0" smt_conds.solve() return smt_conds.getValue(op)
def decode(mode, instr): re_line = re.compile( r'^(?:\S+\s+)?(?P<instr>add|sub|xor|not|mul)\s+(?P<arg1>([A-Za-z0-9_\[\]+*\-]|\s)+)\s*' r'(?:,\s*(?P<arg2>([A-Za-z0-9_\[\]+*\-]|\s)+))?' ) instruction = re_line.search(instr) if instruction is None: return '>>> Invalid instruction! Please try again.' instruction = instruction.groupdict() instruction = Instruction(mode, instruction['instr'], instruction['arg1'], instruction['arg2']) instruction.validate_arguments() ans = instruction.translate() ans = ' '.join([ans[i : i + 4] for i in range(0, len(ans), 4)]) return ans
def decode(self, address, inst): """ Find the type of an instruction, and call for it to be decoded. """ i = Instruction() i.address = address i.inst = inst i.decode() # Pass on to specific op if i.system: decoder = sys_ops[i.op] else: decoder = ops[i.op][i.subop] if decoder == None: # unknown instruction # system, op, subop return i else: # Use specific decoder i = decoder(i) try: i.decode() except DecodeError, e: # Error decoding instruction i.warnings.append(e.message) return i
def __init__(self, reil_code): # The first instruction should be a call self.callstack = [None] self.stack_diff = [] self.index = 0 #self.prev_callstack = [None] # aditional information need to compute the callstack self.calls = [None] self.esp_diffs = [None] self.reil_code = reil_code reil_size = len(reil_code) start = 0 for (end, ins_str) in enumerate(self.reil_code): #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, None) if (ins.instruction == "call" and ins.called_function == None) or ins.instruction == "ret": self.__getStackDiff__(ins.instruction, ins.address, reil_code[start:end]) start = end if (start <> reil_size - 1): pins = parse_reil(reil_code[start]) self.__getStackDiff__(pins.instruction, pins.address, reil_code[start:reil_size]) self.index = len(self.callstack) - 1
def move_inst_unit_unpipelined(self, to_unit, from_unit, number_of_cycles): if (to_unit.is_free()): if (from_unit == None): if (self.all_inst_fetched == False): from_unit_complete_inst = Instruction( self.set_of_instructions[self.registers['PC']].strip(), self.current_inst) self.registers['PC'] += 1 self.current_inst += 1 else: return else: from_unit_complete_inst = from_unit.get_completed_inst() if (from_unit_complete_inst != False): if (to_unit.add_new_inst_unpipelined( from_unit_complete_inst, number_of_cycles) == False): print "Debugging Time" return False return from_unit_complete_inst else: if (from_unit != None and from_unit != self.IF): if (from_unit.peek_completed_inst() != False): self.result[ from_unit.peek_completed_inst().inst_addr][7] = 'Y' return False
def _get_corresponding_inst(self, label): for i in range(len(self.set_of_instructions)): instruction = Instruction(self.set_of_instructions[i], i) if instruction.label == label: return i print "Error: Invalid instruction: missing label" exit()
def detectFuncParameters(self, reil_code, memaccess, callstack, inputs, counter): pins = parse_reil(reil_code[-1]) ins = Instruction(pins, None) assert (ins.instruction == "call" and ins.called_function <> None) # first we locate the stack pointer to know where the parameters are located esp = Operand("esp", "DWORD") pbase = getTypedValueFromCode(reil_code, callstack, inputs, memaccess, esp) #print pbase.name #print pbase.mem_source # func_cons = funcs.get(ins.called_function, Function) func = func_cons(pbase=pbase) parameters = [] for (par_type, location, needed) in func.getParameterLocations(): #print (ins.called_function, par_type, location.mem_source, needed) if needed: reil_code.reverse() reil_code.reset() val = getTypedValueFromCode(reil_code, callstack, inputs, memaccess, location) #print "parameter of",ins.called_function, "at", str(location) , "has value:", val.name parameters.append((location, val)) else: parameters.append((None, None)) if parameters <> []: self.parameters[counter] = self.__getParameters__(ins, parameters)
def __init__(self, in_filename, out_filename): # Set initial values for MIPS engine print("Loading...") self._offset = 0 self._program = {} self._PC = 0 self._error = False # Read in hex file self._f = open(in_filename) inst_all = self._f.read() inst_temp = inst_all.split('\n') # Store all instructions by initializing Instruction objects into _program dictionary # indexed by _PC self._program_len = len(inst_temp) self._PC_last = self._program_len - 1 print('# instructions: {}\tLast Instruction: {}'.format( len(inst_temp), self._PC_last)) for i in range(0, len(inst_temp)): self._program[self._PC] = Instruction.Instruction(inst_temp[i]) self._PC = self._PC + 1 # Output assembly file self._output_f = open(out_filename, 'w') for key in self._program: self._program[key].print_inst() self._output_f.write(self._program[key].get_inst() + '\n') self._output_f.close() print() self._PC = 0 #self.print_state() self._save_cur_state() print('...Program loaded successfully')
def test_SLL(self): instrn_list = [ '00050018', '00010001', '00432020', '009E001C', '009E001E', '0121482E', '00031025', '34830000', 'ACC40000', '00C60001', '10050002', '0BFFFFF6', ] human_instrn_list = [ '00050018', '00010001', '00432020', '009E001C', '009E001E', '0121482E', '00031025', '34830000', 'ACC40000', '00C60001', '10050002', '0BFFFFF6', ] for instrn, human_instrn in zip(instrn_list, human_instrn_list): print 'instrn: ', instrn bin_string = Memory.Memory.get_bin_from_hex_instruction(instrn) instruction = Instruction.Instruction(bin_string) print instruction
def advance(self): #Fetch the next instruction according to simulator program counter # ...if we are not outside instruction memory if self.simulator.programCounter < ( len(self.simulator.instrCollection) * 4 + 0x0): self.instr = self.simulator.instructionMemory[ self.simulator.programCounter] # Non-NOP instruction if (self.instr and self.instr.op != "nop" and self.instr.op != None): self.simulator.instrCount += 1 # NOP if (self.instr.op is 'nop'): self.simulator.instrCount += 1 self.simulator.nopCount += 1 # Instruction is a core instruction if (self.instr.coreInstr): self.simulator.coreInstrCount += 1 # Instruction is a core instruction and a NOP if (self.instr.op is 'nop'): self.simulator.coreNopCount += 1 else: # Something wrong (outside memory range) - ignore instruction self.instr = Instruction(op='nop', coreInstr=False) # Advance PC self.simulator.programCounter += 4
def main(): print("Start") print("Setting all types of instructions into a dict") iparser = Instruction.InstructionParser() print("iparser : ", iparser) pipelinesim = PipelineSimulator.PipelineSimulator( iparser.parseFile("sample.txt")) config = iparser.parseConfigFile("config.txt") print("***************************************************") print("Summary so far: ") print("1. File Read") print("2. Parsed and determined type of instruction") print("3. Stored in a list of instructions") print("4. Created Registers") print("5. Created Main Memory") print("6. Added each instruction to the main memory") print("***************************************************") filename = "debug.txt" print("File name : ", filename) f = open(filename, 'w') print("Begining to Run") pipelinesim.run() print("Done Running") sys.stdout = f
def disassemble(self, filename): #Exécution d'opdis et récupération du XML xml = subprocess.Popen( ["opdis", "-q", "-d", "-f", "xml", "-N", "main", filename], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.read() document = parseString(xml).documentElement #Création de la liste des instructions instructions_table = [] vma_instructions_table = {} for instructionNode in document.getElementsByTagName("instruction"): instruction = Instruction.Instruction( self.get_xml_child_value(instructionNode, "offset"), self.get_xml_child_value(instructionNode, "vma"), self.get_xml_child_value(instructionNode, "ascii"), self.get_xml_child_value(instructionNode, "mnemonic")) if (self.xml_node_has_child(instructionNode, "operands")): for operandNode in instructionNode.getElementsByTagName( "operand"): operand = Operand.Operand( operandNode.attributes["name"] if ("name" in operandNode.attributes) else "", self.get_xml_child_value(operandNode, "ascii")) instruction.add_operand(operand) instructions_table.append(instruction) vma_instructions_table[int(instruction.vma, 0)] = instruction return (instructions_table, vma_instructions_table)
def getJumpConditions(trace, addr): raw_ins = parse_reil(trace["code"][-1]) addr = int(addr, 16) pos = trace["code"].last - 1 if (raw_ins.instruction == "jcc"): ins = Instruction(raw_ins, None) jmp_op = ins.operands[2] if (jmp_op.isVar()): #print addr trace["final_conditions"] = dict([(jmp_op, Operand(str(addr), "DWORD"))]) sol = getPathConditions(trace) if (sol <> None): print "SAT conditions found!" filename = raw_ins.instruction + "[" + str(pos) + "]" dumped = sol.dump(filename, input_vars) for filename in dumped: print filename, "dumped!" else: print "Impossible to jump to", hex( addr), "from", raw_ins.instruction, "at", pos else: return None else: return None
def __init__(self, in_filename, out_filename, mem_config=0): # Set initial values for MIPS engine self._offset = 0 self._program = {} self._PC = 0 # Initialize memory configuration self._mem = Memory.Memory(mem_config) # Read in hex file self._f = open(in_filename) inst_all = self._f.read() inst_temp = inst_all.split('\n') # Store all instructions by initializing Instruction objects into _program dictionary # indexed by _PC self._program_len = len(inst_temp) self._PC_last = (self._program_len * 4) - 4 print('# instructions: {}\tLast Instruction: {}'.format( len(inst_temp), self._PC_last)) for i in range(0, len(inst_temp)): self._program[self._PC] = Instruction.Instruction(inst_temp[i]) self._PC = self._PC + 4 # Output assembly file self._output_f = open(out_filename, 'w') for key in self._program: self._program[key].print_inst() self._output_f.write(self._program[key].get_inst() + '\n') self._output_f.close() print() self._PC = 0 self.print_state() self._save_cur_state()
def main(): iparser = Instruction.InstructionParser() pipelinesim = PipelineSimulator.PipelineSimulator(iparser.parseFile(sys.argv[1])) filename = sys.argv[2] if len(sys.argv) > 2 else "debug.txt" f = open(filename, 'w') sys.stdout = f pipelinesim.run()
def getExploitConditions(trace, value, address, filename): callstack = trace["callstack"] inss = trace["raw_code"] mem_access = trace["mem_access"] stm = parse_reil(inss[-1]) if stm.instruction <> "stm": print "#ERROR: Selected instruction is not a store memory" return else: stm = Instruction(stm,None) addr_op = stm.getMemReg() val_op = stm.getReadRegOperands()[0] getValueFromCode(inss[:-1], callstack, mem_access, addr_op, address, val_op, value)
def populateDests(self): #dest self.__m_Dests.append(Instruction.Instruction('null', '000')) self.__m_Dests.append(Instruction.Instruction('M', '001')) self.__m_Dests.append(Instruction.Instruction('D', '010')) self.__m_Dests.append(Instruction.Instruction('MD', '011')) self.__m_Dests.append(Instruction.Instruction('A', '100')) self.__m_Dests.append(Instruction.Instruction('AM', '101')) self.__m_Dests.append(Instruction.Instruction('AD', '110')) self.__m_Dests.append(Instruction.Instruction('AMD', '111'))
def populateJumps(self): #jumps self.__m_Jumps.append(Instruction.Instruction('null', '000')) self.__m_Jumps.append(Instruction.Instruction('JGT', '001')) self.__m_Jumps.append(Instruction.Instruction('JEQ', '010')) self.__m_Jumps.append(Instruction.Instruction('JGE', '011')) self.__m_Jumps.append(Instruction.Instruction('JLT', '100')) self.__m_Jumps.append(Instruction.Instruction('JNE', '101')) self.__m_Jumps.append(Instruction.Instruction('JLE', '110')) self.__m_Jumps.append(Instruction.Instruction('JMP', '111'))
def addUserLabels(self): for line in self.__m_rawCommands: if (self.isLabel(line)): #cut out first and last () name = line[1:-1] #append label and rom to label table self.__m_Symbols.append((Instruction.Instruction(name, self.__m_rom))) else: self.__m_rom += 1
def test_asm(x): i = Instruction() i.visited = None i.parse(x) # Print instruction, to test parsing/dumping print "in %s" % (i) # Assemble i.inst = assemble(i) #print "%08x %08x" %(i.inst[0], i.inst[1]) # Then disassemble again, and see if we get similar result d = Disassembler() i2 = d.decode(0, i.inst) #print i2 print "%08x %08x %s" % (i.inst[0], i.inst[1], i2) print
def getPathConditions(trace, filename): callstack = list(trace["callstack"]) inss = list(trace["raw_code"]) mem_access = trace["memaccess"] SSA.SSAinit() mvars = set() smt_conds = SMT() #assert(False) for ins_str in inss: #print ins_str.strip("\n") # Instruction parsing pins = parse_reil(ins_str) # Instruction processing current_call = trace["current_call"] mem_access = trace["memaccess"].getAccess(pins.address) ins = Instruction(pins,current_call,mem_access) ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if pins.instruction == "jcc" or len(ins_write_vars.intersection(mvars)) > 0: ssa_map = SSA.SSAMapping(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) mvars = set(filter(lambda o: o.name <> "ebp", mvars)) smt_conds.add(condition.getEq()) #print "mvars ops:" #for op in mvars: # print op smt_conds.write_smtlib_file(filename+".smt2") smt_conds.write_sol_file(filename+".sol")
def addUserSymbols(self): self.addUserLabels() #user defined symbols (check on address start and increment) for line in self.__m_rawCommands: name = line[1:] if self.isA(line) and (not name.isdigit()) and (not self.isNameInTable(name, self.__m_Symbols)): #test if symbol is added at the right address #print("symbol is {0}, address is {1}".format(name, self.__m_ram)) #end test self.__m_Symbols.append(Instruction.Instruction(name, self.__m_ram)) self.__m_ram += 1
def doBranch(self): # Read target value targetval = int(self.instr.immed) # Debug output if in verbose mode if (self.simulator.verbose): print "Branching to target ", hex(targetval) # Update PC self.simulator.programCounter = targetval + 4 # Set the other instructions currently in the pipeline to NOPS (depending on the number of IF stages) self.simulator.pipeline[0] = FetchStage( Instruction(op='nop', coreInstr=True), self) if (self.simulator.nIFit >= 2): self.simulator.pipeline[1] = FetchStage( Instruction(op='nop', coreInstr=True), self) if (self.simulator.nIFit == 3): self.simulator.pipeline[2] = FetchStage( Instruction(op='nop', coreInstr=True), self) # Indicate branch by setting branched flag self.simulator.branched = True
def setUp(self): self.instruction_string = 'R ADD R1 R2 R3' self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.npc = 4 self.PC = 0 self.input_dict = { 'instr': self.instr, 'npc': self.npc, 'PC': self.PC, } self.fetcher_buffer = fetcher_buffer.FetcherBuffer(self.input_dict)
def setUp(self): self.instruction_string = 'R ADD R1 R2 R3' self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.fetch_input_buffer = FetchInputBuffer({ 'PC': 0, 'instr_count': 0, }) self.fetcher_buffer = FetcherBuffer({}) self.fetch_stage = fetch_stage.FetchStage(self.memory, self.fetch_input_buffer, self.fetcher_buffer)
def create_graph(self, instructions_table, vma_instructions_table): graph = nx.DiGraph() start = Instruction.Instruction("-0x1", "-0x1", "\\<start\\>", "\\<start\\>") end = Instruction.Instruction("-0x1", "-0x1", "\\<end\\>", "\\<end\\>") instructions_table.insert(0, start) instructions_table.append(end) for i in range(len(instructions_table)): if (i != 0): graph.add_edge( "\"" + instructions_table[i - 1].create_string() + "\"", "\"" + instructions_table[i].create_string() + "\"") instruction = instructions_table[i] if super(RegularDriver, self).is_jump(instruction): targetVma = instruction.operands[0].ascii graph.add_edge( "\"" + instruction.create_string() + "\"", "\"" + vma_instructions_table[int(targetVma, 0)].create_string() + "\"") return graph
def detectMemAccess(self, reil_code, callstack, inputs, counter): pins = parse_reil(reil_code[-1]) ins = Instruction(pins,None) assert(ins.instruction in ["stm", "ldm"]) addr_op = ins.getMemReg() #print "op:", addr_op, ins.address val = getTypedValueFromCode(reil_code, callstack, inputs, self, addr_op) #print val if (val.isMem()): #if self.__isArgMem__(val, callstack.callstack[1]): # print "arg detected at", ins, "with", str(val) # self.access[counter] = self.__getArgMemAccess__(ins, val, callstack.callstack[1]) #else: #print val self.access[counter] = self.__getMemAccess__(ins, val) elif (val.isImm): self.access[counter] = self.__getGlobalMemAccess__(ins, int(val.name)) else: assert(0)
def getValueFromCode(reil_code, callstack, memory, addr_op, addr, val_op, val): assert(reil_code <> []) free_variables = [] # code should be copied and reversed inss = list(reil_code) inss.reverse() # counter is set counter = len(reil_code) tracked_stack_frame = callstack.index # especial operands in a call ssa = SSA() smt_conds = SMT() # we will track op mvars = set([addr_op, val_op]) ssa_map = ssa.getMap(mvars, set(), set()) eq = Eq(None, None) addr = Operand(str(addr), "DWORD") val = Operand(str(val), "BYTE") val.size = val_op.size smt_conds.add(eq.getEq(ssa_map[addr_op.name],addr)) smt_conds.add(eq.getEq(ssa_map[val_op.name],val)) for ins_str in inss: #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, memory.getAccess(counter), mem_regs = False) ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if pins.instruction == "jcc" or len(ins_write_vars.intersection(mvars)) > 0: #if len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) smt_conds.add(condition.getEq()) counter = counter - 1 if len(mvars) > 0: tracked_stack_frame = callstack.index if pins.instruction == "call": if callstack.index == 1: esp_val = 4 else: esp_val = 8 ebp_val = 0 esp_op = Operand("esp","DWORD") ebp_op = Operand("ebp","DWORD") initial_values_at_call = dict() initial_values_at_call[esp_op] = Operand(str(esp_val), "DWORD") initial_values_at_call[ebp_op] = Operand(str(ebp_val), "DWORD") for iop in initial_values_at_call.keys(): if not (iop in mvars): del initial_values_at_call[iop] ssa_map = ssa.getMap(set(), set(), set(initial_values_at_call.keys())) eq = Eq(None, None) for iop in initial_values_at_call: smt_conds.add(eq.getEq(ssa_map[iop.name],initial_values_at_call[iop])) mvars = set(filter(lambda o: not (o in initial_values_at_call.keys()), mvars)) if (counter == 0 and len(mvars)>0): #cond = Initial_Cond(None, None) # #for v in mvars: # print str(v), # smt_conds.add(cond.getEq(v)) #print "are free" #print smt_conds.solver free_variables = mvars break new_mvars = set() for v in mvars: if v.isMem(): # this should work for stack memory eop = callstack.convertStackMemOp(v) #print eop smt_conds.add(eq.getEq(v,eop)) new_mvars.add(eop) mvars = set(filter(lambda o: not (o.isMem()), mvars)) mvars = mvars.union(new_mvars) # we update the current call for next instruction callstack.prevInstruction(ins_str) #op.name = op.name+"_0" smt_conds.solve() smt_conds.write_smtlib_file("exp.smt2") smt_conds.write_sol_file("exp.sol") if (smt_conds.is_sat()): print "Solution:", for v in free_variables: if v.isReg(): if (v in ssa_map): print v,smt_conds.getValue(ssa_map[v]) elif v.isMem(): sname, offset = stack.read(v) v.mem_source = sname print v, smt_conds.getValue(v) else: print "Not exploitable"
def getPathConditions(trace): inss = trace["code"] callstack = trace["callstack"] initial_values = trace["initial_conditions"] final_values = trace["final_conditions"] memory = trace["mem_access"] parameters = trace["func_parameters"] # we reverse the code order inss.reverse() # we reset the used memory variables Memvars.reset() # we set the instruction counter counter = len(inss)-1 # ssa and smt objects ssa = SSA() smt_conds = SMT() # auxiliary eq condition eq = Eq(None, None) mvars = set() # final conditions: for (op, _) in final_values.items(): mvars.add(op) ssa.getMap(mvars, set(), set()) setInitialConditions(ssa, final_values, smt_conds) # we start without free variables fvars = set() for ins_str in inss: #print ins_str.strip("\n") #for v in mvars: # print v, # pins = parse_reil(ins_str) ins = Instruction(pins, memory.getAccess(counter), mem_regs = False) ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if pins.instruction == "jcc" or len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) smt_conds.add(condition.getEq()) elif (ins.instruction == "call" and ins.called_function <> None): func_cons = funcs.get(ins.called_function, Function) func = func_cons(None, parameters.getParameters(counter)) func_write_vars = set(func.getWriteVarOperands()) func_read_vars = set(func.getReadVarOperands()) #for op in func_write_vars: # print op if len(func_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(func_read_vars.difference(mvars), func_write_vars, func_read_vars.intersection(mvars)) cons = conds.get(ins.called_function, Condition) condition = cons(func, None) c = condition.getEq(func_write_vars.intersection(mvars)) mvars = mvars.difference(func_write_vars) mvars = func_read_vars.union(mvars) smt_conds.add(c) # additional conditions mvars = addAditionalConditions(mvars, ins, ssa, callstack, smt_conds) # no more things to do # we update the counter counter = counter - 1 # we update the current call for next instruction callstack.prevInstruction(ins_str) #for v in mvars: # print v fvars = filter(lambda v: not (v in initial_values.keys()), mvars) for v in fvars: # print v,n if not (v in initial_values) and not (":" in v.name): print "#Warning", str(v), "is free!" setInitialConditions(ssa, initial_values, smt_conds) if (smt_conds.is_sat()): smt_conds.solve() smt_conds.write_smtlib_file("exp.smt2") smt_conds.write_sol_file("exp.sol") return Solution(smt_conds.m, fvars) else: # unsat :( return None
def getTypedValueFromCode(inss, callstack, initial_values, memory, op, debug = False): # Initialization # we reverse the code order inss.reverse() # we reset the used memory variables Memvars.reset() # we save the current callstack last_index = callstack.index # TODO: create a better interface # we set the instruction counter counter = len(inss)-1 # ssa and smt objects ssa = SSA() smt_conds = SMT() val_type = None mvars = set() if (op.isImm()): return op elif (op.isMem()): for i in range(op.size): name = op.mem_source+"@"+str(op.mem_offset+i) mvars.add(Operand(name, "BYTE", op.mem_source, op.mem_offset+i)) #print name else: # we will start tracking op mvars.add(op) # we start without free variables fvars = set() ssa.getMap(mvars, set(), set()) for ins_str in inss: #print inss.current, "->", ins_str.strip("\n") #print ins_str.strip("\n") #for v in mvars: # print v, # #print "" # pins = parse_reil(ins_str) ins = Instruction(pins, memory.getAccess(counter), mem_regs = False) ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) smt_conds.add(condition.getEq()) # simple typing new_val_type = detectType(mvars, ins, counter, callstack) # additional conditions mvars = addAditionalConditions(mvars, ins, ssa, callstack, smt_conds) val_type = max(val_type, new_val_type) # no more things to do # we update the counter counter = counter - 1 # we update the current call for next instruction callstack.prevInstruction(ins_str) if val_type == None: val_type = "imm" for v in mvars: if not (v in initial_values): print "#Warning__", str(v), "is free!" setInitialConditions(ssa, initial_values, smt_conds) smt_conds.solve(debug) if op.isReg(): op.name = op.name+"_0" elif op.isMem(): op.mem_source = op.mem_source+"_0" callstack.index = last_index # TODO: create a better interface if (debug): print val_type, op, smt_conds.getValue(op) return mkVal(val_type, smt_conds.getValue(op))
def assemble(self, i): # Parsing phase # XXX better error reporting, it should at least print the line kernel = None state = 0 # closed line = 0 # line number while True: line += 1 text = i.readline() if not text: break text = text.rstrip("\r\n") # strip comments for c in self.comment: try: text = text[:text.index(c)] except ValueError: pass # strip trailing or initial whitespace text = text.lstrip("\t ") text = text.rstrip("\t ") # skip empty lines or lines containing only comments if len(text)==0: continue if text == "{": # open block if state != 0 or kernel == None: raise CompilationError(line, "Block open in wrong context") state = 1 # block opened elif text == "}": # close block if state != 1 or kernel == None: raise CompilationError(line, "Block close in wrong context") #print kernel.instructions self.output.kernels.append(kernel) state = 0 # closed kernel = None elif text.startswith("."): # meta instruction text = text[1:] inst = text.split(" ") if inst[0] == "entry": kernel = Kernel() kernel.name = inst[1] kernel.lmem = 0 kernel.smem = 0 kernel.reg = 0 kernel.bar = 0 kernel.instructions = [] elif inst[0] in ["lmem", "smem", "reg", "bar"]: if kernel == None: raise CompilationError(line, "Kernel attribute outside kernel definition") setattr(kernel, inst[0], int(inst[1])) elif inst[0] == "constseg": # start of constant segment # N:offset name (N, offset) = inst[1].split(":") try: name = inst[2] except LookupError: name = None print N, offset, name else: raise CompilationError(line, "Invalid meta-instruction %s" % inst[0]) else: # check for label try: lend = text.index(":") except ValueError: pass else: # label label = text[0:lend] text = text[lend+1:] text = text.lstrip("\t ") ptr = len(kernel.instructions) kernel.instructions.append(Label(label)) if len(text) != 0: # normal instruction if kernel == None: raise CompilationError(line, "Instruction outside kernel definition") inst = Instruction() inst.visited = None inst.line = line try: inst.parse(text) except ValueError,e: raise CompilationError(line, e.message) kernel.instructions.append(inst)