Format with black
This commit is contained in:
@@ -27,16 +27,17 @@ desired_names = {
|
||||
"ActorGauge": None,
|
||||
"PlaceFieldMarkerPreset": "PresetWaymark",
|
||||
"PlaceFieldMarker": "Waymark",
|
||||
"SystemLogMessage": None
|
||||
"SystemLogMessage": None,
|
||||
}
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("opcodes_file", type=click.File('r'))
|
||||
@click.argument("opcodes_file", type=click.File("r"))
|
||||
def generate_act_format(opcodes_file):
|
||||
opcode_mapping = dict()
|
||||
|
||||
for line in opcodes_file.readlines():
|
||||
match_groups = re.findall(r'^\s*([^\/].*)=\s*(.*),\s*\/\/.*$', line)
|
||||
match_groups = re.findall(r"^\s*([^\/].*)=\s*(.*),\s*\/\/.*$", line)
|
||||
if len(match_groups) != 1:
|
||||
continue
|
||||
|
||||
@@ -53,9 +54,10 @@ def generate_act_format(opcodes_file):
|
||||
desired = name
|
||||
opcodes = opcode_mapping[name]
|
||||
if len(opcodes) == 1:
|
||||
print(f'{desired}|{opcodes[0]:x}')
|
||||
print(f"{desired}|{opcodes[0]:x}")
|
||||
elif len(opcodes) > 1:
|
||||
print(f'{desired}|{[f"{opcode:x}" for opcode in opcodes]}')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_act_format()
|
||||
@@ -2,6 +2,7 @@ import json
|
||||
import re
|
||||
import click
|
||||
|
||||
|
||||
def load_diff_file(f, reverse=False):
|
||||
diff = dict()
|
||||
diff_json = json.load(f)
|
||||
@@ -11,9 +12,12 @@ def load_diff_file(f, reverse=False):
|
||||
old_key = "new" if reverse else "old"
|
||||
new_key = "old" if reverse else "new"
|
||||
for old_opcode in pair[old_key]:
|
||||
diff[int(old_opcode, 16)] = set((int(new_opcode, 16) for new_opcode in pair[new_key]))
|
||||
diff[int(old_opcode, 16)] = set(
|
||||
(int(new_opcode, 16) for new_opcode in pair[new_key])
|
||||
)
|
||||
return diff
|
||||
|
||||
|
||||
def opcodes_str(opcodes):
|
||||
if len(opcodes) == 1:
|
||||
return hex(list(opcodes)[0])
|
||||
@@ -22,8 +26,9 @@ def opcodes_str(opcodes):
|
||||
else:
|
||||
return "UNKNOWN"
|
||||
|
||||
|
||||
def replace_line_with_new_opcode(line, diff, ver):
|
||||
match_groups = re.findall(r'^\s*([^\/].*)=\s*(.*),\s*\/\/.*$', line)
|
||||
match_groups = re.findall(r"^\s*([^\/].*)=\s*(.*),\s*\/\/.*$", line)
|
||||
if len(match_groups) != 1:
|
||||
return line
|
||||
|
||||
@@ -42,14 +47,16 @@ def replace_line_with_new_opcode(line, diff, ver):
|
||||
|
||||
@click.command()
|
||||
@click.argument("new_version_string")
|
||||
@click.argument("diff_file", type=click.File('r'))
|
||||
@click.argument("opcodes_file", type=click.File('r'))
|
||||
@click.argument("diff_file", type=click.File("r"))
|
||||
@click.argument("opcodes_file", type=click.File("r"))
|
||||
@click.option("--reverse", is_flag=True)
|
||||
def generate_opcodes_file(new_version_string, diff_file, opcodes_file, reverse):
|
||||
diff = load_diff_file(diff_file, reverse)
|
||||
queued_lines = []
|
||||
for line in opcodes_file.readlines():
|
||||
queued_lines.append(replace_line_with_new_opcode(line, diff, new_version_string))
|
||||
queued_lines.append(
|
||||
replace_line_with_new_opcode(line, diff, new_version_string)
|
||||
)
|
||||
|
||||
new_filename = f"{new_version_string}_opcodes.txt"
|
||||
with open(new_filename, "w+") as f:
|
||||
@@ -57,5 +64,6 @@ def generate_opcodes_file(new_version_string, diff_file, opcodes_file, reverse):
|
||||
|
||||
print("Wrote to", new_filename)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_opcodes_file()
|
||||
+34
-16
@@ -4,9 +4,10 @@ import re
|
||||
|
||||
ZONE_PROTO_DOWN_SIG = "48 89 ? 24 ? ? 48 83 EC 50 8B F2 49 8B"
|
||||
|
||||
fucked_distance = 0xffffffff
|
||||
fucked_distance = 0xFFFFFFFF
|
||||
max_size_diff = 10
|
||||
|
||||
|
||||
def get_opcode_offset(r2):
|
||||
orig_loc = r2.cmd("s") # Save original spot
|
||||
r2.cmd("aei") # Initialize ESIL VM
|
||||
@@ -22,13 +23,14 @@ def get_opcode_offset(r2):
|
||||
opcode_offset = regs["rdx"] - regs["rax"]
|
||||
|
||||
# Clear the ESIL environment
|
||||
r2.cmd('ar0')
|
||||
r2.cmd('aeim-')
|
||||
r2.cmd('aei-')
|
||||
r2.cmd("ar0")
|
||||
r2.cmd("aeim-")
|
||||
r2.cmd("aei-")
|
||||
r2.cmd(f"s {orig_loc}") # Seek back to original spot
|
||||
|
||||
return opcode_offset
|
||||
|
||||
|
||||
def get_longest_switch(switch_cases):
|
||||
switches = dict()
|
||||
|
||||
@@ -55,12 +57,14 @@ def get_longest_switch(switch_cases):
|
||||
|
||||
return longest_switch
|
||||
|
||||
|
||||
def get_block_sizes(blocks):
|
||||
block_sizes = dict()
|
||||
for block in blocks:
|
||||
block_sizes[block["addr"]] = block["size"]
|
||||
return block_sizes
|
||||
|
||||
|
||||
def generate_opcode_db(packet_handler_ea, switch, opcode_offset, block_sizes):
|
||||
opcodes_db = dict()
|
||||
|
||||
@@ -74,6 +78,7 @@ def generate_opcode_db(packet_handler_ea, switch, opcode_offset, block_sizes):
|
||||
}
|
||||
return opcodes_db
|
||||
|
||||
|
||||
def get_opcodes_db(exe_file):
|
||||
from utils import eprint, create_r2_byte_pattern, sync_r2_output
|
||||
|
||||
@@ -112,18 +117,21 @@ def get_opcodes_db(exe_file):
|
||||
## STEP 4: Process data
|
||||
packet_handler_switch = get_longest_switch(switch_cases)
|
||||
block_sizes = get_block_sizes(blocks)
|
||||
opcode_db = generate_opcode_db(packet_handler_ea, packet_handler_switch, opcode_offset, block_sizes)
|
||||
opcode_db = generate_opcode_db(
|
||||
packet_handler_ea, packet_handler_switch, opcode_offset, block_sizes
|
||||
)
|
||||
|
||||
eprint(f" Loaded {len(opcode_db)} cases from packet handler")
|
||||
|
||||
return opcode_db
|
||||
|
||||
|
||||
def find_closest_rel_ea(opcodes_db, dest):
|
||||
closest = fucked_distance
|
||||
closest_opcode = None
|
||||
|
||||
for opcode, case in opcodes_db.items():
|
||||
rel_ea = case['rel_ea']
|
||||
rel_ea = case["rel_ea"]
|
||||
|
||||
num = abs(rel_ea - dest)
|
||||
|
||||
@@ -132,27 +140,30 @@ def find_closest_rel_ea(opcodes_db, dest):
|
||||
closest_opcode = opcode
|
||||
return (closest, closest_opcode)
|
||||
|
||||
|
||||
def get_opcodes_str(opcodes):
|
||||
return ', '.join([hex(o) for o in opcodes])
|
||||
return ", ".join([hex(o) for o in opcodes])
|
||||
|
||||
|
||||
def add_match_case(cases, case):
|
||||
# check if case already exists
|
||||
|
||||
for c in cases:
|
||||
if c['rel_ea'] == case['rel_ea']:
|
||||
if c["rel_ea"] == case["rel_ea"]:
|
||||
return
|
||||
|
||||
cases.append(case)
|
||||
|
||||
|
||||
def find_opcode_matches(old_opcodes_db, new_opcodes_db):
|
||||
matches = []
|
||||
new_opcodes = list(new_opcodes_db.keys())
|
||||
|
||||
for k, case in enumerate(old_opcodes_db.values()):
|
||||
old_opcodes = case['opcodes']
|
||||
old_opcodes = case["opcodes"]
|
||||
|
||||
# see if we can get a match for the relative ea first
|
||||
dist, dist_match_opcode = find_closest_rel_ea(new_opcodes_db, case['rel_ea'])
|
||||
dist, dist_match_opcode = find_closest_rel_ea(new_opcodes_db, case["rel_ea"])
|
||||
|
||||
if dist == fucked_distance:
|
||||
continue
|
||||
@@ -162,18 +173,22 @@ def find_opcode_matches(old_opcodes_db, new_opcodes_db):
|
||||
order_match = new_opcodes_db[order_match_opcode]
|
||||
dist_match = new_opcodes_db[dist_match_opcode]
|
||||
|
||||
size_diff = abs(dist_match['size'] - case['size'])
|
||||
size_diff = abs(dist_match["size"] - case["size"])
|
||||
|
||||
# see if the rva matches for the cases found by the distance and order
|
||||
if dist_match['rel_ea'] == order_match['rel_ea'] and size_diff < max_size_diff:
|
||||
if dist_match["rel_ea"] == order_match["rel_ea"] and size_diff < max_size_diff:
|
||||
matches.append((old_opcodes, order_match["opcodes"]))
|
||||
|
||||
return matches
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("old_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True))
|
||||
@click.argument("new_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True))
|
||||
@click.argument(
|
||||
"old_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True)
|
||||
)
|
||||
@click.argument(
|
||||
"new_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True)
|
||||
)
|
||||
def minor_patch_diff(old_exe, new_exe):
|
||||
old_opcodes_db = get_opcodes_db(old_exe)
|
||||
new_opcodes_db = get_opcodes_db(new_exe)
|
||||
@@ -184,12 +199,15 @@ def minor_patch_diff(old_exe, new_exe):
|
||||
for k, v in enumerate(opcodes_found):
|
||||
old, new = v
|
||||
|
||||
opcodes_object.append({
|
||||
opcodes_object.append(
|
||||
{
|
||||
"old": [hex(o) for o in old],
|
||||
"new": [hex(o) for o in new],
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
print(json.dumps(opcodes_object, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
minor_patch_diff()
|
||||
@@ -1,9 +1,11 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
def create_r2_byte_pattern(sig):
|
||||
tokens = sig.split()
|
||||
r2_tokens = []
|
||||
@@ -14,6 +16,7 @@ def create_r2_byte_pattern(sig):
|
||||
r2_tokens.append(token)
|
||||
return "".join(r2_tokens)
|
||||
|
||||
|
||||
def sync_r2_output(r2):
|
||||
"""
|
||||
For some fucking reason r2pipe output gets desynced from the start,
|
||||
|
||||
Reference in New Issue
Block a user