我正在尝试获取PE文件的IAT。我的计划最终是覆盖一些值,以便我可以钩一些东西来帮助解包,等等。我目前在第4位,那对我来说有些模糊。我能够获得一个指向DataDirectory数组中条目的指针。我选择第13个条目是因为从我的研究http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms680305%28v=vs.85%29.aspx看来,这将使我进入IAT 。我不确定自己是否走对了,因为此DataDirectory的大小为size = 0且virtualaddress =172。virtualsize 172是否为必须添加到某些基址的偏移量?我只使用一个简单的C程序,没有打印“ Hello World”的调试信息。任何帮助是极大的赞赏。不确定显示多少代码会对我的方法有所帮助,但是我将在下面发布相关部分。任何帮助表示赞赏。谢谢!

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]


#1 楼

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

以IDA中的以下代码为例:

FF 15 44 60 03 01    call    ds:GetVersion


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

99%的时间中,所有IAT将在内存中背对背,因此您应该能够只知道一个IAT条目地址就能找到所有IAT。因为如果反汇编的代码已经打包,则依赖于PE导入表将失败,而上述方法将适用于打包和非打包的样本。

#2 楼

注意:仅当从磁盘读取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有疑问,请查看用法示例。

评论


如果反汇编的代码已经打包,则将失败。查找由代码本身生成的IAT引用更加可靠。

–詹森·格夫纳(Jason Geffner)
13 Sep 26 '21:54



@JasonGeffner你是对的,我没有意识到他指的是内存句柄。也许下次用户在此处提出问题时,他将添加更多详细信息,例如其他问题...stackoverflow.com/questions/19018906/…

– alexanderh
2013年9月26日23:00