def main(path=None): if len(sys.argv) != 2: print "Usage: python " + sys.argv[0] + " <config.json>" print "Try with one of the JSON files from the ROP collection." return -1 if path is None: path = sys.argv[1] config = Config.from_json(path) out_dir = "output/" if not os.path.exists(out_dir): os.mkdir(out_dir) try: emu = Emulator.emu_config(config) except MemoryError as me: print me.message return -1 # emu.add_function_hook(lambda e: e.emu_stop(), address=0x401030) # from syscall_emu import virtualalloc_emu # emu.add_function_hook(virtualalloc_emu, name='VirtualAlloc') # from unicorn import UC_HOOK_MEM_VALID, UC_HOOK_CODE # from types import MethodType # def new_hook_mem(self, uc, type, address, size, value, user_data): # print 'NEW HOOOOOOOK' # def aa(self, uc, address, size, user_data): # print 'ciao' # emu.new_hook = MethodType(new_hook_mem, emu) # emu.emu.hook_add(UC_HOOK_MEM_VALID, emu.new_hook) # emu.add_unicorn_hook(UC_HOOK_MEM_VALID, new_hook_mem) # emu.add_unicorn_hook(UC_HOOK_CODE, aa) if path.endswith("CVE-2018-4990-POC.json"): from unicorn.x86_const import UC_X86_REG_EDI emu.add_pp_hook(0x64560028, 0x64145b62, lambda e: e.emu.reg_write(UC_X86_REG_EDI, 1)) emu.emu_start() emu.output.branch_handler.compute_eflags_setter() spgs = [emu.output.sequence_spg] seqs = [emu.output.gadget_sequence] def explore_branches_from(first_branch, graphs): while first_branch.bstat.get_status( ) != BranchStatus.STATUS.FULLY_EXPLORED: for fb in first_branch.bstat.get_internal_branches(): explore_branches_from(fb, graphs) if first_branch.bstat.get_status( ) == BranchStatus.STATUS.NOT_EXPLORED: # force path emu.restore_from(first_branch.flag_loading.checkpoint, first_branch.flag_loading.get_eflag_bitmask()) emu.output.branch_handler.compute_eflags_setter() graphs.append(emu.output.mm_esp_graph) spgs.append(emu.output.sequence_spg) seqs.append(emu.output.gadget_sequence) def explore_all_branches(): graphs = [emu.output.mm_esp_graph] if emu.output.branch_handler.possible_branch_gadget: explore_branches_from( emu.output.branch_handler.possible_branch_gadget.itervalues(). next(), graphs) return graphs cfgs = explore_all_branches() combination = CFG.combine_CFGs(cfgs) combination.render_graph() combination.render_empty_graph() with open(out_dir + 'MP-ip-trace.txt', 'w') as f: brand_new = [] for seq in seqs: brand_new.append([hex(a).strip('L') for a, _ in seq]) f.write(str(brand_new).replace("'", "")) with open(out_dir + 'MP-sp-trace.txt', 'w') as f: brand_new = [] for spg in spgs: brand_new.append([(hex(a).rstrip('L'), hex(b).rstrip('L')) for a, b in spg]) f.write(str(brand_new).replace("'", "")) from IPBasedCFG import IPBasedMPCFG ipCFG = IPBasedMPCFG() ipCFG.add_nodes(seqs) ipCFG.add_edges(seqs) ipCFG.render() print emu.output.called_syscall_sequence # G = emu.output.mm_esp_graph # emu.output.mm_esp_graph.render_graph() # # b = emu.output.branch_handler.possible_branch_gadget.itervalues().next() # emu.restore_from(b.flag_loading.checkpoint, b.flag_loading.get_eflag_bitmask()) # # emu.output.mm_esp_graph.render_graph() # emu.output.mm_esp_graph.combine_with(G) # emu.output.mm_esp_graph.render_graph() # dis32 = Cs(CS_ARCH_X86, CS_MODE_32) # dis32.detail = True # # def get_eflag_name(eflag): # if eflag == X86_EFLAGS_UNDEFINED_OF: # return "UNDEF_OF" # elif eflag == X86_EFLAGS_UNDEFINED_SF: # return "UNDEF_SF" # elif eflag == X86_EFLAGS_UNDEFINED_ZF: # return "UNDEF_ZF" # elif eflag == X86_EFLAGS_MODIFY_AF: # return "MOD_AF" # elif eflag == X86_EFLAGS_UNDEFINED_PF: # return "UNDEF_PF" # elif eflag == X86_EFLAGS_MODIFY_CF: # return "MOD_CF" # elif eflag == X86_EFLAGS_MODIFY_SF: # return "MOD_SF" # elif eflag == X86_EFLAGS_MODIFY_ZF: # return "MOD_ZF" # elif eflag == X86_EFLAGS_UNDEFINED_AF: # return "UNDEF_AF" # elif eflag == X86_EFLAGS_MODIFY_PF: # return "MOD_PF" # elif eflag == X86_EFLAGS_UNDEFINED_CF: # return "UNDEF_CF" # elif eflag == X86_EFLAGS_MODIFY_OF: # return "MOD_OF" # elif eflag == X86_EFLAGS_RESET_OF: # return "RESET_OF" # elif eflag == X86_EFLAGS_RESET_CF: # return "RESET_CF" # elif eflag == X86_EFLAGS_RESET_DF: # return "RESET_DF" # elif eflag == X86_EFLAGS_RESET_IF: # return "RESET_IF" # elif eflag == X86_EFLAGS_TEST_OF: # return "TEST_OF" # elif eflag == X86_EFLAGS_TEST_SF: # return "TEST_SF" # elif eflag == X86_EFLAGS_TEST_ZF: # return "TEST_ZF" # elif eflag == X86_EFLAGS_TEST_PF: # return "TEST_PF" # elif eflag == X86_EFLAGS_TEST_CF: # return "TEST_CF" # elif eflag == X86_EFLAGS_RESET_SF: # return "RESET_SF" # elif eflag == X86_EFLAGS_RESET_AF: # return "RESET_AF" # elif eflag == X86_EFLAGS_RESET_TF: # return "RESET_TF" # elif eflag == X86_EFLAGS_RESET_NT: # return "RESET_NT" # elif eflag == X86_EFLAGS_PRIOR_OF: # return "PRIOR_OF" # elif eflag == X86_EFLAGS_PRIOR_SF: # return "PRIOR_SF" # elif eflag == X86_EFLAGS_PRIOR_ZF: # return "PRIOR_ZF" # elif eflag == X86_EFLAGS_PRIOR_AF: # return "PRIOR_AF" # elif eflag == X86_EFLAGS_PRIOR_PF: # return "PRIOR_PF" # elif eflag == X86_EFLAGS_PRIOR_CF: # return "PRIOR_CF" # elif eflag == X86_EFLAGS_PRIOR_TF: # return "PRIOR_TF" # elif eflag == X86_EFLAGS_PRIOR_IF: # return "PRIOR_IF" # elif eflag == X86_EFLAGS_PRIOR_DF: # return "PRIOR_DF" # elif eflag == X86_EFLAGS_TEST_NT: # return "TEST_NT" # elif eflag == X86_EFLAGS_TEST_DF: # return "TEST_DF" # elif eflag == X86_EFLAGS_RESET_PF: # return "RESET_PF" # elif eflag == X86_EFLAGS_PRIOR_NT: # return "PRIOR_NT" # elif eflag == X86_EFLAGS_MODIFY_TF: # return "MOD_TF" # elif eflag == X86_EFLAGS_MODIFY_IF: # return "MOD_IF" # elif eflag == X86_EFLAGS_MODIFY_DF: # return "MOD_DF" # elif eflag == X86_EFLAGS_MODIFY_NT: # return "MOD_NT" # elif eflag == X86_EFLAGS_MODIFY_RF: # return "MOD_RF" # elif eflag == X86_EFLAGS_SET_CF: # return "SET_CF" # elif eflag == X86_EFLAGS_SET_DF: # return "SET_DF" # elif eflag == X86_EFLAGS_SET_IF: # return "SET_IF" # else: # return None # # def get_up_flags(eflags): # updated_flags = [] # for i in range(0, 46): # if eflags & (1 << i): # updated_flags.append(get_eflag_name(1 << i)) # print("\tEFLAGS: %s" % (','.join(p for p in updated_flags))) # # # For every gadget that had used an eflag related instruction there are possible multiple traces if that gadget is # # used in multiple branching instructions # flag_insn = False # infos = [] # eflags_g_uses = {} # for fl, traces in emu.branch_handler.traces.items(): # for trace in traces: # if fl.g_addr in eflags_g_uses: # eflags_g_uses[fl.g_addr] += 1 # else: # eflags_g_uses[fl.g_addr] = 1 # for g_addr in trace: # if flag_insn: # flag_insn = False # break # gadget_bytes = emu.gadget_map[g_addr].rop_bytes # for insn in dis32.disasm(gadget_bytes, g_addr): # if insn.eflags: # infos.append((g_addr, insn.address, insn.eflags)) # fl.eflag_bitmask = insn.eflags # flag_insn = True # break # # print "BRANCH INFOS:\n" # # print "Flags set up:\n" # for g_addr, insn_addr, eflags in infos: # print emu.gadget_map[g_addr] # get_up_flags(eflags) # print # # print 'Eflags loading gadgets:\n' # for g_addr, uses in eflags_g_uses.items(): # print 'Used {} times'.format(uses) # print emu.gadget_map[g_addr] print "Branching actions:" for sp, g_addr in emu.output.branch_handler.possible_branch_gadget.keys(): print '\nGADGET:' print 'sp value: 0x{:x}'.format(sp) print emu.output.gadget_map[g_addr] print 'STATUS DEBUG {}'.format( emu.output.branch_handler.possible_branch_gadget[ sp, g_addr].bstat.get_status()) print 'INTERNAL BRANCH STATUSES: ' for branch in emu.output.branch_handler.possible_branch_gadget[ sp, g_addr].bstat.get_internal_branches(): print '0x{:x}, {}'.format(branch.bstat.sp, branch.bstat.get_status()) tg_map = barf_classify(emu.output.gadget_map, True) print tg_map return 0