Skip to content

Commit

Permalink
Improvements to IDA namer script. (#1017)
Browse files Browse the repository at this point in the history
- Output a valid standalone script.
- Merge base script and IDA 7.7 variant script.
- Additional options for script output.
- Reduce code duplication.
  • Loading branch information
gibbed committed Apr 1, 2024
1 parent f03662d commit f21f089
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 140 deletions.
134 changes: 81 additions & 53 deletions reversing/scripts/ida_namer/ida_namer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,88 @@
import fire
import os

def main(il2cpp_path=None, out_path=None, imagebase = None, new_imagebase = None):
if il2cpp_path is None:
def main(il2cpp_path = None, out_path = None, imagebase = None, new_imagebase = None, no_reflection = None, ida77 = None, undefine = None):
if not il2cpp_path:
print("--il2cpp_path not specified")
return

if out_path is None:
elif not out_path:
print("--out_path not specified")
return

if not os.path.exists(il2cpp_path):
elif imagebase and not new_imagebase:
print("--imagebase specified but --new_imagebase not specified")
return
elif not imagebase and new_imagebase:
print("--new_imagebase specified but --imagebase not specified")
return
elif not os.path.exists(il2cpp_path):
print("--il2cpp_path does not exist")
return

if imagebase and isinstance(imagebase, str):
imagebase = int(imagebase, 16)

if new_imagebase and isinstance(new_imagebase, str):
new_imagebase = int(new_imagebase, 16)

with open(il2cpp_path, "r", encoding="utf8") as f:
il2cpp_dump = json.load(f)

out_str = ""
bad_chars = ['<', '>', '`', ".", ",", "[", "]", "|", ' ', '=']
out_lines = []
seen_functions = set()

def output_code_old(address, name):
nonlocal out_lines, undefine

if undefine:
out_lines.append("MakeUnkn(%s, BADADDR);\n" % (address))
out_lines.append("MakeNameEx(%s, \"%s\", SN_CHECK);\n" % (address, name))
if undefine:
out_lines.append("MakeFunction(%s, BADADDR);\n" % (address))

def output_code_new(address, name):
nonlocal out_lines, undefine
if undefine:
out_lines.append("del_items(%s);\n" % (address))
out_lines.append("set_name(%s, \"%s\", SN_CHECK);\n" % (address, name))
if undefine:
out_lines.append("add_func(%s);\n" % (address))

def output_code(address, name):
nonlocal out_lines, imagebase, new_imagebase, undefine, ida77

if address == 0 or address in seen_functions:
return False

seen_functions.add(address)

if imagebase is not None and new_imagebase is not None:
address = address - imagebase
address = address + new_imagebase

address = str(hex(address))

if ida77:
output_code_new(address, name)
else:
output_code_old(address, name)

return True

bad_chars = ['<', '>', '`', '.', ',', '[', ']', '|', ' ', '=']

def filter_name(name):
nonlocal bad_chars
for bad_char in bad_chars:
name = name.replace(bad_char, "_")
return name

out_lines.append("#include <idc.idc>\n")
out_lines.append("static main()\n")
out_lines.append("{\n")

num_methods_found = 0
num_reflection_methods_found = 0

seen_functions = set()

for class_name, entry in il2cpp_dump.items():
try:
for bad_char in bad_chars:
Expand All @@ -39,66 +97,36 @@ def main(il2cpp_path=None, out_path=None, imagebase = None, new_imagebase = None
if method_entry is None:
continue

# filter the method name and class name for bad chars
for bad_char in bad_chars:
method_name = method_name.replace(bad_char, "_")
address = int("0x" + method_entry["function"], 16) # is a string not an int

#print(hex(int("0x" + method_entry["function"], 16)))
address = str(hex(int("0x" + method_entry["function"], 16))) # is a string not an int
if output_code(address, filter_name(class_name) + "__" + filter_name(method_name)):
num_methods_found = num_methods_found + 1

if address == "0" or address in seen_functions:
if not no_reflection and "reflection_methods" in entry:
for method_name, method_entry in entry["reflection_methods"].items():
if method_entry is None:
continue

seen_functions.add(address)

if imagebase is not None and new_imagebase is not None:
address_int = int("0x" + method_entry["function"], 16)
address_int = address_int - imagebase
address_int = address_int + new_imagebase
address = str(hex(address_int))
address = int(method_entry["function"], 16) # is a string not an int

out_str = out_str + "idc.MakeName(%s, '%s__%s')\n" % (address, class_name, method_name)
num_methods_found = num_methods_found + 1

if "reflection_methods" in entry:
try:
for method_name, method_entry in entry["reflection_methods"].items():
if method_entry is None:
continue

for bad_char in bad_chars:
method_name = method_name.replace(bad_char, "_")

address = str(hex(int("0x" + method_entry["function"], 16))) # is a string not an int

if address == "0" or address in seen_functions:
continue

seen_functions.add(address)

if imagebase is not None and new_imagebase is not None:
address_int = int("0x" + method_entry["function"], 16)
address_int = address_int - imagebase
address_int = address_int + new_imagebase
address = str(hex(address_int))

out_str = out_str + "idc.MakeName(%s, 'reflection_methods_%s')\n" % (address, method_name)
if output_code(address, "reflection_methods_" + filter_name(method_name)):
num_reflection_methods_found = num_reflection_methods_found + 1
except:
continue

except (KeyError, TypeError):
print("Error processing class %s" % class_name)
continue

out_lines.append("}\n")

print("Found %d methods" % num_methods_found)
print("Found %d reflection methods" % num_reflection_methods_found)
print("Writing to %s..." % out_path)

with open(out_path, "w", encoding="utf8") as f:
f.write(out_str)
f.writelines(out_lines)

print("Done!")


if __name__ == '__main__':
fire.Fire(main)
fire.Fire(main)
87 changes: 0 additions & 87 deletions reversing/scripts/ida_namer/ida_namer_ida77.py

This file was deleted.

0 comments on commit f21f089

Please sign in to comment.