使用 Python CTypes 访问 IAT

逆向工程 Python 我在
2021-06-17 06:52:49

我正在尝试访问 PE 文件的 IAT。我的计划最终是覆盖一些值,这样我就可以挂钩一些东西来帮助解包等。我使用这篇文章https://stackoverflow.com/questions/7673754/pe-format-iat-questions作为指南。我目前排在第 4 位,这就是对我来说事情变得有点模糊的地方。我能够获得一个指向 DataDirectory 数组中的条目的指针。我选择了第 13 个条目,因为根据我的研究http://msdn.microsoft.com/en-us/library/windows/desktop/ms680305%28v=vs.85%29.aspx看起来那会带我去 IAT。我不确定我是否在正确的轨道上,因为这个 DataDirectory 的值是 size = 0 和 virtualaddress = 172。172 的 virtualsize 是必须添加到某个基地址的偏移量吗?我只是在使用一个没有打印“Hello World”的调试信息的简单 C 程序。任何帮助是极大的赞赏。不确定显示代码对我的方法有多大帮助,但我会在下面发布相关部分。任何帮助表示赞赏。谢谢!

pDOSHeader = ctypes.cast(hModule, ctypes.POINTER(IMAGE_DOS_HEADER)).contents

e_lfanew_offset = pDOSHeader.e_lfanew

offset_to_NTHeaders = e_lfanew_offset + hModule
pNTHeaders = ctypes.cast(offset_to_NTHeaders,ctypes.POINTER(IMAGE_NT_HEADERS)).contents

pImage_NT_Headers = pNTHeaders.OptionalHeader
pDataDirectory = pImage_NT_Headers.DataDirectory
pDataDirectory_IAT = pDataDirectory[13]
2个回答

不要依赖 PE 数据目录中的 IAT 条目来确保准确。查找 IAT 的唯一真正准确的方法是查找从反汇编代码到静态导入的 API 函数的实际调用。

我们以 IDA 中的以下代码为例:

FF 15 44 60 03 01    call    ds:GetVersion

的实际反汇编FF 15 44 60 03 01call dword ptr ds:[1036044h],但 IDA 知道这指向GetVersion(),因此它显示了“漂亮”的反汇编。在这个例子中,地址1036044h实际上是GetVersion()kernel32.dll 的 IAT 中 的条目的虚拟地址因此,您现在可以在虚拟地址附近的内存中“向上”和“向下”1036044h查找,以找到 kernel32.dll 的 IAT 的开头和结尾。

99% 的情况下,所有 IAT 将在内存中背靠背,因此您应该能够找到所有 IAT,只知道一个 IAT 入口地址。

我推荐上面的方法,而不是依赖 PE 导入表中的内容,因为如果反汇编的代码已经打包,依赖 PE 导入表将失败,而上述方法将适用于打包和非打包样本。

注意:仅适用于从磁盘读取 PE

如果您使用pefile而不是 Python ,则可以简化您的代码ctypes这是用于获取某些 API 名称的十六进制地址的快速脚本。

import pefile

try:
        pe = pefile.PE(f)
    except:
        print 'could not load file...exiting'
        return
ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint
ep_ava = ep+pe.OPTIONAL_HEADER.ImageBase
API_addr = None
for entry in pe.DIRECTORY_ENTRY_IMPORT:
      for imp in entry.imports:
          if 'SOME_API' in imp.name:
               API_addr = hex(imp.address).lower()

如果您对pefile查看使用示例有任何疑问