Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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