加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows – PE – 区分数据与函数导出

发布时间:2020-12-14 02:25:14 所属栏目:Windows 来源:网络整理
导读:我正试图找到一种方法来弄清楚IDA中哪些出口是数据输出,哪些是实际功能输出. 例如,让我们看看Microsoft的msftedit.dll的导出条目: 而CreateTextServices是一个真正的导出函数: IID_IRichEditOle是一个数据导出,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混淆为不将代码视为函数.

误报:内存中可能有一个字符串紧跟一个C3或C2,如db’BACKGAMMON0′,0C3h – 这可以逻辑地反汇编为有效的11指令函数,带有ret和无参数.

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

如果IDA认为它是代码,也许合理的建议就是信任IDA并将导出视为代码. IDA的很大一部分功能是自动猜测数据的逻辑类型,而且它通常很擅长.如你所示,有时它是错的.但无论如何,你无法获得100%的准确性.你能做的最好的是假阴性和假阳性之间的平衡.

证明这个问题的不确定性:

导出是否将作为代码执行是不可判定的.导出是否将被读取为数据也是不可判定的.由于我们不能保证其中任何一个都是真的,因此区分看似模棱两可的案例是不可能的.

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

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

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

如果Z(Z,E)执行(或读取)导出E,则A(Z,E)将返回1.但Z(Z,E)被定义为不访问导出E,除非A( Z,E)返回0.这是一个矛盾.

如果Z(Z,E)没有执行(或读取)导出E,那么A(Z,E)将返回0.但是Z(Z,E)被定义为使得它将访问导出E当A(Z,E)返回0时.这是一个矛盾.

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

但你可以通过仪器做得更好……

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

例如,您可以编写一个应用程序,其中debugs是您要分析的程序,并将guard pages放在包含您要挂钩的导出的每个页面上.这意味着,无论何时页面访问(执行/读取/写入),都会引发异常,并且调试程序将获得控制权.

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

在任何一种情况下,PAGE_GUARD修饰符在每次异常后都会被提升,因此您每次都需要将其恢复.

不出所料,这会使您的程序执行速度非常慢,因为对包含导出的任何页面的任何R / W / X访问都会导致代价高昂的context switch – 这可能包括执行导出过程中的大多数指令功能,以及其他几个与它们无关的功能.

您可以采用与其他仪器工具类似的方法,例如Pin.

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

另请注意,执行和读取(甚至写入)访问都可能发生在同一个导出中.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读