针对Windows下闭源二进制可执行文件热补丁的研究

2021-10-29 12:18陈炜昊于子洋
网络安全技术与应用 2021年10期
关键词:二进制补丁调用

◆陈炜昊 于子洋

针对Windows下闭源二进制可执行文件热补丁的研究

◆陈炜昊 于子洋

(中国矿业大学 计算机科学与技术学院 江苏 221116)

随着计算机科学技术的飞速发展,越来越多的厂商与作者为保护程序算法知识产权,选择将自己的代码程序以闭源的形式发布,导致很多闭源软件存在不同程度的安全问题。如何对已经产生安全事件的闭源二进制文件进行修复已逐渐成了安全应用的重要课题,本文就此问题进行探讨,以Windows x86架构为框架,详细分析了文件静态补丁技术的可行性,并给出了针对此问题的基本解决方案,最终达到在无源码的情况下对文件漏洞修复的目的。

Windows x86;相对虚拟地址;动态链接库

1 引言

随着计算机信息技术的快速发展,各行各业的人都加入了软件开发的行列,他们会将自己的专业知识封装成各种各样的软件,供有需求的人们去使用。开发出来的软件主要分为两种:开源软件与闭源软件。闭源软件无法在源代码的层级上对程序进行修改,删除,更新等操作。由于开发人员没有接触过系统的安全教育以及如何进行底层CVE的发掘,导致大多数的闭源软件都存在安全隐患。主要包括危险函数的误用导致的栈溢出、内存管理释放部分缺失导致的堆溢出等隐患。

本文主要是对Windows下闭源二进制可执行文件的修补方法进行研究,目的是修复无人维护的闭源软件的安全问题和在官方未发布补丁时的1Day漏洞。

2 汇编级别的简单函数替换

Windows自带的的可执行文件格式是PE文件格式。PE文件中的内容会被划分成一个个小块,这一个个小块就是Section(节)。Windows可执行程序拥有一个独特的机制--导入表与导出表。导入表与导出表中保存了PE文件中调用的所有动态链接库的函数,以及这些函数来自哪些动态链接库。Windows加载器在运行PE时会将导入表中声明的动态链接库一并加载到进程的地址空间,并修正指令代码中调用的函数地址。这个机制的存在保证了PE文件中的函数可以被重复调用。导入表与导出表机制决定了本小节需要分为以下两种情况加以讨论。

(1)导入表导出表已有函数

PE文件的导入表与导出表中存在相应函数,可以直接对函数进行调用,对更加安全的函数进行重复调用。在可执行文件调用了危险函数时,可以直接在原text段进行汇编的修改从而达到修复程序的目的。由于不同的函数有不同的参数个数种类等独特的用法,所以一般情况下需要对函数前后的调用进行部分调整。比如程序中调用了一个gets函数,这个函数会导致堆栈的溢出,为程序带来不可控的风险。而程序导入表与导出表中加载了read函数,此时需要使用read函数替换gets函数。对比两个函数原型,可知两个函数的调用参数不同,所以不可以直接进行简单的替换,需要对函数传递进行适当的调整。在调整部分参数后,才可以使用read函数对gets函数进行整体替换。

(2)导入表导出表未加载函数

对于导入表和导出表未加载同类型可替换的函数,一般在不借助其他方法的情况下,只能进行小修小改。危险函数在没有同等功能的其他函数可以进行替换的情况下,只能对本身已有函数的参数进行修改,使其尽可能安全可靠。比如printf函数没有使用规范的格式化字符会导致格式化字符串的漏洞,从而泄露栈中敏感信息。修复printf漏洞时可以在参数传递处加入相应的格式化字符参数,以提高整体程序的稳定性。相似的漏洞还有read函数造成的单字节溢出等漏洞。

3 汇编级别的函数代码重写

本小节主要针对一些特定的函数修复,这些函数通常自身存在一些安全隐患,但是功能比较简单,一般可以直接通过几条简单的汇编语言函数功能重现。比如stcopy函数,它在程序中很容易产生栈溢出漏洞,本节就将以它作为例子简述函数的汇编代码重写方法。虽然Microsoft提供了更安全的strcpy_s()函数供编程人员调用,但是一些老旧程序并没有载入这个函数,所以不能采取上节中的方法对stcopy函数进行直接替换。所以为了让程序正常工作并不引发错误,需要对函数进行重写以实现拷贝的功能。拷贝函数重写如图1。

图1 拷贝函数重写

重写函数汇编字节码字节数往往会多于原函数,额外空间的获取就成了研究的关键。本节主要探讨两种获取额外空间的方法,通过同义指令替换获得额外空间与额外添加新段区。

(1)同义指令替换

由于编译器的原因,每一个PE文件都会出现一些不那么简洁的汇编指令。如moveax,0等需要传递常数的汇编指令,这类指令一般可以被简化修改为xoreax,eax,进而为整个二进制文件节省出空间以便于插入补丁。

(2)额外添加新段区

在所需空间很大的情况下,可以考虑为程序添加新的段区。新添段区的一般需要三步,首先需要PE头部增添块头,其次为添加的区块头添加数据段,最后修正映像文件即可。这种方法可以为PE文件快速创建一个空的区块段,以便填入补丁代码,更改程序流程。

4 源码级别的外部.dll文件引用

当补丁代码过于复杂时,可以通过编写第三方dll并将动态链接库注入二进制文件中的方式来替换危险函数。基本注入流程如图2所示。

程序调用动态链接库需要先使用LoadLibrary函数对指定的动态链接库进行加载,然后再使用GetProcAddress获取目标链接库中相关函数的地址。这两个函数存在于Kernel32.dll中,绝大多数Windows程序都会加载ntdll.dll和kernel32.dll,故我们首先获取kernel32.dll的基址,相关汇编代码如图3所示。

图2 基本注入流程

图3 相关汇编代码

图4 完成函数的调用

由于函数名字换算成ASCII码后会占用比较大的空间,这里采用hash的方式对目标函数进行查找,在成功加载动态链接库并获取函数的地址后,就可以直接对函数进行调用了。在目标调用处插入调用代码,即可完成函数的调用,如图4。

将上述汇编编译成二进制字节码后,就可对目标程序进行注入,方法与第二三小节基本相同,在函数拥有足够的空间时,可选择在源码处进行动态链接库的加载和函数的调用,空间不足时,可为程序添加必要的段区。

5 结束语

本文主要探讨了有关闭源二进制可执行文件的静态补丁的基本理论方法,主要应用于未加密Windows x86的可执行文件。对于动态加密,程序的自校验程序还需要做进一步的研究。

[1]何迎生,段明秀. 32位Windows系统下的PE文件结构及其应用[J]. 吉首大学学报(自然科学版),2003(01).

[2]刘科. 计算机科学技术的发展现状及发展趋势展望 [J]. 信息记录材料,2020,21(07).

[3]昝道广. 计算机科学技术的应用现状及其发展前景探析 [J]. 通讯世界,2017(6):133.

[4]李晨燕. 计算机网络信息安全问题策略探讨[J]. 电子世界,2020(24).

[5]王众魁. 探索计算机信息网络安全技术及发展方向[J].电脑知识与技术,2021,17(08).

猜你喜欢
二进制补丁调用
用二进制解一道高中数学联赛数论题
核电项目物项调用管理的应用研究
有趣的进度
二进制在竞赛题中的应用
健胃补丁
绣朵花儿当补丁
补丁奶奶
基于系统调用的恶意软件检测技术研究
二进制宽带毫米波合成器设计与分析
大病医保期待政策“补丁”