有没有办法通过 IDAPython 获取函数中所有被调用 API 的列表。例如,我有以下来自函数的代码。
.text:003A33D9 call esi ; _snwprintf
.text:003A33DB add esp, 1Ch
.text:003A33DE mov eax, 3A4336h
.text:003A33E3 push ebx ; dwReserved
.text:003A33E4 mov [ebp+var_C], eax
.text:003A33E7 mov [ebp+var_8], eax
.text:003A33EA push 0Ch ; dwBufferLength
.text:003A33EC lea eax, [ebp+pBuffer]
.text:003A33EF push eax ; pBuffer
.text:003A33F0 push 26h ; dwOption
.text:003A33F2 mov [ebp+pBuffer], 1
.text:003A33F9 call ds:UrlMkSetSessionOption
.text:003A33FF lea eax, [ebp+szUrlName]
.text:003A3405 push eax ; lpszUrlName
.text:003A3406 call ds:DeleteUrlCacheEntryW
我想获得所有 API 调用(_snwprintf、UrlMkSetSessionOption、DeleteUrlCacheEntryW 等)。可以使用以下 IDAPython 函数获取其中的大部分内容。
def get_apis(func_addr):
calls = 0
apis = []
flags = GetFunctionFlags(func_addr)
# ignore library functions
if flags & FUNC_LIB or flags & FUNC_THUNK:
logging.debug("get_apis: Library code or thunk")
return None
# list of addresses
dism_addr = list(FuncItems(func_addr))
for instr in dism_addr:
tmp_api_address = ""
if idaapi.is_call_insn(instr):
# In theory an API address should only have one xrefs
# The xrefs approach was used because I could not find how to
# get the API name by address.
for xref in XrefsFrom(instr, idaapi.XREF_FAR):
if xref.to == None:
calls += 1
continue
tmp_api_address = xref.to
break
# get next instr since api address could not be found
if tmp_api_address == "":
calls += 1
continue
api_flags = GetFunctionFlags(tmp_api_address)
# check for lib code (api)
if api_flags & idaapi.FUNC_LIB == True or api_flags & idaapi.FUNC_THUNK:
tmp_api_name = NameEx(0, tmp_api_address)
if tmp_api_name:
apis.append(tmp_api_name)
else:
calls += 1
return (calls, apis
输出
Python>get_apis(here())
(18, ['UrlMkSetSessionOption', 'DeleteUrlCacheEntryW', 'URLDownloadToFileW', 'GetModuleFileNameW', 'CreateProcessW', 'Sleep', 'ExitProcess', 'RtlGetLastWin32Error', 'byte_3A3E45', 'RtlGetLastWin32Error'])
我遇到的问题call esi ; _snwprintf是不存在。我知道我可以使用回溯来找到 ESI 的价值,但我想找到另一种方法。是否有更可靠的技术来获取函数中的所有 API?类似的数据存在于邻近浏览器中。