def extract_dependency(self, opt=[ cnst.dep_raw(), cnst.dep_war(), cnst.dep_waw() ]): if cnst.dep_raw() in opt: self.extract_raw_dep() if cnst.dep_waw() in opt: self.extract_waw_dep() if cnst.dep_war in opt: self.extract_war_dep()
def analyze_bbls(self, data): def ops_ip(data): val = [] for row in data: val.append([int(row[1], 16), row[3]]) return val if len(data) > 0: bbAddr = int(data[0][1], 16) bbID = data[0][0] self.BBid2BaseAddr[bbID] = bbAddr if bbAddr not in self.BB: from PyMicroTracer.BasicBlock import BasicBlock import PyMicroTracer.Constant as cnst bb = BasicBlock(operations=ops_ip(data), machine_mode=self.machineMode, machine_arch=self.machineArch, log_handler=self.log_handler, prefix=self.prefix, log_output=self.log_output, bbl_id=bbID, bbl_base_addr=bbAddr) bb.skim_instructions() bb.extract_dependency([cnst.dep_raw()]) bb.extract_graph() bb.extract_static_ipc() bb.alive_registers() self.BB[bbAddr] = bb else: self.BB[bbAddr].called_again()
def skim_instructions(self, data): count_local = 0 idx = len(self.parsedInst) for row in reversed(data): op = row[3] pc = int(row[1], 16) bbl_id = int(row[0]) inst = Instruction(machine_mode=self.machineMode, machine_arch=self.machineArch, log_handler=self.log_handler, bll_id=bbl_id, ip=pc, op=op, log_output=self.log_output) if inst.dis_assemble() == cnst.success(): if len(inst.readRegisters) > 0 or len(inst.writeRegisters) > 0: self.parsedInst.append(inst) if bbl_id in self.bbl_instr_indx: self.bbl_instr_indx[bbl_id].add(idx) else: self.bbl_instr_indx[bbl_id] = set() self.bbl_instr_indx[bbl_id].add(idx) idx = idx + 1 count_local = count_local + 1 if self.log_output: self.log_handler.info(inst) else: if self.log_output: self.log_handler.debug("%s is useless!" % inst) else: self.log_handler.error("The instruction 0x%x can be not parsed!" % pc) return count_local
def extract_raw_dep(self): row = self.howManyParsedInst - 1 col = self.howManyParsedInst - 1 for rowInst in reversed(self.parsedInst): tmp = rowInst.readRegisters if len(tmp) > 0: for colInst in reversed(self.parsedInst): if rowInst.ip > colInst.ip: for readReg in tmp: if self.machineArch == CS_ARCH_X86: all_family = cnst.is_it_shredded_register( readReg) else: if not isinstance(readReg, type([])): all_family = [readReg] if len(all_family) > 0: for member in all_family: if member in colInst.writeRegisters: dep = Dependency( rowInst. dictionaryForRegisters[readReg], cnst.dep_raw()) arr = self.dependencyMatrix[row][col] arr.append( dep) # it acts like pointer in `C` tmp.remove(readReg) break else: if readReg in colInst.writeRegisters: dep = Dependency( rowInst. dictionaryForRegisters[readReg], cnst.dep_raw()) arr = self.dependencyMatrix[row][col] arr.append( dep) # it acts like pointer in `C` tmp.remove(readReg) col = col - 1 col = self.howManyParsedInst - 1 if len(tmp) > 0: for reg in tmp: self.readRegsAtBoarder.add(reg) row = row - 1
def extract_registers(self, inst=None, consider_pc=False): status = cnst.fail() if inst is not None: (self.readRegisters, self.writeRegisters) = inst.regs_access() self.readRegisters = set(self.readRegisters) if self.machineArch == CS_ARCH_X86: self.readRegisters = set(self.readRegisters) - { 34, 41 } # Remove IP, and RIP from registers elif self.machineArch == CS_ARCH_ARM and consider_pc: self.readRegisters = set(self.readRegisters) - { ARM_REG_PC } # Remove IP, and RIP from registers self.readRegisters = list(self.readRegisters) for reg in self.readRegisters: self.dictionaryForRegisters[reg] = inst.reg_name(reg) for reg in self.writeRegisters: self.dictionaryForRegisters[reg] = inst.reg_name(reg) self.stringOfInstruction = "<0x%x:\t%s\t%s>" % ( self.ip, inst.mnemonic, inst.op_str) if self.log_output: self.log_handler.info("-> Instruction:\t%s\t%s" % (inst.mnemonic, inst.op_str)) for reg in self.writeRegisters: self.log_handler.info("\tModified Registers:\t%s" % (inst.reg_name(reg))) for reg in self.readRegisters: self.log_handler.info("\tAccessed Registers:\t%s" % (inst.reg_name(reg))) status = cnst.success() return status
def dis_assemble(self): status = cnst.fail() try: """ Also it is possible to disassemble the whole code, but here only I get one. """ machine = Cs(self.machineArch, self.machineMode) machine.detail = True for inst in machine.disasm(bytes(bytearray.fromhex(self.op)), self.ip): if self.saveDetail: self.disAssembledInstruction = inst self.machine = machine self.extract_registers(inst) status = cnst.success() except CsError as e: self.log_handler.error("%s" % e) return status
def extract_waw_dep(self): row = self.howManyParsedInst - 1 col = self.howManyParsedInst - 1 for rowInst in reversed(self.parsedInst): tmp = rowInst.writeRegisters for colInst in reversed(self.parsedInst): if rowInst.PC > colInst.PC: for Reg in tmp: if Reg in colInst.writeRegisters: dep = Dependency( colInst.dictionaryForRegisters[Reg], cnst.dep_waw()) arr = self.dependencyMatrix[row][col] arr.append(dep) # it acts like pointer in `C` tmp.remove(Reg) col = col - 1 col = self.howManyParsedInst - 1 row = row - 1
def skim_instructions(self): for (pc, op) in self.ops: inst = Instruction(machine_mode=self.machineMode, machine_arch=self.machineArch, log_handler=self.log_handler, ip=pc, op=op, log_output=self.log_output) if inst.dis_assemble() == cnst.success(): self.parsedInst.append(inst) inst_to_string = str(inst) if self.log_output: self.log_handler.info(inst_to_string) else: if self.log_output: self.log_handler.warn( "The instruction 0x%x can be not parsed!" % pc) self.howManyParsedInst = len(self.parsedInst) self.dependencyMatrix = [[[] for j in range(self.howManyParsedInst)] for i in range(self.howManyParsedInst)]
(int("0x1045c", 16), "04202de501"), (int("0x10460", 16), "04002de501"), (int("0x10464", 16), "10c09fe5"), (int("0x10468", 16), "04c02de501"), (int("0x1046c", 16), "0c009fe5"), (int("0x10470", 16), "0c309fe5")) ''' ops = (("0x00000000004022e0", "ff3522bd2100"), ("0x00000000004022e6" , "ff2524bd2100"), ("0x0000000000402790" , "ff25d2ba2100"), ("0x0000000000402790" , "ff25d2ba2100"), ("0x0000000000402340" , "ff25fabc2100")) ''' pref = '/home/mbaharan/ArmOutput/' DUT = BasicBlock(operations=ops, machine_mode=m_m, machine_arch=m_a, bbl_id=0, log_handler=logging, prefix=pref) DUT.skim_instructions() DUT.extract_dependency([cnst.dep_raw()]) DUT.extract_graph() DUT.export_graph_as_dot(save_as_pdf=True) DUT.alive_registers() #print(DUT.dependencyMatrix) # DUT.printMatrixDependency() DUT.draw_html_table() # print("IPC: %.2f" % DUT.IPC()) print("FINISHED")
def __repr__(self): return self.dependent + " (" + cnst.dep_name( self.dependency_type) + ")"
Dependencies: """ import PyMicroTracer.Constant as cnst class Dependency(object): ''' Class name: Dependency Description: It capsulates the dependency between instructions. Date added: Dec 4, 2017-9:56:35 AM ''' def __init__(self, dependent, dependency_type): ''' Constructor ''' self.dependent = dependent self.dependency_type = dependency_type def __str__(self): return self.dependent + " (" + cnst.dep_name( self.dependency_type) + ")" def __repr__(self): return self.dependent + " (" + cnst.dep_name( self.dependency_type) + ")" if __name__ == "__main__": DUT = Dependency("rdx", cnst.dep_raw()) print(str(DUT))
def extract_raw_dep(self, data_portion=None): from capstone import CS_ARCH_X86 if data_portion is None: data_portion = [] self.log_handler.info("RAW dependency is started.") from PyMicroTracer.Dependency import Dependency row = 0 col = 0 if data_portion == -1: local_data = self.parsedInst else: local_data = data_portion total = len(data_portion) dependency_matrix = [[[] for j in range(total)] for i in range(total)] for rowInst in local_data: tmp = list(rowInst.readRegisters) if len(tmp) > 0: for colInst in local_data: if row < col: for readReg in tmp: if self.machineArch == CS_ARCH_X86: all_family = cnst.is_it_shredded_register( readReg) else: if not isinstance(readReg, type([])): all_family = [readReg] if len(all_family) > 0: for member in all_family: if member in colInst.writeRegisters: dep = Dependency( rowInst. dictionaryForRegisters[readReg], cnst.dep_raw()) arr = dependency_matrix[row][col] arr.append( dep) # it acts like pointer in `C` tmp.remove(readReg) break else: if readReg in colInst.writeRegisters: dep = Dependency( rowInst. dictionaryForRegisters[readReg], cnst.dep_raw()) arr = dependency_matrix[row][col] arr.append( dep) # it acts like pointer in `C` tmp.remove(readReg) col = col + 1 col = 0 if len(tmp) > 0: for reg in tmp: self.readRegsAtBoarder.add(reg) row = row + 1 return dependency_matrix