Format with black
This commit is contained in:
+49
-47
@@ -3,59 +3,61 @@ import click
|
|||||||
|
|
||||||
# Convert opcodes to the ACT expected format
|
# Convert opcodes to the ACT expected format
|
||||||
desired_names = {
|
desired_names = {
|
||||||
"StatusEffectList": None,
|
"StatusEffectList": None,
|
||||||
"StatusEffectList2": None,
|
"StatusEffectList2": None,
|
||||||
"StatusEffectList3": None,
|
"StatusEffectList3": None,
|
||||||
"BossStatusEffectList": None,
|
"BossStatusEffectList": None,
|
||||||
"Effect": "Ability1",
|
"Effect": "Ability1",
|
||||||
"AoeEffect8": "Ability8",
|
"AoeEffect8": "Ability8",
|
||||||
"AoeEffect16": "Ability16",
|
"AoeEffect16": "Ability16",
|
||||||
"AoeEffect24": "Ability24",
|
"AoeEffect24": "Ability24",
|
||||||
"AoeEffect32": "Ability32",
|
"AoeEffect32": "Ability32",
|
||||||
"ActorCast": None,
|
"ActorCast": None,
|
||||||
"EffectResult": None,
|
"EffectResult": None,
|
||||||
"EffectResultBasic": None,
|
"EffectResultBasic": None,
|
||||||
"ActorControl": None,
|
"ActorControl": None,
|
||||||
"ActorControlSelf": None,
|
"ActorControlSelf": None,
|
||||||
"ActorControlTarget": None,
|
"ActorControlTarget": None,
|
||||||
"UpdateHpMpTp": None,
|
"UpdateHpMpTp": None,
|
||||||
"PlayerSpawn": None,
|
"PlayerSpawn": None,
|
||||||
"NpcSpawn": None,
|
"NpcSpawn": None,
|
||||||
"NpcSpawn2": None,
|
"NpcSpawn2": None,
|
||||||
"ActorMove": None,
|
"ActorMove": None,
|
||||||
"ActorSetPos": None,
|
"ActorSetPos": None,
|
||||||
"ActorGauge": None,
|
"ActorGauge": None,
|
||||||
"PlaceFieldMarkerPreset": "PresetWaymark",
|
"PlaceFieldMarkerPreset": "PresetWaymark",
|
||||||
"PlaceFieldMarker": "Waymark",
|
"PlaceFieldMarker": "Waymark",
|
||||||
"SystemLogMessage": None
|
"SystemLogMessage": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument("opcodes_file", type=click.File('r'))
|
@click.argument("opcodes_file", type=click.File("r"))
|
||||||
def generate_act_format(opcodes_file):
|
def generate_act_format(opcodes_file):
|
||||||
opcode_mapping = dict()
|
opcode_mapping = dict()
|
||||||
|
|
||||||
for line in opcodes_file.readlines():
|
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:
|
if len(match_groups) != 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
opcode_name = match_groups[0][0].strip()
|
opcode_name = match_groups[0][0].strip()
|
||||||
opcode_val = match_groups[0][1]
|
opcode_val = match_groups[0][1]
|
||||||
if " or " in opcode_val:
|
if " or " in opcode_val:
|
||||||
opcodes = [int(v, 16) for v in opcode_val.split(" or ")]
|
opcodes = [int(v, 16) for v in opcode_val.split(" or ")]
|
||||||
else:
|
else:
|
||||||
opcodes = [int(opcode_val, 16)]
|
opcodes = [int(opcode_val, 16)]
|
||||||
opcode_mapping[opcode_name] = opcodes
|
opcode_mapping[opcode_name] = opcodes
|
||||||
|
|
||||||
|
for name, desired in desired_names.items():
|
||||||
|
if desired == None:
|
||||||
|
desired = name
|
||||||
|
opcodes = opcode_mapping[name]
|
||||||
|
if len(opcodes) == 1:
|
||||||
|
print(f"{desired}|{opcodes[0]:x}")
|
||||||
|
elif len(opcodes) > 1:
|
||||||
|
print(f'{desired}|{[f"{opcode:x}" for opcode in opcodes]}')
|
||||||
|
|
||||||
for name, desired in desired_names.items():
|
|
||||||
if desired == None:
|
|
||||||
desired = name
|
|
||||||
opcodes = opcode_mapping[name]
|
|
||||||
if len(opcodes) == 1:
|
|
||||||
print(f'{desired}|{opcodes[0]:x}')
|
|
||||||
elif len(opcodes) > 1:
|
|
||||||
print(f'{desired}|{[f"{opcode:x}" for opcode in opcodes]}')
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
generate_act_format()
|
generate_act_format()
|
||||||
|
|||||||
+41
-33
@@ -2,60 +2,68 @@ import json
|
|||||||
import re
|
import re
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
||||||
def load_diff_file(f, reverse=False):
|
def load_diff_file(f, reverse=False):
|
||||||
diff = dict()
|
diff = dict()
|
||||||
diff_json = json.load(f)
|
diff_json = json.load(f)
|
||||||
for pair in diff_json:
|
for pair in diff_json:
|
||||||
if "old" not in pair or "new" not in pair:
|
if "old" not in pair or "new" not in pair:
|
||||||
continue
|
continue
|
||||||
old_key = "new" if reverse else "old"
|
old_key = "new" if reverse else "old"
|
||||||
new_key = "old" if reverse else "new"
|
new_key = "old" if reverse else "new"
|
||||||
for old_opcode in pair[old_key]:
|
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(
|
||||||
return diff
|
(int(new_opcode, 16) for new_opcode in pair[new_key])
|
||||||
|
)
|
||||||
|
return diff
|
||||||
|
|
||||||
|
|
||||||
def opcodes_str(opcodes):
|
def opcodes_str(opcodes):
|
||||||
if len(opcodes) == 1:
|
if len(opcodes) == 1:
|
||||||
return hex(list(opcodes)[0])
|
return hex(list(opcodes)[0])
|
||||||
elif len(opcodes) > 1:
|
elif len(opcodes) > 1:
|
||||||
return " or ".join((hex(opcode) for opcode in opcodes))
|
return " or ".join((hex(opcode) for opcode in opcodes))
|
||||||
else:
|
else:
|
||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
|
|
||||||
|
|
||||||
def replace_line_with_new_opcode(line, diff, ver):
|
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:
|
if len(match_groups) != 1:
|
||||||
return line
|
return line
|
||||||
|
|
||||||
opcode_name = match_groups[0][0]
|
opcode_name = match_groups[0][0]
|
||||||
opcode_val = match_groups[0][1]
|
opcode_val = match_groups[0][1]
|
||||||
if " or " in opcode_val:
|
if " or " in opcode_val:
|
||||||
old_opcode = int(opcode_val.split(" or ")[0], 16)
|
old_opcode = int(opcode_val.split(" or ")[0], 16)
|
||||||
else:
|
else:
|
||||||
old_opcode = int(opcode_val, 16)
|
old_opcode = int(opcode_val, 16)
|
||||||
if old_opcode in diff:
|
if old_opcode in diff:
|
||||||
new_opcodes = diff[old_opcode]
|
new_opcodes = diff[old_opcode]
|
||||||
return f"{opcode_name}= {opcodes_str(new_opcodes)}, // updated {ver}\n"
|
return f"{opcode_name}= {opcodes_str(new_opcodes)}, // updated {ver}\n"
|
||||||
|
|
||||||
return f"// {line}"
|
return f"// {line}"
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument("new_version_string")
|
@click.argument("new_version_string")
|
||||||
@click.argument("diff_file", type=click.File('r'))
|
@click.argument("diff_file", type=click.File("r"))
|
||||||
@click.argument("opcodes_file", type=click.File('r'))
|
@click.argument("opcodes_file", type=click.File("r"))
|
||||||
@click.option("--reverse", is_flag=True)
|
@click.option("--reverse", is_flag=True)
|
||||||
def generate_opcodes_file(new_version_string, diff_file, opcodes_file, reverse):
|
def generate_opcodes_file(new_version_string, diff_file, opcodes_file, reverse):
|
||||||
diff = load_diff_file(diff_file, reverse)
|
diff = load_diff_file(diff_file, reverse)
|
||||||
queued_lines = []
|
queued_lines = []
|
||||||
for line in opcodes_file.readlines():
|
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"
|
new_filename = f"{new_version_string}_opcodes.txt"
|
||||||
with open(new_filename, "w+") as f:
|
with open(new_filename, "w+") as f:
|
||||||
f.writelines(queued_lines)
|
f.writelines(queued_lines)
|
||||||
|
|
||||||
|
print("Wrote to", new_filename)
|
||||||
|
|
||||||
print("Wrote to", new_filename)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
generate_opcodes_file()
|
generate_opcodes_file()
|
||||||
|
|||||||
+140
-122
@@ -4,192 +4,210 @@ import re
|
|||||||
|
|
||||||
ZONE_PROTO_DOWN_SIG = "48 89 ? 24 ? ? 48 83 EC 50 8B F2 49 8B"
|
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
|
max_size_diff = 10
|
||||||
|
|
||||||
|
|
||||||
def get_opcode_offset(r2):
|
def get_opcode_offset(r2):
|
||||||
orig_loc = r2.cmd("s") # Save original spot
|
orig_loc = r2.cmd("s") # Save original spot
|
||||||
r2.cmd("aei") # Initialize ESIL VM
|
r2.cmd("aei") # Initialize ESIL VM
|
||||||
r2.cmd("aeim") # Initialize ESIL VM stack
|
r2.cmd("aeim") # Initialize ESIL VM stack
|
||||||
r2.cmd("aeip") # Initialize ESIL VM IP to curseek
|
r2.cmd("aeip") # Initialize ESIL VM IP to curseek
|
||||||
|
|
||||||
r2.cmd("aecc") # continue until call
|
r2.cmd("aecc") # continue until call
|
||||||
r2.cmd('"aesue rax,0x0,>"') # continue until rax changes?
|
r2.cmd('"aesue rax,0x0,>"') # continue until rax changes?
|
||||||
r2.cmd("aer rdx=0x200") # set rdx to some arbitrary number
|
r2.cmd("aer rdx=0x200") # set rdx to some arbitrary number
|
||||||
r2.cmd("aeso") # step
|
r2.cmd("aeso") # step
|
||||||
|
|
||||||
regs = r2.cmdj("arj")
|
regs = r2.cmdj("arj")
|
||||||
opcode_offset = regs["rdx"] - regs["rax"]
|
opcode_offset = regs["rdx"] - regs["rax"]
|
||||||
|
|
||||||
# Clear the ESIL environment
|
# Clear the ESIL environment
|
||||||
r2.cmd('ar0')
|
r2.cmd("ar0")
|
||||||
r2.cmd('aeim-')
|
r2.cmd("aeim-")
|
||||||
r2.cmd('aei-')
|
r2.cmd("aei-")
|
||||||
r2.cmd(f"s {orig_loc}") # Seek back to original spot
|
r2.cmd(f"s {orig_loc}") # Seek back to original spot
|
||||||
|
|
||||||
|
return opcode_offset
|
||||||
|
|
||||||
return opcode_offset
|
|
||||||
|
|
||||||
def get_longest_switch(switch_cases):
|
def get_longest_switch(switch_cases):
|
||||||
switches = dict()
|
switches = dict()
|
||||||
|
|
||||||
pattern = re.compile("case\.(0x[0-9a-fA-F]+)\.(\d+)")
|
pattern = re.compile("case\.(0x[0-9a-fA-F]+)\.(\d+)")
|
||||||
|
|
||||||
for l in switch_cases:
|
for l in switch_cases:
|
||||||
match = pattern.match(l["name"])
|
match = pattern.match(l["name"])
|
||||||
if match is not None:
|
if match is not None:
|
||||||
switch_ea = match[1]
|
switch_ea = match[1]
|
||||||
case_ea = l["offset"]
|
case_ea = l["offset"]
|
||||||
|
|
||||||
if switch_ea not in switches:
|
if switch_ea not in switches:
|
||||||
switches[switch_ea] = dict()
|
switches[switch_ea] = dict()
|
||||||
if case_ea not in switches[switch_ea]:
|
if case_ea not in switches[switch_ea]:
|
||||||
switches[switch_ea][case_ea] = {
|
switches[switch_ea][case_ea] = {
|
||||||
"opcodes": [],
|
"opcodes": [],
|
||||||
}
|
}
|
||||||
switches[switch_ea][case_ea]["opcodes"].append(match[2])
|
switches[switch_ea][case_ea]["opcodes"].append(match[2])
|
||||||
|
|
||||||
longest_switch = dict()
|
longest_switch = dict()
|
||||||
for switch_ea in switches:
|
for switch_ea in switches:
|
||||||
if len(switches[switch_ea].keys()) > len(longest_switch):
|
if len(switches[switch_ea].keys()) > len(longest_switch):
|
||||||
longest_switch = switches[switch_ea]
|
longest_switch = switches[switch_ea]
|
||||||
|
|
||||||
|
return longest_switch
|
||||||
|
|
||||||
return longest_switch
|
|
||||||
|
|
||||||
def get_block_sizes(blocks):
|
def get_block_sizes(blocks):
|
||||||
block_sizes = dict()
|
block_sizes = dict()
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
block_sizes[block["addr"]] = block["size"]
|
block_sizes[block["addr"]] = block["size"]
|
||||||
return block_sizes
|
return block_sizes
|
||||||
|
|
||||||
|
|
||||||
def generate_opcode_db(packet_handler_ea, switch, opcode_offset, block_sizes):
|
def generate_opcode_db(packet_handler_ea, switch, opcode_offset, block_sizes):
|
||||||
opcodes_db = dict()
|
opcodes_db = dict()
|
||||||
|
|
||||||
|
for case_ea, data in switch.items():
|
||||||
|
resolved_opcodes = [int(opcode) + opcode_offset for opcode in data["opcodes"]]
|
||||||
|
opcodes_db[resolved_opcodes[0]] = {
|
||||||
|
"case_ea": case_ea,
|
||||||
|
"rel_ea": case_ea - packet_handler_ea,
|
||||||
|
"opcodes": resolved_opcodes,
|
||||||
|
"size": block_sizes[case_ea] if case_ea in block_sizes else 0,
|
||||||
|
}
|
||||||
|
return opcodes_db
|
||||||
|
|
||||||
for case_ea, data in switch.items():
|
|
||||||
resolved_opcodes = [int(opcode) + opcode_offset for opcode in data["opcodes"]]
|
|
||||||
opcodes_db[resolved_opcodes[0]] = {
|
|
||||||
"case_ea": case_ea,
|
|
||||||
"rel_ea": case_ea - packet_handler_ea,
|
|
||||||
"opcodes": resolved_opcodes,
|
|
||||||
"size": block_sizes[case_ea] if case_ea in block_sizes else 0,
|
|
||||||
}
|
|
||||||
return opcodes_db
|
|
||||||
|
|
||||||
def get_opcodes_db(exe_file):
|
def get_opcodes_db(exe_file):
|
||||||
from utils import eprint, create_r2_byte_pattern, sync_r2_output
|
from utils import eprint, create_r2_byte_pattern, sync_r2_output
|
||||||
|
|
||||||
import r2pipe
|
import r2pipe
|
||||||
|
|
||||||
r2 = r2pipe.open(exe_file, ["-2"])
|
r2 = r2pipe.open(exe_file, ["-2"])
|
||||||
eprint(f"Radare loaded {exe_file}")
|
eprint(f"Radare loaded {exe_file}")
|
||||||
|
|
||||||
sync_r2_output(r2)
|
sync_r2_output(r2)
|
||||||
|
|
||||||
p = create_r2_byte_pattern(ZONE_PROTO_DOWN_SIG)
|
p = create_r2_byte_pattern(ZONE_PROTO_DOWN_SIG)
|
||||||
target = r2.cmd(f"/x {p}").split()[0] # Find byte pattern
|
target = r2.cmd(f"/x {p}").split()[0] # Find byte pattern
|
||||||
packet_handler_ea = int(target, 16)
|
packet_handler_ea = int(target, 16)
|
||||||
|
|
||||||
r2.cmd(f"s {target}") # Seek to target
|
r2.cmd(f"s {target}") # Seek to target
|
||||||
|
|
||||||
## STEP 1: Grab switch cases
|
## STEP 1: Grab switch cases
|
||||||
r2.cmd("f--") # Delete existing flags
|
r2.cmd("f--") # Delete existing flags
|
||||||
r2.cmd("afr") # Analyze function recursively
|
r2.cmd("afr") # Analyze function recursively
|
||||||
switch_cases = r2.cmdj(f"fj")
|
switch_cases = r2.cmdj(f"fj")
|
||||||
|
|
||||||
eprint(f" Loaded switch cases")
|
eprint(f" Loaded switch cases")
|
||||||
|
|
||||||
## STEP 2: Grab opcode offset
|
## STEP 2: Grab opcode offset
|
||||||
|
|
||||||
opcode_offset = get_opcode_offset(r2)
|
opcode_offset = get_opcode_offset(r2)
|
||||||
eprint(f" Found opcode offset: {opcode_offset}")
|
eprint(f" Found opcode offset: {opcode_offset}")
|
||||||
|
|
||||||
## STEP 3: Grab blocks from packet handler
|
## STEP 3: Grab blocks from packet handler
|
||||||
blocks = r2.cmdj("afbj")
|
blocks = r2.cmdj("afbj")
|
||||||
|
|
||||||
r2.quit()
|
r2.quit()
|
||||||
|
|
||||||
eprint(f" Grabbed blocks from packet handler")
|
eprint(f" Grabbed blocks from packet handler")
|
||||||
|
|
||||||
## STEP 4: Process data
|
## STEP 4: Process data
|
||||||
packet_handler_switch = get_longest_switch(switch_cases)
|
packet_handler_switch = get_longest_switch(switch_cases)
|
||||||
block_sizes = get_block_sizes(blocks)
|
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")
|
eprint(f" Loaded {len(opcode_db)} cases from packet handler")
|
||||||
|
|
||||||
|
return opcode_db
|
||||||
|
|
||||||
return opcode_db
|
|
||||||
|
|
||||||
def find_closest_rel_ea(opcodes_db, dest):
|
def find_closest_rel_ea(opcodes_db, dest):
|
||||||
closest = fucked_distance
|
closest = fucked_distance
|
||||||
closest_opcode = None
|
closest_opcode = None
|
||||||
|
|
||||||
for opcode, case in opcodes_db.items():
|
for opcode, case in opcodes_db.items():
|
||||||
rel_ea = case['rel_ea']
|
rel_ea = case["rel_ea"]
|
||||||
|
|
||||||
num = abs(rel_ea - dest)
|
num = abs(rel_ea - dest)
|
||||||
|
|
||||||
|
if num < closest:
|
||||||
|
closest = num
|
||||||
|
closest_opcode = opcode
|
||||||
|
return (closest, closest_opcode)
|
||||||
|
|
||||||
if num < closest:
|
|
||||||
closest = num
|
|
||||||
closest_opcode = opcode
|
|
||||||
return (closest, closest_opcode)
|
|
||||||
|
|
||||||
def get_opcodes_str(opcodes):
|
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):
|
def add_match_case(cases, case):
|
||||||
# check if case already exists
|
# check if case already exists
|
||||||
|
|
||||||
for c in cases:
|
for c in cases:
|
||||||
if c['rel_ea'] == case['rel_ea']:
|
if c["rel_ea"] == case["rel_ea"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
cases.append(case)
|
||||||
|
|
||||||
cases.append(case)
|
|
||||||
|
|
||||||
def find_opcode_matches(old_opcodes_db, new_opcodes_db):
|
def find_opcode_matches(old_opcodes_db, new_opcodes_db):
|
||||||
matches = []
|
matches = []
|
||||||
new_opcodes = list(new_opcodes_db.keys())
|
new_opcodes = list(new_opcodes_db.keys())
|
||||||
|
|
||||||
for k, case in enumerate(old_opcodes_db.values()):
|
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
|
# 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:
|
if dist == fucked_distance:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
order_match_opcode = new_opcodes[k]
|
order_match_opcode = new_opcodes[k]
|
||||||
|
|
||||||
order_match = new_opcodes_db[order_match_opcode]
|
order_match = new_opcodes_db[order_match_opcode]
|
||||||
dist_match = new_opcodes_db[dist_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
|
# 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"]))
|
matches.append((old_opcodes, order_match["opcodes"]))
|
||||||
|
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument("old_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True))
|
@click.argument(
|
||||||
@click.argument("new_exe", type=click.Path(exists=True, dir_okay=False, resolve_path=True))
|
"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):
|
def minor_patch_diff(old_exe, new_exe):
|
||||||
old_opcodes_db = get_opcodes_db(old_exe)
|
old_opcodes_db = get_opcodes_db(old_exe)
|
||||||
new_opcodes_db = get_opcodes_db(new_exe)
|
new_opcodes_db = get_opcodes_db(new_exe)
|
||||||
|
|
||||||
opcodes_found = find_opcode_matches(old_opcodes_db, new_opcodes_db)
|
opcodes_found = find_opcode_matches(old_opcodes_db, new_opcodes_db)
|
||||||
opcodes_object = []
|
opcodes_object = []
|
||||||
|
|
||||||
for k, v in enumerate(opcodes_found):
|
for k, v in enumerate(opcodes_found):
|
||||||
old, new = v
|
old, new = v
|
||||||
|
|
||||||
opcodes_object.append({
|
opcodes_object.append(
|
||||||
"old": [hex(o) for o in old],
|
{
|
||||||
"new": [hex(o) for o in new],
|
"old": [hex(o) for o in old],
|
||||||
})
|
"new": [hex(o) for o in new],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
print(json.dumps(opcodes_object, indent=2))
|
||||||
|
|
||||||
print(json.dumps(opcodes_object, indent=2))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
minor_patch_diff()
|
minor_patch_diff()
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
def eprint(*args, **kwargs):
|
def eprint(*args, **kwargs):
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def create_r2_byte_pattern(sig):
|
def create_r2_byte_pattern(sig):
|
||||||
tokens = sig.split()
|
tokens = sig.split()
|
||||||
r2_tokens = []
|
r2_tokens = []
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if token == "?":
|
if token == "?":
|
||||||
r2_tokens.append("..")
|
r2_tokens.append("..")
|
||||||
else:
|
else:
|
||||||
r2_tokens.append(token)
|
r2_tokens.append(token)
|
||||||
return "".join(r2_tokens)
|
return "".join(r2_tokens)
|
||||||
|
|
||||||
|
|
||||||
def sync_r2_output(r2):
|
def sync_r2_output(r2):
|
||||||
"""
|
"""
|
||||||
For some fucking reason r2pipe output gets desynced from the start,
|
For some fucking reason r2pipe output gets desynced from the start,
|
||||||
making the result of every command what the previous command should
|
making the result of every command what the previous command should
|
||||||
have returned.
|
have returned.
|
||||||
|
|
||||||
Read stuff from the process pipe until it stops being stupid.
|
Read stuff from the process pipe until it stops being stupid.
|
||||||
"""
|
"""
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
p = r2.process.stdout.read(1)
|
p = r2.process.stdout.read(1)
|
||||||
if len(p) > 0:
|
if len(p) > 0:
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
output = r2.cmd(f"?vi 123").strip()
|
output = r2.cmd(f"?vi 123").strip()
|
||||||
if output != "123":
|
if output != "123":
|
||||||
raise Exception("R2 state never got synced")
|
raise Exception("R2 state never got synced")
|
||||||
|
|||||||
Reference in New Issue
Block a user