-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeobfuscate.py
105 lines (77 loc) · 3.14 KB
/
deobfuscate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
bv.begin_undo_actions()
jmp_table_addr = 0x6eba60
n = 0x5a
index_offset = 0x388
addr_array_stack_addr = 0x2e0
def is_in_ranges(addr, addr_ranges):
for addr_range in addr_ranges:
if addr_range[0] <= addr <= addr_range[1]:
return True
return False
valid_addr_range = [] # List of valid address ranges
refs = [ref for ref in bv.get_code_refs(jmp_table_addr)]
base_func = bv.get_functions_containing(refs[0].address)[0]
log_info(f"Base function: {base_func.name}")
valid_addr_range.append((base_func.lowest_address, base_func.highest_address))
arch = bv.arch
br = BinaryReader(bv)
br.seek(jmp_table_addr)
addrs = []
# Create functions at each address in the jump table
for i in range(n):
addr = br.read64le()
if not bv.get_function_at(addr):
bv.create_user_function(addr)
log_info("Adding function at: 0x%x" % addr)
else:
log_info("Function already exists at: 0x%x" % addr)
addrs.append(addr)
bv.update_analysis_and_wait()
# Update the valid address ranges
for addr in addrs:
func = bv.get_function_at(addr)
if not func:
log_error("Function not found at 0x%x" % addr)
raise
log_info("Append Function: %s" % func.name)
valid_addr_range.append((func.lowest_address, func.highest_address))
search_text = f"mov qword [rbp-0x{index_offset:x}],"
# Search the valid address of the text and parse the code
for res in bv.find_all_text(bv.start, bv.end, search_text):
addr, text, line = res
if not is_in_ranges(addr, valid_addr_range):
log_info(f"Skipping address {addr: #x}")
continue
func = bv.get_functions_containing(addr)[0]
llil_func = func.llil # Get the LLIL instructions of the function
llil_ins = func.get_llil_at(addr) # Get the LLIL instruction at the address
idx = llil_ins.instr_index # Get the instruction index
if llil_func[idx + 1].operation == LowLevelILOperation.LLIL_GOTO: # Check if the next instruction is a GOTO
llil_next = llil_func[idx + 1].dest + 1# Get the ins after the destination of the GOTO
else:
llil_next = idx + 1
while llil_func[llil_next].src.src.left.operation != LowLevelILOperation.LLIL_ADD:
llil_next += 1
llil_check_ins = llil_func[llil_next] # Get the instruction at the index
try:
offset_jmp_table = llil_check_ins.src.src.right.constant # Get the offset of the jump table
except:
continue
if offset_jmp_table != -addr_array_stack_addr:
continue # Not what we want
if llil_ins.operation == LowLevelILOperation.LLIL_STORE:
if llil_ins.src.operation == LowLevelILOperation.LLIL_CONST:
next_jump_offset = llil_ins.src.constant
log_info(f"Next jump offset: 0x{next_jump_offset:x}")
try:
next_jump = addrs[next_jump_offset]
except:
next_jump = 0x0
log_warn("Next jump not found")
# log start patching
log_info(f"Start patching at {addr: #x} from function name {func.name} with 'jmp {next_jump: #x}'")
code = arch.assemble(f"jmp {next_jump: #x}", addr)
bv.write(addr, code)
bv.update_analysis_and_wait()
bv.commit_undo_actions()
log_info("Done")