windows - PE-从功能导出中区分数据

标签 windows debugging portable-executable ida

我试图在IDA中找出一种方法,哪些导出是数据导出,哪些是实函数导出。

例如,让我们看一下Microsoft的msftedit.dll的导出条目:
enter image description here

虽然CreateTextServices是真正的导出函数:
enter image description here
IID_IRichEditOle是数据导出,而IDA未能意识到这一点,将数据作为代码插入:
enter image description here

有人知道区分这两者的可靠方法吗?帮助将不胜感激。

提前致谢。

最佳答案

对于每种导出,都没有完全可靠的方法来执行此操作。

每次导出仅在可执行文件中指定一个偏移量-从逻辑上讲,任何引用该可执行文件的其他代码都可以将其视为代码或数据。

正如您提到的,您几乎可以在所有情况下提出启发式方法来检测导出的类型,但是很容易提出对任何给定启发式方法都无效的反例。以您建议的规则为例:

The exported entry will be considered a valid exported function if there is a ret instruction in the function, and there are more than <min> valid instructions, and IDA recognizes the function's calling convention.



假阴性:您可能具有使用tail call optimization并以jmp指令而不是ret指令结尾的函数。任何短函数也将失败。可以将IDA混淆为不将代码视为函数的几种方式。

误报:内存中可能有一个字符串,紧接着是C3C2,例如db 'BACKGAMMON0',0,0C3h-从逻辑上讲,它可以作为带ret但不带参数的有效11指令函数分解。

当您认为导出可以在逻辑上同时视为代码和数据时,这些线会更加模糊:想象一下,将导出时的字节序列复制到动态分配的内存中(甚至可能在另一个进程中),以后再执行作为代码。

如果IDA认为是代码,则可能合理的建议是仅信任IDA并将导出视为代码。 IDA的很大一部分功能是自动猜测数据的逻辑类型,通常它非常擅长。如您所显示,有时是错误的。但是无论如何您都无法获得100%的准确性。您能做的最好的事情就是在假阴性和假阳性之间取得平衡。

该问题的不确定性证明:

导出是否将作为代码执行尚不确定。导出是否将被读取为数据也是不确定的。由于我们不能保证两者都是正确的,因此不可能区分看似模棱两可的情况。

证明:假设我们有一个oracle A(P,I,E),如果程序P(包括其所有依赖项)执行(或读取)导出E(从P执行过程中加载的任何DLL)并带有“input”(外部),则返回oracle 1状态)I。否则,它返回0。

让我们构造一个最小程序Z(P,I,E),当且仅当E返回0时,该程序才执行(或读取)导出A(P,I,E)(已将其DLL加载到地址空间中)。

现在考虑Z(Z,I,E)的结果:

如果Z(Z,I,E)执行(或从中读取)export E,则A(Z,I,E)将返回1。但是Z(Z,I,E)定义为不访问导出E,除非A(Z,I,E)返回0。这是矛盾的。

如果Z(Z,I,E)不执行(或不读取)export E,则A(Z,I,E)将返回0。但是Z(Z,I,E)定义为当E返回0时将访问导出A(Z,I,E)。这是一个矛盾。

因此,我们最初对oracle A(P,I,E)存在的假设被证明是错误的。

但是通过仪器可以做得更好...

根据您要解决的确切问题,您可以在运行时确定哪些导出是有效函数。

例如,您可以编写一个应用程序,将应用程序debugs进行分析,并将guard pages放置在每个包含您要 Hook 的导出的页面上。这意味着,每当页面被访问(执行/读取/写入)时,都会引发异常,调试器程序将获得控制权。

调试器可以检查程序上下文,以查看进行了哪种类型的访问以及它是否与导出有关。如果访问是尝试执行导出,则可以在将控制权返回给程序之前执行某些 Hook 功能。否则,它可能只是将控制权返回给程序。

在任何一种情况下,PAGE_GUARD修饰符在每次异常后都会被取消,因此您需要每次都将其放回原处。

毫不奇怪,这会使您的程序的执行非常慢,因为对包含导出的任何页面的任何R/W/X访问都会导致昂贵的context switch -这很可能包括大多数指令的执行,而这些指令是您导出的函数,以及与它们无关的其他几个函数。

您可以对其他检测工具采用类似的方法,例如Pin

请注意,您可能无法通过检测获得有关每个导出的用法的信息。这是因为您可能需要确定导致程序访问每个导出的所需输入/外部状态,以了解该导出是用作代码还是用作数据(如果有的话)。

还要注意,执行和读取(甚至是写入)访问都可能在同一导出上发生。

关于windows - PE-从功能导出中区分数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40338682/

相关文章:

windows - 在 Windows 中查找 USB 以太网链路本地 IP 地址

javascript - 您使用什么工具来调试 Javascript?

c++ - PE文件中的MZ签名有什么用?

Windows 10 通过鼠标悬停延迟激活窗口?

c++ - 抑制 system() 输出

windows - 找不到用于 apache/windows 的 mod_wsgi

c++ - 我如何知道 IMAGE_THUNK_DATA 数组何时终止?

c - C 程序中的 Seg 错误

html - Internet Explorer 表单输入问题

c - 在压缩的 PE 中,数据部分的虚拟大小必须与原始大小匹配吗?