def should_blacklist(self): # This check is pretty weak. I thought I could set the minimum number to # 6, but the pattern deobfuscators might eliminate some of them before # this function gets called. if self.nseen < MIN_NUM_COMPARISONS: return True # Count the number of 1-bits in the constant values used for comparison num_bits = 0 num_ones = 0 for num in self.nums: num_bits += num.size * 8 v = num.nnn.value for i in range(num.size * 8): if v & (1 << i): num_ones += 1 # Compute the percentage of 1-bits. Given that these constants seem to be # created pseudorandomly, the percentage should be roughly 1/2. entropy = 0.0 if num_bits == 0 else num_ones / float(num_bits) hexrays_util.report_info( "%d comparisons, %d numbers, %d bits, %d ones, %f entropy" % (self.nseen, len(self.nums), num_bits, num_ones, entropy)) return entropy < 0.4 or entropy > 0.6
def apply(self, mba): # Iterate through the edges slated for removal or addition for e in self.edges: mb_src = mba.get_mblock(e.src) if e.dst1 != -1: mb_dst1 = mba.get_mblock(e.dst1) mb_src.succset._del(mb_dst1.serial) mb_dst1.predset._del(mb_src.serial) mb_dst2 = mba.get_mblock(e.dst2) mb_src.succset.push_back(mb_dst2.serial) mb_dst2.predset.push_back(mb_src.serial) hexrays_util.report_info("Replaced edge (%d->%d) by (%d->%d)\n" % ( e.src, e.dst1, e.src, e.dst2)) return len(self.edges)
def extract_jcc_parts(pred1): if is_mcode_jcond(pred1.tail.opcode): if pred1.tail.d.t != mop_b: hexrays_util.report_info("extract_jcc_parts: block was jcc, but destination was %s, not mop_b" % ( hexrays_util.mopt_t_to_string(pred1.tail.d.t))) return False, None, None, None ends_with_jcc = pred1 jcc_dest = pred1.tail.d.b # The fallthrough location is the block that's not directly targeted # by the jcc instruction. Determine that by looking at the successors. # I guess technically Hex-Rays enforces that it must be the # sequentially-next-numbered block, but oh well. jcc_fall_through = pred1.succ(1) if pred1.succ(0) == jcc_dest else pred1.succ(0) return True, ends_with_jcc, jcc_dest, jcc_fall_through return False, None, None, None
def report_info(self, msg): hexrays_util.report_info(msg)