Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to IDA namer script. #1017

Merged
merged 1 commit into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.