Skip to content

Instantly share code, notes, and snippets.

@edeca
Last active December 16, 2019 13:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edeca/716c38cc78c5df17120583c203c1640d to your computer and use it in GitHub Desktop.
Save edeca/716c38cc78c5df17120583c203c1640d to your computer and use it in GitHub Desktop.
Find functions in IDA which are called by library functions and probably aren't user code
import idaapi
from idautils import *
########
# Date: October 2019
# Author: David Cannings (@edeca)
#
# Rename all functions that are called by library code as "__unknown_library_function_N".
#
# There is a high likelyhood these are less interesting to analyse than user
# code, therefore attention should probably be spent elsewhere. This works well
# when FLIRT detects some library functions but not all. Adding additional
# signatures (View -> Subviews -> Signatures) can often give enough clues for this
# script to make your life easier.
#
# The search is conducted in multiple passes, so any function called by something
# we already renamed as __unknown_library_function_N will also be treated as internal.
########
MAX_PASSES = 16
def rename_function(function_ea, name, max=999):
renamed = False
for n in range(0, max+1):
new_name = "{}_{}".format(name, n)
if idaapi.set_name(function_ea, new_name, idaapi.SN_NOWARN):
renamed = True
break
if not renamed:
print("[!] Couldn't rename, do you need to increase max?")
func = idaapi.get_func(function_ea)
func.flags |= FUNC_LIB
idaapi.update_func(func)
def is_thunk_function(function_ea):
func = idaapi.get_func(function_ea)
if not func or not (func.flags & idaapi.FUNC_THUNK):
return False
return True
def is_library_function(function_ea):
func = idaapi.get_func(function_ea)
if not func or not (func.flags & idaapi.FUNC_LIB):
return False
return True
def should_skip(function_ea):
return is_thunk_function(function_ea) | is_library_function(function_ea)
def main():
renamed = 0
for i in range(1, MAX_PASSES + 1):
renamed_this_pass = 0
print("[+] Pass {}".format(i))
for function_ea in Functions():
name = idaapi.get_func_name(function_ea)
if should_skip(function_ea) :
#print "[+] {} is a library/thunk function, skipping".format(name)
continue
if not name.startswith("sub_"):
#print("[+] Skipping {} because it has been renamed".format(name))
continue
called_by_lib = False
for ref in CodeRefsTo(function_ea, 1):
# The caller name can be None when it's not part of a function
caller_name = idaapi.get_func_name(ref)
if caller_name is None:
continue
if is_library_function(ref) or caller_name.startswith("__unknown_library_function_"):
res = is_library_function(ref)
called_by_lib = True
break
if called_by_lib:
print("[+] Xref to 0x{:08x} comes from library function {}".format(function_ea, caller_name))
rename_function(function_ea, "__unknown_library_function")
renamed_this_pass += 1
renamed += renamed_this_pass
print("[+] End of pass {}, renamed {} functions".format(i, renamed_this_pass))
if renamed_this_pass == 0:
break
print("[+] Finished, renamed a total of {} functions".format(renamed))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment