def is_pop(self): """ @brief Tests if the VmInstruction is a 'vpop'. If True sets the PseudoInstruction """ for pos, inst in enumerate(self.Instructions): if(inst.is_add_basepointer()): break else : # no break return False pos_pmov_lst = self.get_previous(Instruction.is_read_stack, pos) if len(pos_pmov_lst) == 0: return False for ppos in pos_pmov_lst: pop_inst = self.Instructions[ppos] # get last pop_mov inst in case there are more pop_op = make_op(pop_inst, 1, self.catch_value) pos_mov_lst = self.get_subsequent(Instruction.is_mov, pos) op_pos = ppos for pos_mov in pos_mov_lst: pos_mov_inst = self.Instructions[pos_mov] if(pos_mov_inst.is_write_stack()): return False if((get_reg_class(pop_inst.get_op_str(1)) == get_reg_class(pos_mov_inst.get_op_str(2))) and get_reg_class(pop_inst.get_op_str(1))): #maybe too weak pop_op = make_op(pos_mov_inst, 1, self.catch_value) op_pos = pos_mov if(not self.Instructions[op_pos].op_is_mem(1)): return False add_value = self.Instructions[pos].get_op_value(2) self.Pseudocode = PseudoInstruction('vpop', self.addr, [pop_op], add_value) #print 'vpop' return True
def is_push(self): """ @brief Tests if the VmInstruction is a 'vpush'. If True sets the PseudoInstruction """ for pos, inst in enumerate(self.Instructions): if(inst.is_sub_basepointer()): break if(get_reg_class(self.catch_reg) == get_reg_class('eax') and (inst.is_cwde() or inst.is_cbw() or inst.is_cdqe())): self.is_signed = True else : # no break return False pos_pmov_lst = self.get_subsequent(Instruction.is_write_stack, pos) if len(pos_pmov_lst) != 1: return False push_inst = self.Instructions[pos_pmov_lst[0]] pos_mov_lst = self.get_previous(Instruction.is_mov, pos) push_op = make_op(push_inst, 2, self.catch_value) for pos_mov in pos_mov_lst: pos_mov_inst = self.Instructions[pos_mov] if pos_mov_inst.is_read_stack(): return False if((get_reg_class(push_inst.get_op_str(2)) == get_reg_class(pos_mov_inst.get_op_str(1))) and get_reg_class(push_inst.get_op_str(2)) != None): # too strong condition push_op = make_op(pos_mov_inst, 2, self.catch_value) sub_value = self.Instructions[pos].get_op_value(2) self.Pseudocode = PseudoInstruction('vpush', self.addr, [push_op], sub_value) return True
def replace_push_ebp(ps_lst, has_loc): """ @brief Replaces all 'push ebp' or 'push rbp' with array operands @param List of PseudoInstructions @param has_loc Indicates if there are locals in this function @return List of PseudoInstructions """ ret = [] is_ret = False for r_item in ps_lst: if r_item.inst_type == PI.RET_T: is_ret = True for pos, item in enumerate(ps_lst): if (item.inst_type == PI.PUSH_T and item.op_lst[0].type == PI.REGISTER_T and get_reg_class( item.op_lst[0].register) == get_reg_class('ebp')): push_pos = last_rel_push(ps_lst, pos - 1) if push_pos == None: ret.append(item) else: push_inst = ps_lst[push_pos] if (push_inst.list_len == 0 or push_inst.addr == item.addr): #need this for saving push ebp ret.append(item) continue push_inst_op = ps_lst[push_pos].op_lst[0] push_poss = scan_stack(ps_lst, pos) val_arr = [] #all pos should be push so dont need a test here for pos in push_poss: val_arr.append(ps_lst[pos].op_lst[0]) #TODO look for better possibility if is_ret: if (((is_mov_ebp(ps_lst, 0, pos)) and is_mov_ebp(ps_lst, 0, len(ps_lst) - 1)) or not has_loc): val_arr.append( PI.PseudoOperand(PI.EXP_T, 'RET_ADDR', 0)) val_arr.append(PI.PseudoOperand(PI.EXP_T, 'ARGS', 0)) else: if (((not is_mov_ebp(ps_lst, 0, pos)) and is_mov_ebp(ps_lst, 0, len(ps_lst) - 1)) or not has_loc): val_arr.append( PI.PseudoOperand(PI.EXP_T, 'RET_ADDR', 0)) val_arr.append(PI.PseudoOperand(PI.EXP_T, 'ARGS', 0)) new_op = PI.ArrayOperand(PI.ARRAY_T, ps_lst[push_poss[0]].size, len(val_arr), val_arr) new_inst = PI.PseudoInstruction(item.mnem, item.addr, [new_op], item.size, item.inst_type, item.inst_class) #new_inst.comment = comment ret.append(new_inst) else: ret.append(item) return ret
def replace_push_ebp(ps_lst, has_loc): """ @brief Replaces all 'push ebp' or 'push rbp' with array operands @param List of PseudoInstructions @param has_loc Indicates if there are locals in this function @return List of PseudoInstructions """ ret = [] is_ret = False for r_item in ps_lst: if r_item.inst_type == PI.RET_T: is_ret = True for pos, item in enumerate(ps_lst): if(item.inst_type == PI.PUSH_T and item.op_lst[0].type == PI.REGISTER_T and get_reg_class(item.op_lst[0].register) == get_reg_class('ebp')): push_pos = last_rel_push(ps_lst, pos-1) if push_pos == None: ret.append(item) else: push_inst = ps_lst[push_pos] if(push_inst.list_len == 0 or push_inst.addr == item.addr):#need this for saving push ebp ret.append(item) continue push_inst_op = ps_lst[push_pos].op_lst[0] push_poss = scan_stack(ps_lst, pos) val_arr = [] #all pos should be push so dont need a test here for pos in push_poss: val_arr.append(ps_lst[pos].op_lst[0]) #TODO look for better possibility if is_ret: if (((is_mov_ebp(ps_lst, 0, pos)) and is_mov_ebp(ps_lst, 0, len(ps_lst)-1)) or not has_loc): val_arr.append(PI.PseudoOperand(PI.EXP_T, 'RET_ADDR', 0)) val_arr.append(PI.PseudoOperand(PI.EXP_T, 'ARGS', 0)) else: if (((not is_mov_ebp(ps_lst, 0, pos)) and is_mov_ebp(ps_lst, 0, len(ps_lst)-1)) or not has_loc): val_arr.append(PI.PseudoOperand(PI.EXP_T, 'RET_ADDR', 0)) val_arr.append(PI.PseudoOperand(PI.EXP_T, 'ARGS', 0)) new_op = PI.ArrayOperand( PI.ARRAY_T, ps_lst[push_poss[0]].size, len(val_arr), val_arr) new_inst = PI.PseudoInstruction( item.mnem, item.addr, [new_op], item.size, item.inst_type, item.inst_class) #new_inst.comment = comment ret.append(new_inst) else: ret.append(item) return ret
def is_nor(self): """ @brief Tests if the VmInstruction is a 'vnor'. If True sets the PseudoInstruction """ # 1. search for and with 2 different registers and_found = False reg0 = '' reg1 = '' and_size = 0 for pos, inst in enumerate(self.Instructions): if inst.is_and(): reg0 = inst.get_reg_name(1) reg1 = inst.get_reg_name(2) and_size = inst.get_mov_size() if reg0 != reg1: and_found = True break if not and_found: return False pos_not = self.get_previous(Instruction.is_not, pos) #if len(pos_not) < 1 or len(pos_not) > 2: # return False not_size = 0 for posn in pos_not: not_size += (self.Instructions[posn].Instruction.operands[0].size / 8) if(not_size != 2 * and_size): return False pos_mov = self.get_previous(Instruction.is_mov, pos) #if len(pos_mov) != 2: # return False mov_r0 = False mov_r1 = False op1 = make_op(self.Instructions[pos], 1, self.catch_value) op2 = make_op(self.Instructions[pos], 2, self.catch_value) for pos_reg0 in pos_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[pos_reg0].get_reg_name(1))): mov_r0 = True break for pos_reg1 in pos_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[pos_reg1].get_reg_name(1))): mov_r1 = True break if mov_r0: op1 = make_op(self.Instructions[pos_reg0], 2, self.catch_value) if mov_r1: op2 = make_op(self.Instructions[pos_reg1], 2, self.catch_value) #quick fix correct !!! if(op1.register == 'ebp') and (and_size == 2): op1 = op1.replace('+0x4', '+0x2') self.Pseudocode = PseudoInstruction('vnor', self.addr, [op1, op2], and_size) return True
def get_scratch_variable(self): """ @brief Replace memory operands from 'vpush' and 'vpop' with ScratchOperands """ if (self.inst_type != POP_T and self.inst_type != PUSH_T and self.list_len != 1): return op0 = self.op_lst[0] if (op0.type == MEMORY_T and get_reg_class(op0.register) == get_reg_class('edi')): self.op_lst[0] = ScratchOperand(SVARIABLE_T, op0.displacement, op0.size)
def get_reg(reg_string, reg_size): """ returns the register name to be used as key with a Traceline.ctx object :param reg_string: any string representing a reg, e.g. rax, RAX, eax, ah, al, etc. :param reg_size: size in bit of the registers in Traceline.ctx, e.g. 64, 32, 16 :return: reg_string of the ctx keys, e.g. rax """ return get_reg_by_size(get_reg_class(reg_string), reg_size)
def is_write(self): """ @brief Tests if the VmInstruction is a 'vwrite'. If True sets the PseudoInstruction """ reg0 = '' reg1 = '' mov_size = 0 sub_size = 0 for pos, inst in enumerate(self.all_instructions): if inst.op_is_mem(1) and not inst.is_write_stack(): reg0 = inst.get_reg_name(1) reg1 = inst.get_reg_name(2) mov_size = inst.get_mov_size() break else: # no break return False for subpos, inst in enumerate(self.Instructions): if(inst.is_add_basepointer()): sub_size = inst.get_op_value(2) break else : # no break return False pos_mov = self.get_previous(Instruction.is_mov, pos) mov_r0 = False mov_r1 = False for pos_reg0 in pos_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[pos_reg0].get_reg_name(1))): mov_r0 = True break for pos_reg1 in pos_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[pos_reg1].get_reg_name(1))): mov_r1 = True break if mov_r0 and mov_r1: op1_inst = self.Instructions[pos_reg0] op1 = PseudoOperand(PI.REFERENCE_T, op1_inst.get_op_str(2), op1_inst.get_op_size(2), op1_inst.get_reg_name(2)) op2 = make_op(self.Instructions[pos_reg1], 2, self.catch_value) self.Pseudocode = PseudoInstruction('vwrite', self.addr, [op1, op2], mov_size, PI.WRITE_T, PI.IN2_OUT0, sub_size) return True else: return False
def is_vcall(self): """ @brief Tests if the VmInstruction is a 'vcall'. If True sets the PseudoInstruction """ for pos, inst in enumerate(self.Instructions): if(inst.is_call()): break else : # no break return False op1 = self.Instructions[pos].get_op_str(1) prev_mov = self.get_previous(Instruction.is_mov, pos) for prev_pos in prev_mov: if (get_reg_class(self.Instructions[pos].get_reg_name(1)) == get_reg_class(self.Instructions[prev_pos].get_reg_name(1))): op1 = make_op(self.Instructions[prev_pos], 2, self.catch_value) self.Pseudocode = PseudoInstruction('vcall', self.addr, [op1]) return True
def is_mov_ebp(self): """ @brief Tests if the VmInstruction is a 'vebp_mov'. If True sets the PseudoInstruction """ op1 = '' op2 = '' for pos, inst in enumerate(self.Instructions): if(inst.is_mov() and get_reg_class(inst.get_reg_name(1)) == get_reg_class('ebp') and get_reg_class(inst.get_reg_name(2)) == get_reg_class('ebp')): op1 = make_op(inst, 1, self.catch_value) op2 = make_op(inst, 2, self.catch_value) break else : # no break return False self.Pseudocode = PseudoInstruction('vebp_mov', self.addr, [op1, op2]) return True
def PopulateModel(self): self.CleanModel() assert isinstance(self.ctx, dict) for key in self.ctx.keys(): if get_reg_class(key) is not None: node = QtGui.QStandardItem('Register %s' % key) node_brush = set() for line in self.ctx[key]: assert isinstance(line, Traceline) tid = QtGui.QStandardItem('%s' % line.thread_id) addr = QtGui.QStandardItem('%x' % line.addr) disasm = QtGui.QStandardItem(line.disasm_str()) comment = QtGui.QStandardItem(''.join( c for c in line.comment if line.comment is not None)) context = QtGui.QStandardItem(''.join( '%s:%s ' % (c, line.ctx[c]) for c in line.ctx.keys() if line.ctx is not None)) ci = 0 co = 0 for selector in self.selection[ 'upper']: # check input values if line.to_str_line().__contains__( selector) or line.to_str_line().__contains__( selector.lower()): ci = 1 for selector in self.selection[ 'lower']: # check output values if line.to_str_line().__contains__( selector) or line.to_str_line().__contains__( selector.lower()): co = 2 node_brush.add(ci + co) tid.setBackground(self.brush_map[ci + co]) addr.setBackground(self.brush_map[ci + co]) disasm.setBackground(self.brush_map[ci + co]) comment.setBackground(self.brush_map[ci + co]) context.setBackground(self.brush_map[ci + co]) node.appendRow([tid, addr, disasm, comment, context]) try: if len(node_brush) == 3: color = 3 else: color = max(node_brush) node.setBackground(self.brush_map[color]) except: pass self.sim.appendRow(node) self.treeView.resizeColumnToContents(0) self.treeView.resizeColumnToContents(1) self.treeView.resizeColumnToContents(2) self.treeView.resizeColumnToContents(3) self.treeView.resizeColumnToContents(4)
def rec_find_addr(pp_lst, pos, op, max_rec_depth): """ @brief Recursiv search for finding jmp addresses @param pp_lst List of PseudoInstructions push/pop represtentation @param pos Index of jump instruction @param op Operand of jump instruction @param max_rec_depth Maximal recursion depth @return List positions which are used to calc jump address """ if max_rec_depth == 0: return [] if (op.type == PI.IMMEDIATE_T or (op.type == PI.REGISTER_T and get_reg_class(op.register) == get_reg_class('ebp'))): return [pos] inst_pos = find_last_inst(pp_lst, pos - 1, op) if inst_pos == None or inst_pos == 0: return [] curr_inst = pp_lst[inst_pos] if curr_inst.inst_type == PI.POP_T: push_pos = last_rel_push(pp_lst, inst_pos - 1) if push_pos == None: return [] new_op = pp_lst[push_pos].op_lst[0] new_pos = push_pos return [] + rec_find_addr(pp_lst, new_pos, new_op, max_rec_depth - 1) elif (curr_inst.inst_class == PI.ASSIGNEMENT_T and curr_inst.list_len == 2): new_op = pp_lst[inst_pos].op_lst[1] new_pos = inst_pos return [] + rec_find_addr(pp_lst, new_pos, new_op, max_rec_depth - 1) elif (curr_inst.inst_class == PI.ASSIGNEMENT_T and curr_inst.list_len >= 2): new_pos = inst_pos ret_lst = [] for new_op in curr_inst.op_lst[1:]: ret_lst += rec_find_addr(pp_lst, new_pos, new_op, max_rec_depth - 1) return ret_lst else: return []
def rec_find_addr(pp_lst, pos, op, max_rec_depth): """ @brief Recursiv search for finding jmp addresses @param pp_lst List of PseudoInstructions push/pop represtentation @param pos Index of jump instruction @param op Operand of jump instruction @param max_rec_depth Maximal recursion depth @return List positions which are used to calc jump address """ if max_rec_depth == 0: return [] if(op.type == PI.IMMEDIATE_T or (op.type == PI.REGISTER_T and get_reg_class(op.register) == get_reg_class('ebp'))): return [pos] inst_pos = find_last_inst(pp_lst, pos - 1, op) if inst_pos == None or inst_pos == 0: return [] curr_inst = pp_lst[inst_pos] if curr_inst.inst_type == PI.POP_T: push_pos = last_rel_push(pp_lst, inst_pos - 1) if push_pos == None: return [] new_op = pp_lst[push_pos].op_lst[0] new_pos = push_pos return [] + rec_find_addr(pp_lst, new_pos, new_op, max_rec_depth-1) elif (curr_inst.inst_class == PI.ASSIGNEMENT_T and curr_inst.list_len == 2): new_op = pp_lst[inst_pos].op_lst[1] new_pos = inst_pos return [] + rec_find_addr(pp_lst, new_pos, new_op, max_rec_depth-1) elif (curr_inst.inst_class == PI.ASSIGNEMENT_T and curr_inst.list_len >= 2): new_pos = inst_pos ret_lst = [] for new_op in curr_inst.op_lst[1:]: ret_lst += rec_find_addr(pp_lst, new_pos , new_op, max_rec_depth-1) return ret_lst else: return []
def is_read(self): """ @brief Tests if the VmInstruction is a 'vread'. If True sets the PseudoInstruction """ reg0 = '' reg1 = '' mov_size = 0 for pos, inst in enumerate(self.all_instructions): if inst.op_is_mem(2) and not inst.is_read_stack(): reg0 = inst.get_reg_name(1) reg1 = inst.get_reg_name(2) mov_size = inst.get_mov_size() break else: # no break return False prev_mov = self.get_previous(Instruction.is_mov, pos) post_mov = self.get_subsequent(Instruction.is_mov, pos) for prev_pos in prev_mov: if(get_reg_class(reg1) == get_reg_class(self.Instructions[prev_pos].get_reg_name(1))): break else: # no break return False for post_pos in post_mov: if(get_reg_class(reg0) == get_reg_class(self.Instructions[post_pos].get_reg_name(2))): push_size = self.Instructions[post_pos].get_mov_size() break else: # no break return False # wta = write to address #if mov_size == 1: op1 = make_op(self.Instructions[post_pos], 1, self.catch_value) op2_inst = self.Instructions[prev_pos] op2 = PseudoOperand(PI.REFERENCE_T, op2_inst.get_op_str(2), op2_inst.get_op_size(2), op2_inst.get_reg_name(2)) self.Pseudocode = PseudoInstruction('vread', self.addr, [op1, op2], mov_size, PI.READ_T, PI.IN1_OUT1 , push_size) return True
def is_imul(self): """ @brief Tests if the VmInstruction is a 'vimul'. If True sets the PseudoInstruction """ reg0 = '' reg1 = '' mul_found = False for pos, inst in enumerate(self.Instructions): if (inst.is_imul() and inst.op_is_reg(1)): reg0 = inst.get_reg_name(1) if inst.get_reg_name(2) == None: reg1 = get_reg_by_size(get_reg_class('eax'), SV.dissassm_type) else: reg1 = inst.get_reg_name(2) if reg0 != reg1: mul_found = True break if not mul_found: return False pos_mov = self.get_previous(Instruction.is_mov, pos) for pos_reg0 in pos_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[pos_reg0].get_reg_name(1))): mov_r0 = True break for pos_reg1 in pos_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[pos_reg1].get_reg_name(1))): mov_r1 = True break if mov_r0 and mov_r1: self.Pseudocode = PseudoInstruction('vimul', self.addr, [make_op(self.Instructions[pos_reg0], 2, self.catch_value), make_op(self.Instructions[pos_reg1], 2, self.catch_value)], SV.dissassm_type / 8, PI.IMUL_T, PI.IN2_OUT3) return True else: return False
def return_push_ebp(ps_lst): """ @brief Replace all array operands, which are not part of an assignement, with 'push ebp' or 'push rbp' @param ps_lst List of PseudoInstructions @remark Just do this after 'replace_push_ebp' and 'reduce_assignements' """ for inst in ps_lst: if (inst.inst_type == PI.PUSH_T and inst.op_lst[0].type == PI.ARRAY_T): reg_class = get_reg_class('ebp') register = get_reg_by_size(reg_class, SV.dissassm_type) ebp_op = PI.PseudoOperand(PI.REGISTER_T, register, SV.dissassm_type, register) inst.op_lst[0] = ebp_op
def get_catch_reg(reg, length): """ @brief Determines the right catch register for further usage @param reg Register from x86 code @param length Move size of catch instruction in bytes @return Register with right size or empty string """ reg_class = get_reg_class(reg) if reg_class == None: return '' catch_reg = get_reg_by_size(reg_class, length * 8) if catch_reg == None: catch_reg = '' return catch_reg
def PopulateModel(self): self.CleanModel() assert isinstance(self.ctx, dict) for key in self.ctx.keys(): if get_reg_class(key) is not None: node = QtGui.QStandardItem('Register %s' % key) node_brush = set() for line in self.ctx[key]: assert isinstance(line, Traceline) tid = QtGui.QStandardItem('%s' % line.thread_id) addr = QtGui.QStandardItem('%x' % line.addr) disasm = QtGui.QStandardItem(line.disasm_str()) comment = QtGui.QStandardItem(''.join(c for c in line.comment if line.comment is not None)) context = QtGui.QStandardItem(''.join('%s:%s ' % (c, line.ctx[c]) for c in line.ctx.keys() if line.ctx is not None)) ci = 0 co = 0 for selector in self.selection['upper']: # check input values if line.to_str_line().__contains__(selector) or line.to_str_line().__contains__(selector.lower()): ci = 1 for selector in self.selection['lower']: # check output values if line.to_str_line().__contains__(selector) or line.to_str_line().__contains__(selector.lower()): co = 2 node_brush.add(ci+co) tid.setBackground(self.brush_map[ci+co]) addr.setBackground(self.brush_map[ci+co]) disasm.setBackground(self.brush_map[ci+co]) comment.setBackground(self.brush_map[ci+co]) context.setBackground(self.brush_map[ci+co]) node.appendRow([tid, addr, disasm, comment, context]) try: if len(node_brush) == 3: color = 3 else: color = max(node_brush) node.setBackground(self.brush_map[color]) except: pass self.sim.appendRow(node) self.treeView.resizeColumnToContents(0) self.treeView.resizeColumnToContents(1) self.treeView.resizeColumnToContents(2) self.treeView.resizeColumnToContents(3) self.treeView.resizeColumnToContents(4)
def replace_reg_class(self, rreg, catch_value): """ @brief Replace register of evrey op with catch_value if it is in the same register class as rreg @param rreg Register to replace @param catch_value Value that replaces the register """ reg_class = get_reg_class(rreg) for reg in reversed(get_reg_class_lst(reg_class)): for op in self.op_lst: if op.type == REGISTER_T and op.register == reg: op.type = IMMEDIATE_T op.val = catch_value op.name = op.name.replace(reg, '{0:#x}'.format(catch_value)) elif op.type == MEMORY_T and reg in op.name: op.displacement = catch_value op.name = op.name.replace(reg, '{0:#x}'.format(catch_value))
def is_shift_left(self): """ @brief Tests if the VmInstruction is a 'vshl'. If True sets the PseudoInstruction """ # 1. search for and with 2 different registers and_found = False reg0 = '' reg1 = '' for pos, inst in enumerate(self.Instructions): if inst.is_shl() and inst.op_is_reg(1) and inst.op_is_reg(2): reg0 = inst.get_reg_name(1) reg1 = inst.get_reg_name(2) if reg0 != reg1: and_found = True break if not and_found: return False pos_mov = self.get_previous(Instruction.is_mov, pos) if len(pos_mov) != 2: return False mov_r0 = False mov_r1 = False for pos_reg0 in pos_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[pos_reg0].get_reg_name(1))): mov_r0 = True break for pos_reg1 in pos_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[pos_reg1].get_reg_name(1))): mov_r1 = True break post_mov = self.get_subsequent(Instruction.is_mov, pos) for save_mov in post_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[save_mov].get_reg_name(2))): ret_size = self.Instructions[save_mov].get_mov_size() break else: # no break return False if mov_r0 and mov_r1: # TODO byte word usw... self.Pseudocode = PseudoInstruction('vshl', self.addr, [make_op(self.Instructions[pos_reg0], 2, self.catch_value), make_op(self.Instructions[pos_reg1], 2, self.catch_value)], ret_size) return True else: return False
def is_shld(self): """ @brief Tests if the VmInstruction is a 'vshld'. If True sets the PseudoInstruction """ and_found = False reg0 = '' reg1 = '' reg2 = '' for pos, inst in enumerate(self.Instructions): if (inst.is_shld() and inst.op_is_reg(1) and inst.op_is_reg(2) and inst.op_is_reg(3)): reg0 = inst.get_reg_name(1) reg1 = inst.get_reg_name(2) reg2 = inst.get_reg_name(3) if reg0 != reg1: and_found = True break if not and_found: return False prev_mov = self.get_previous(Instruction.is_mov, pos) for prev_pos0 in prev_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[prev_pos0].get_reg_name(1))): break else: # no break return False for prev_pos1 in prev_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[prev_pos1].get_reg_name(1))): break else: # no break return False for prev_pos2 in prev_mov: if (get_reg_class(reg2) == get_reg_class(self.Instructions[prev_pos2].get_reg_name(1))): break else: # no break return False self.Pseudocode = PseudoInstruction('vshld', self.addr, [make_op(self.Instructions[prev_pos0], 2, self.catch_value), make_op(self.Instructions[prev_pos1], 2, self.catch_value), make_op(self.Instructions[prev_pos2], 2, self.catch_value)]) return True
def is_idiv(self): """ @brief Tests if the VmInstruction is a 'vimul'. If True sets the PseudoInstruction """ reg0 = '' reg1 = '' op_name = '' div_found = False for pos, inst in enumerate(self.Instructions): if (inst.is_idiv()): reg0 = get_reg_by_size(get_reg_class('eax'), SV.dissassm_type) reg1 = get_reg_by_size(get_reg_class('edx'), SV.dissassm_type) op_name = inst.get_op_str(1) div_found = True if not div_found: return False pos_mov = self.get_previous(Instruction.is_mov, pos) for pos_reg0 in pos_mov: if (get_reg_class(reg0) == get_reg_class(self.Instructions[pos_reg0].get_reg_name(1))): mov_r0 = True break for pos_reg1 in pos_mov: if (get_reg_class(reg1) == get_reg_class(self.Instructions[pos_reg1].get_reg_name(1))): mov_r1 = True break if mov_r0 and mov_r1: self.Pseudocode = PseudoInstruction('vidiv', self.addr, [make_op(self.Instructions[pos_reg0], 2, self.catch_value), make_op(self.Instructions[pos_reg1], 2, self.catch_value), make_op(self.Instructions[pos], 1, self.catch_value)], SV.dissassm_type / 8, PI.DIV_T, PI.IN3_OUT3) return True else: return False
def is_op2_reg(self): try: return get_reg_class(self._line[2][2]) is not None except: return False