查找函数中的所有 API 调用

逆向工程 艾达 蟒蛇
2021-06-17 12:41:10

有没有办法通过 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?类似的数据存在于邻近浏览器中。

1个回答

一个扫描注册调用并打印它们的 idc 脚本
(这个脚本使用文本搜索,因为 ida 通配符似乎对屏蔽没有用,
即我们不能像FF D那样搜索二进制 这样所有的二进制序列“ff d0”,“ff d1","ff d2"等可以一次搜索)

#include <idc.idc>
static main (void) {
  auto offset,count;
  count = 1;
  offset= MinEA();
  while(offset != BADADDR) {
    offset = FindText(offset+2,3,0,0,"call    e");
    Message(
    "%03d %08x %s %s %s\n",
    count++,
    offset,
    GetMnem(offset),
    GetOpnd(offset,0),
    Name(Dfirst(offset))
    );
  }
}

calc.exe xp sp3 x86 上的结果

Compiling file 'C:\Documents and Settings\Admin\My Documents\callreg.idc'...
Executing function 'main'...
001 01001682 call esi CharNextW
002 010016ba call esi CharNextW
003 01001713 call esi 
004 01001740 call esi 
005 0100178b call esi 
006 010017b4 call esi 
007 01001a74 call esi GetProfileStringW
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
069 01007b5d call esi LoadLibraryA
070 01007ba0 call eax 
071 0101248a call edi GetModuleHandleA
072 010125e1 call edi GetModuleHandleA
073 ffffffff   
其它你可能感兴趣的问题