def get_changed_bytes(functions): """Applies all the randomizations on each function and returns the superset of the changed bytes for each technique (coverage).""" swap_b, preserv_b, equiv_b, reorder_b = set(), set(), set(), set() for f in filter(lambda x: x.level != -1, functions.itervalues()): # swap swap.liveness_analysis(f.code) live_regs = swap.get_reg_live_subsets(f.instrs, f.code, f.igraph) swap.split_reg_live_subsets(live_regs, f.code) swaps = swap.get_reg_swaps(live_regs) swap_b |= swap.do_single_swaps(swaps, gen_patched=False) # preserv preservs, avail_regs = preserv.get_reg_preservations(f) preserv_b |= preserv.do_reg_preservs(f.instrs, f.blocks, preservs, avail_regs, gen_patched=False) # equiv equiv_b |= equiv.do_equiv_instrs(f.instrs, gen_patched=False) # reorder reorder_b |= reorder.do_reordering(f.blocks, gen_patched=False) return swap_b, preserv_b, equiv_b, reorder_b
def testAll(self): funcs = inp.load_data(self.INPUT) for ea, f in funcs.iteritems(): if ea == self.FUNC: break else: self.fail("could not find MD5Update at %x" % self.FUNC) # analyze levels = func.classify_functions(funcs) func.analyze_functions(funcs, levels) # swap swap.liveness_analysis(f.code) live_regs = swap.get_reg_live_subsets(f.instrs, f.code, f.igraph) swap.split_reg_live_subsets(live_regs, f.code) swaps = swap.get_reg_swaps(live_regs) swap.do_single_swaps(swaps, gen_patched=True) # preserv preservs, avail_regs = preserv.get_reg_preservations(f) preserv.do_reg_preservs(f.instrs, f.blocks, preservs, avail_regs, gen_patched=True) # equiv equiv.do_equiv_instrs(f.instrs, gen_patched=True) # reorder reorder.do_reordering(f.blocks, gen_patched=True) # check the numner of generated files print self.assertEqual(len(glob.glob(self.GEN_FILES)), 50) for genf in glob.glob(self.GEN_FILES): output = util.run("%s %s" % (self.PROG, genf), 10) self.assertTrue(self.EXPECT in output, "%s: %s %s" % (genf, self.EXPECT, output)) # remove the generated files map(os.remove, glob.glob(self.GEN_FILES))
def randomize(input_file): # get the changed byte sets functions = inp.get_functions(input_file) levels = func.classify_functions(functions) func.analyze_functions(functions, levels) global_diffs = [] changeable = 0 for f in filter(lambda x: x.level != -1, functions.itervalues()): # skip the SEH prolog and epilog functions .. they cause trouble if "_SEH_" in f.name: continue diffs = [] # swap (register reassignment with CFG): RUNTIME ERROR # This application has requested the Runtime to terminate it in an unsusal way. # Please Contact the application's support team for more information swap.liveness_analysis(f.code) live_regs = swap.get_reg_live_subsets(f.instrs, f.code, f.igraph) swaps = swap.get_reg_swaps(live_regs) swap.do_single_swaps(swaps, False, diffs) # preserv (reordering of register preservation): ERROR preservs, avail_regs = preserv.get_reg_preservations(f) preserv.do_reg_preservs(f.instrs, f.blocks, preservs, avail_regs, False, diffs) # equiv (automic instruction substitution): GOOD equiv.do_equiv_instrs(f.instrs, False, diffs) # reorder (intra basic block reordering): GOOD reorder.do_reordering(f.blocks, False, diffs) if diffs: changeable += len(list(itertools.chain(*diffs))) global_diffs.extend(random.choice(diffs)) inp.patch(global_diffs, "rand", False) print "changed %d bytes of at least %d changeable" % (len(global_diffs), changeable) print "(not counting all possible reorderings and preservations)"
def testExecuteEquiv(self): GEN_FILE = TEST + "testlib/testlib_patched-equiv.dll" changed_bytes = equiv.do_equiv_instrs(self.f.instrs, gen_patched=True) # check the number of changed bytes self.assertEqual(len(changed_bytes), 13) # check the numner of generated files self.assertEqual(len(glob.glob(GEN_FILE)), 1) output = util.run("%s %s" % (self.PROG, GEN_FILE), 10) # check the output of the generated files self.assertTrue(self.EXPECT in output, "%s: %s %s" % (GEN_FILE, self.EXPECT, output)) # remove the generated files map(os.remove, glob.glob(GEN_FILE))