def TstBarf(file_path): barf = BARF(file_path) # Recover CFG. sys.stdout.write("dir=%s\n"%str(dir(barf))) cfg = barf.recover_cfg() basna = os.path.basename(file_path) # Save CFG to a .dot file. cfg.save(basna)
def De_IS(filename, start): # sys.argv = ["test.py", "/Users/mark/Desktop/de_obfuscator/IS/New-test/total/inssub", "0x694"] # if len(sys.argv) != 3: # print 'Usage: python DeInsSub.py filename function_address(hex)' # exit(0) # filename = sys.argv[1] start = int(start, 16) filename = filename # start = int(start, 16) barf = BARF(filename) base_addr = barf.binary.entry_point >> 12 << 12 cfg = barf.recover_cfg(start) blocks = cfg.basic_blocks print('The function has %d blocks. ' % len(blocks)) origin = open(filename, 'rb') data = list(origin.read()) for block in blocks: opposite = [] #查找所用的MOV指令,然后记录所用寄存器值相反的对 # for ins in block.instrs: # if ins.mnemonic_full.startswith(u'mvn'): # if ins.operands[0].name not in opposite: # opposite[ins.operands[0].name] = ins.operands[1].name block_size = len(block.instrs) ADDHex, ADDnop = check_add(block, block_size) data = fix_substitution(data, ADDHex, ADDnop, base_addr) SUBHex, SUBnop = check_sub(block, block_size) data = fix_substitution(data, SUBHex, SUBnop, base_addr) XORHex, XORnop = check_xor(block, block_size) data = fix_substitution(data, XORHex, XORnop, base_addr) ANDHex, ANDnop = check_and(block, block_size) data = fix_substitution(data, ANDHex, ANDnop, base_addr) ORHex, ORnop = check_or(block, block_size) data = fix_substitution(data, ORHex, ORnop, base_addr) origin.close() # recovery = open(filename + '_recovered', 'wb') path = sys.argv[3] if not os.path.exists(path + filename.split('/')[-2] + '/'): os.mkdir(path + filename.split('/')[-2] + '/') recovery = open( path + filename.split('/')[-2] + '/' + filename.split('/')[-1] + '_recovered', 'wb') recovery.write(''.join(data)) recovery.close() print 'Successful! The recovered file: %s' % (filename + '_recovered')
# 8048401: 75 19 jne 804841c <main+0x2f> # 8048403: 81 7d f8 48 47 46 45 cmp DWORD PTR [ebp-0x8],0x45464748 # 804840a: 75 10 jne 804841c <main+0x2f> # 804840c: 81 7d fc ef cd ab 00 cmp DWORD PTR [ebp-0x4],0xabcdef # 8048413: 75 07 jne 804841c <main+0x2f> # 8048415: c7 45 f0 00 00 00 00 mov DWORD PTR [ebp-0x10],0x0 # 804841c: 8b 45 f0 mov eax,DWORD PTR [ebp-0x10] # 804841f: c9 leave # 8048420: c3 ret start_addr = 0x80483ed end_addr = 0x8048420 print("[+] Recovering function CFG...") cfg = barf.recover_cfg(start_addr, end_addr) print("[+] Checking path satisfiability...") # Preconditions: set stack # Note: this isn't strictly necessary but it helps reduce the time it # takes the solver find a solution. esp = barf.code_analyzer.get_register_expr("esp", mode="pre") barf.code_analyzer.add_constraint(esp == 0xffffceec) # Traverse paths and check satisfiability for bb_path in cfg.all_simple_bb_paths(start_addr, end_addr): print("[+] Path: {0}".format(" -> ".join( [hex(bb.address) for bb in bb_path])))
def De_BCF(filename, start): # sys.argv = ["test.py", '/Users/mark/Desktop/de_obfuscator/benchmark/binary/pyramid-bcf-sub', "0x72c"] # start = int(sys.argv[2], 16) start = int(start, 16) # filename = sys.argv[1] filename = filename barf = BARF(filename) base_addr = barf.binary.entry_point >> 12 << 12 cfg = barf.recover_cfg(start) cmp_blocks, opaque_predicate_blocks = get_predicate_blocks(cfg) print(cmp_blocks) print(opaque_predicate_blocks) blocks = cfg.basic_blocks fixhex = [] fixaddr = [] # for each block for block in blocks: command = '' # compare blocks(0 for beq(taken), 1 for bne(not-taken)) if hex(block.address) in cmp_blocks: if cmp_blocks[hex(block.address)] == 0: for branch in block.branches: if branch[1] == 'taken': off_set = hex(branch[0] - block.instrs[-1].address) command = 'b #' + off_set elif cmp_blocks[hex(block.address)] == 1: for branch in block.branches: if branch[1] == 'not-taken': off_set = hex(branch[0] - block.instrs[-1].address) command = 'b #' + off_set # opaque predicate blocks(0 for beq(taken), 1,2 for bne(not-taken)) if hex(block.address) in opaque_predicate_blocks: if opaque_predicate_blocks[hex(block.address)] == 0: for branch in block.branches: if branch[1] == 'taken': off_set = hex(branch[0] - block.instrs[-1].address) command = 'b #' + off_set elif opaque_predicate_blocks[hex(block.address)] == 1 or \ opaque_predicate_blocks[hex(block.address)] == 2: for branch in block.branches: if branch[1] == 'not-taken': off_set = hex(branch[0] - block.instrs[-1].address) command = 'b #' + off_set # change the conditional jump before opaque_predicate_blocks to unconditional jump # (force the flow through opaque_predicate_blocks) for branch in block.branches: if hex(branch[0]) in opaque_predicate_blocks and block.instrs[ -1].mnemonic_full == u'blt': off_set = hex(branch[0] - block.instrs[-1].address) command = 'b #' + off_set # if command.startswith('b'): # print command if command != '': bcommand = bytes(command) hexcommand = '' try: # Initialize engine in X86-32bit mode ks = Ks(KS_ARCH_ARM, KS_MODE_LITTLE_ENDIAN) encoding, count = ks.asm(bcommand) for i in encoding: hexcommand = hexcommand + hex(int(i)) + ',' fixaddr.append(block.instrs[-1].address) fixhex.append(hexcommand) except KsError as e: print("ERROR: %s" % e) # elif command.startswith('negative,'): # hexcommand = '' # off_set = command.split(',')[-1] # x = int(off_set, 16) - 8 # x &= 0x3FFFFFF # x >>= 2 # tmp = hex(0xEB000000 + x) # for i in range(len(tmp), 2, -2): # hexcommand = hexcommand + '0x' + tmp[i-2:i] + ',' # fixaddr.append(block.instrs[-1].address) # fixhex.append(hexcommand) origin = open(filename, 'rb') data = list(origin.read()) print fixaddr, fixhex data = fix_instruction_substitution(data, fixhex, fixaddr, base_addr) origin.close() path = sys.argv[3] recovery = open( path + filename.split('/')[-2] + '/' + filename.split('/')[-1] + '_recovered', 'wb') recovery.write(''.join(data)) recovery.close() print 'Successful! The recovered file: %s' % (filename + '_recovered')
# 8048403: 81 7d f8 48 47 46 45 cmp DWORD PTR [ebp-0x8],0x45464748 # 804840a: 75 10 jne 804841c <main+0x2f> # 804840c: 81 7d fc ef cd ab 00 cmp DWORD PTR [ebp-0x4],0xabcdef # 8048413: 75 07 jne 804841c <main+0x2f> # 8048415: c7 45 f0 00 00 00 00 mov DWORD PTR [ebp-0x10],0x0 # 804841c: 8b 45 f0 mov eax,DWORD PTR [ebp-0x10] # 804841f: c9 leave # 8048420: c3 ret start_addr = 0x80483ed end_addr = 0x8048420 # Recover control flow graph print("[+] Recovering function CFG...") cfg = barf.recover_cfg(start_addr, end_addr) # Set stack esp = barf.code_analyzer.get_register_expr("esp") barf.code_analyzer.set_precondition(esp == 0xffffceec) # Traverse paths and check satisfiability print("Checking path satisfiability...") for bb_path in cfg.all_simple_bb_paths(start_addr, end_addr): path_addrs = [hex(bb.address) for bb in bb_path] print("[+] Path : {0}".format(" -> ".join(path_addrs))) is_sat = barf.code_analyzer.check_path_satisfiability(bb_path, start_addr)
data[start + i] = jmp_offset[i] if __name__ == '__main__': if len(sys.argv) != 3: print 'Usage: python deflat.py filename function_address(hex)' exit(0) opcode = {'a':'\x87', 'ae': '\x83', 'b':'\x82', 'be':'\x86', 'c':'\x82', 'e':'\x84', 'z':'\x84', 'g':'\x8F', 'ge':'\x8D', 'l':'\x8C', 'le':'\x8E', 'na':'\x86', 'nae':'\x82', 'nb':'\x83', 'nbe':'\x87', 'nc':'\x83', 'ne':'\x85', 'ng':'\x8E', 'nge':'\x8C', 'nl':'\x8D', 'nle':'\x8F', 'no':'\x81', 'np':'\x8B', 'ns':'\x89', 'nz':'\x85', 'o':'\x80', 'p':'\x8A', 'pe':'\x8A', 'po':'\x8B', 's':'\x88', 'nop':'\x90', 'jmp':'\xE9', 'j':'\x0F'} filename = sys.argv[1] start = int(sys.argv[2], 16) barf = BARF(filename) base_addr = barf.binary.entry_point >> 12 << 12 b = angr.Project(filename, load_options={'auto_load_libs': False, 'main_opts':{'custom_base_addr': 0}}) cfg = barf.recover_cfg(start=start) blocks = cfg.basic_blocks prologue = start main_dispatcher = cfg.find_basic_block(prologue).direct_branch retn, pre_dispatcher = get_retn_predispatcher(cfg) relevant_blocks, nop_blocks = get_relevant_nop_blocks(cfg) print '*******************relevant blocks************************' print 'prologue:%#x' % start print 'main_dispatcher:%#x' % main_dispatcher print 'pre_dispatcher:%#x' % pre_dispatcher print 'retn:%#x' % retn print 'relevant_blocks:', [hex(addr) for addr in relevant_blocks] print '*******************symbolic execution*********************' relevants = relevant_blocks relevants.append(prologue)