class ReplaceMovHigh(PatternMatchingRule): PATTERN = AstNode(m_mov, AstConstant('c_0')) REPLACEMENT_PATTERN = AstNode( m_or, AstConstant("new_c_0"), AstNode(m_and, AstLeaf("new_reg"), AstConstant("mask"))) def check_candidate(self, candidate): # IDA does not do constant propagation for pattern such as: # mov #0x65A4.2, r6.2 # mov #0x210F.2, r6^2.2 # jz r0.4, r6.4 # Thus, we try to detect mov to r6^2 and replace by (or #0x210F0000.4, r6.4 & 0x0000ffff.4, r6.4 # By doing that, IDA constant propagation will work again. if candidate.dst_mop.t != mop_r: return False dst_reg_name = format_mop_t(candidate.dst_mop) if dst_reg_name is None: return False if "^2" in dst_reg_name: if candidate["c_0"].mop.size != 2: return False candidate.add_constant_leaf("new_c_0", candidate["c_0"].value << 16, 4) candidate.add_constant_leaf("mask", 0xffff, 4) new_dst_reg = mop_t() new_dst_reg.make_reg(candidate.dst_mop.r - 2, 4) candidate.add_leaf("new_reg", new_dst_reg) candidate.dst_mop = new_dst_reg return True else: return False
class Xor_MbaRule_3(PatternMatchingRule): PATTERN = AstNode( m_sub, AstLeaf('x_0'), AstNode(m_mul, AstConstant('2', 2), AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1')))) REPLACEMENT_PATTERN = AstNode( m_sub, AstNode(m_xor, AstLeaf("x_0"), AstLeaf("x_1")), AstLeaf("x_1"))
class SetGlobalVariablesToZero(EarlyRule): DESCRIPTION = "This rule can be used to patch memory read" PATTERN = AstNode(m_mov, AstLeaf("ro_dword")) REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_res")) def __init__(self): super().__init__() self.ro_dword_min_ea = None self.ro_dword_max_ea = None def configure(self, kwargs): super().configure(kwargs) self.ro_dword_min_ea = None self.ro_dword_max_ea = None if "ro_dword_min_ea" in kwargs.keys(): self.ro_dword_min_ea = int(kwargs["ro_dword_min_ea"], 16) if "ro_dword_max_ea" in kwargs.keys(): self.ro_dword_max_ea = int(kwargs["ro_dword_max_ea"], 16) def check_candidate(self, candidate): if (self.ro_dword_min_ea is None) or (self.ro_dword_max_ea is None): return False if candidate["ro_dword"].mop.t != mop_v: return False mem_read_address = candidate["ro_dword"].mop.g if not(self.ro_dword_min_ea <= mem_read_address <= self.ro_dword_max_ea): return False candidate.add_constant_leaf("val_res", 0, candidate["ro_dword"].mop.size) return True
class Xor_HackersDelightRule_3(PatternMatchingRule): PATTERN = AstNode( m_sub, AstNode(m_add, AstLeaf("x_0"), AstLeaf("x_1")), AstNode(m_mul, AstConstant("2", 2), AstNode(m_and, AstLeaf("x_0"), AstLeaf("x_1")))) REPLACEMENT_PATTERN = AstNode(m_xor, AstLeaf("x_0"), AstLeaf("x_1"))
class Add_HackersDelightRule_1(PatternMatchingRule): PATTERN = AstNode(m_sub, AstLeaf("x_0"), AstNode(m_sub, AstNode(m_bnot, AstLeaf("x_1")), AstConstant("1", 1))) REPLACEMENT_PATTERN = AstNode(m_add, AstLeaf("x_0"), AstLeaf("x_1"))
class Bnot_FactorRule_1(PatternMatchingRule): PATTERN = AstNode(m_xor, AstNode(m_bnot, AstNode(m_xor, AstLeaf("x_0"), AstLeaf("x_1"))), AstLeaf("x_1")) REPLACEMENT_PATTERN = AstNode(m_bnot, AstLeaf("x_0"))
class And_FactorRule_2(PatternMatchingRule): PATTERN = AstNode(m_and, AstLeaf('x_0'), AstNode(m_bnot, AstNode(m_xor, AstLeaf('x_0'), AstLeaf('x_1')))) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1'))
class Bnot_MbaRule_1(PatternMatchingRule): PATTERN = AstNode(m_sub, AstNode(m_sub, AstLeaf("x_0"), AstConstant("1", 1)), AstNode(m_mul, AstConstant("2", 2), AstLeaf("x_0"))) REPLACEMENT_PATTERN = AstNode(m_bnot, AstLeaf("x_0"))
class Bnot_HackersDelightRule_2(PatternMatchingRule): PATTERN = AstNode(m_or, AstNode(m_bnot, AstNode(m_or, AstLeaf("x_0"), AstLeaf("x_1"))), AstNode(m_bnot, AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode(m_bnot, AstLeaf("x_1"))
class And_HackersDelightRule_1(PatternMatchingRule): PATTERN = AstNode(m_sub, AstNode(m_or, AstNode(m_bnot, AstLeaf("x_0")), AstLeaf("x_1")), AstNode(m_bnot, AstLeaf("x_0"))) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf("x_0"), AstLeaf("x_1"))
class And_HackersDelightRule_4(PatternMatchingRule): PATTERN = AstNode(m_sub, AstNode(m_or, AstLeaf('x_0'), AstLeaf('x_1')), AstNode(m_xor, AstLeaf('x_0'), AstLeaf('x_1'))) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1'))
class Add_HackersDelightRule_3(PatternMatchingRule): PATTERN = AstNode(m_add, AstNode(m_or, AstLeaf("x_0"), AstLeaf("x_1")), AstNode(m_and, AstLeaf("x_0"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode(m_add, AstLeaf("x_0"), AstLeaf("x_1"))
class GetIdentRule1(PatternMatchingRule): PATTERN = AstNode(m_add, AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1')), AstNode(m_and, AstLeaf('x_0'), AstLeaf('bnot_x_1'))) REPLACEMENT_PATTERN = AstNode(m_mov, AstLeaf("x_0")) def check_candidate(self, candidate): if not equal_bnot_mop(candidate["x_1"].mop, candidate["bnot_x_1"].mop): return False return True
class Or_HackersDelightRule_1(PatternMatchingRule): PATTERN = AstNode(m_add, AstNode(m_and, AstLeaf("x_0"), AstLeaf("bnot_x_1")), AstLeaf("x_1")) REPLACEMENT_PATTERN = AstNode(m_or, AstLeaf("x_0"), AstLeaf("x_1")) def check_candidate(self, candidate): if not equal_bnot_mop(candidate["x_1"].mop, candidate["bnot_x_1"].mop): return False return True
class Xor1_MbaRule_1(PatternMatchingRule): PATTERN = AstNode( m_add, AstNode(m_bnot, AstLeaf('x_0')), AstNode(m_or, AstNode(m_mul, AstConstant('2', 2), AstLeaf('x_0')), AstConstant('2', 2))) REPLACEMENT_PATTERN = AstNode(m_xor, AstLeaf('x_0'), AstConstant("val_1")) def check_candidate(self, candidate): candidate.add_constant_leaf("val_1", 1, candidate.size) return True
class OrBnot_FactorRule_3(PatternMatchingRule): PATTERN = AstNode(m_add, AstNode(m_sub, AstLeaf("x_0"), AstLeaf("x_1")), AstNode(m_or, AstLeaf("bnot_x_0"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode(m_or, AstLeaf("x_0"), AstNode(m_bnot, AstLeaf("x_1"))) def check_candidate(self, candidate): if not equal_bnot_mop(candidate["x_0"].mop, candidate["bnot_x_0"].mop): return False return True
class And_OllvmRule_1(PatternMatchingRule): PATTERN = AstNode(m_and, AstNode(m_or, AstLeaf('x_0'), AstLeaf('x_1')), AstNode(m_bnot, AstNode(m_xor, AstLeaf('x_0'), AstLeaf('x_1')))) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1'))
class And_FactorRule_1(PatternMatchingRule): PATTERN = AstNode(m_and, AstNode(m_xor, AstLeaf("x_0"), AstLeaf("bnot_x_1")), AstLeaf("x_1")) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf("x_0"), AstLeaf("x_1")) def check_candidate(self, candidate): return equal_bnot_mop(candidate["x_1"].mop, candidate["bnot_x_1"].mop)
class WeirdRule1(PatternMatchingRule): PATTERN = AstNode(m_sub, AstLeaf("x_0"), AstNode(m_or, AstLeaf("x_0"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode( m_add, AstNode(m_or, AstLeaf("x_0"), AstNode(m_bnot, AstLeaf("x_1"))), AstConstant("val_1")) def check_candidate(self, candidate): candidate.add_constant_leaf("val_1", 1, candidate.size) return True
def get_ast_variations_with_add_sub(opcode, left, right): possible_ast = [AstNode(opcode, left, right)] if opcode == m_add: if isinstance(left, AstNode) and isinstance(right, AstNode): if (left.opcode == m_neg) and (right.opcode == m_neg): possible_ast.append( AstNode(m_neg, AstNode(m_add, left.left, right.left))) if isinstance(right, AstNode) and (right.opcode == m_neg): possible_ast.append(AstNode(m_sub, left, right.left)) return possible_ast
class CstSimplificationRule15(PatternMatchingRule): PATTERN = AstNode(m_shr, AstNode(m_shr, AstLeaf("x_0"), AstConstant("c_1")), AstConstant("c_2")) REPLACEMENT_PATTERN = AstNode(m_shr, AstLeaf("x_0"), AstConstant("c_res")) def check_candidate(self, candidate): candidate.add_constant_leaf( "c_res", candidate["c_1"].value + candidate["c_2"].value, candidate["c_1"].size) return True
class Bnot_FactorRule_2(PatternMatchingRule): PATTERN = AstNode(m_sub, AstConstant("minus_1"), AstLeaf("x_0")) REPLACEMENT_PATTERN = AstNode(m_bnot, AstLeaf("x_0")) def check_candidate(self, candidate): if candidate["minus_1"].value != SUB_TABLE[candidate["minus_1"].size] - 1: return False return True
class CompareConstantRule2(JumpOptimizationRule): ORIGINAL_JUMP_OPCODES = [m_jge] LEFT_PATTERN = AstNode( m_or, AstNode( m_xdu, AstNode(m_and, AstNode(m_bnot, AstLeaf("x_0")), AstConstant("c_1"))), AstNode( m_and, AstNode(m_sub, AstLeaf('xdu_x_0'), AstConstant('xdu_c_1')), AstNode( m_bnot, AstNode( m_xdu, AstNode(m_xor, AstLeaf('xdu1_x_0'), AstConstant('xdu_c_1')))))) RIGHT_PATTERN = AstConstant("0", 0) REPLACEMENT_OPCODE = m_jge REPLACEMENT_LEFT_PATTERN = AstLeaf("x_0") REPLACEMENT_RIGHT_PATTERN = AstLeaf("c_1") def check_candidate(self, opcode, left_candidate, right_candidate): if not equal_mops_bypass_xdu(left_candidate["xdu_x_0"].mop, left_candidate["x_0"].mop): return False if not equal_mops_bypass_xdu(left_candidate["xdu1_x_0"].mop, left_candidate["x_0"].mop): return False self.jump_replacement_block_serial = self.jump_original_block_serial return True
class Add_OllvmRule_4(PatternMatchingRule): PATTERN = AstNode(m_sub, AstNode(m_xor, AstLeaf('x_0'), AstLeaf('x_1')), AstNode(m_mul, AstConstant("val_fe"), AstNode(m_and, AstLeaf('x_0'), AstLeaf('x_1')))) REPLACEMENT_PATTERN = AstNode(m_add, AstLeaf('x_0'), AstLeaf('x_1'))
class WeirdRule4(PatternMatchingRule): PATTERN = AstNode(m_sub, AstNode(m_and, AstLeaf("x_0"), AstLeaf("bnot_x_1")), AstNode(m_and, AstLeaf("x_0"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode( m_sub, AstNode(m_xor, AstLeaf("x_0"), AstLeaf("x_1")), AstLeaf("x_1")) def check_candidate(self, candidate): if not equal_bnot_mop(candidate["x_1"].mop, candidate["bnot_x_1"].mop): return False return True
class CstSimplificationRule4(PatternMatchingRule): PATTERN = AstNode(m_sub, AstLeaf("x_0"), AstNode(m_sub, AstConstant("c_1"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode( m_add, AstLeaf("x_0"), AstNode(m_add, AstLeaf("x_1"), AstConstant("c_res"))) def check_candidate(self, candidate): c_res = SUB_TABLE[candidate["c_1"].size] - candidate["c_1"].value candidate.add_constant_leaf("c_res", c_res, candidate["c_1"].size) return True
class CstSimplificationRule16(PatternMatchingRule): PATTERN = AstNode(m_bnot, AstNode(m_xor, AstLeaf("x_0"), AstConstant("c_1"))) REPLACEMENT_PATTERN = AstNode(m_xor, AstLeaf("x_0"), AstLeaf("bnot_c_1")) def check_candidate(self, candidate): candidate.add_constant_leaf( "bnot_c_1", candidate["c_1"].value ^ AND_TABLE[candidate["c_1"].size], candidate["c_1"].size) return True
class And1_MbaRule_1(PatternMatchingRule): PATTERN = AstNode(m_and, AstNode(m_mul, AstLeaf("x_0"), AstLeaf("x_0")), AstConstant("3", 3)) REPLACEMENT_PATTERN = AstNode(m_and, AstLeaf("x_0"), AstConstant("val_1")) def check_candidate(self, candidate): candidate.add_constant_leaf("val_1", 1, candidate.size) return True
class JbRule1(JumpOptimizationRule): ORIGINAL_JUMP_OPCODES = [m_jb] PATTERN = AstNode(m_xdu, AstNode(m_and, AstLeaf("x_0"), AstConstant("1", 1))) RIGHT_PATTERN = AstConstant("2", 2) REPLACEMENT_OPCODE = m_goto def check_candidate(self, opcode, left_candidate, right_candidate): self.jump_replacement_block_serial = self.jump_original_block_serial return True
class Sub_HackersDelightRule_4(PatternMatchingRule): PATTERN = AstNode( m_sub, AstNode(m_mul, AstConstant("2", 2), AstNode(m_and, AstLeaf("x_0"), AstLeaf("bnot_x_1"))), AstNode(m_xor, AstLeaf("x_0"), AstLeaf("x_1"))) REPLACEMENT_PATTERN = AstNode(m_sub, AstLeaf("x_0"), AstLeaf("x_1")) def check_candidate(self, candidate): if not equal_bnot_mop(candidate["x_1"].mop, candidate["bnot_x_1"].mop): return False return True