# 大创项目资料征集 ## DBI **Dynamic Binary Instrumentation(动态二进制插桩技术)** 动态二进制插桩(dynamic binary instrumentation ,DBI)技术是一种通过注入插桩代码,来分析二进制应用程序在运行时的行为的方法。 动态二进制插桩技术,可以在不影响程序动态执行结果的前提下,按照用户的分析需求,在程序执行过程中插入特定分析代码,实现对程序动态执行过程的监控与分析。目前,应用广泛的动态二进制分析平台有Pin,DynamoRIO和Frida等。 ## Anti-DBI-instruction ![](https://i.imgur.com/pc0MfES.png) ### 技术相关文章 Reducing the Attack Surface of Dynamic Binary Instrumentation Frameworks http://webdiis.unizar.es/~ricardo/files/papers/SRF-MICRADS-19.pdf https://webdiis.unizar.es/~ricardo/files/papers/SRF-DTRAP-21.pdf ### 基于JIT编译的反插桩技术 JIT(Just_In_Time),即时编译,是一种动态编译技术,也是DBI的重要技术特征。与我们熟知的静态编译,即程序全部翻译为机器码后再载入运行不同,动态编译是边运行边翻译。 当我们在JIT模式下对程序进行JIT编译时,原始汇编代码作为不会执行的参考副本加载到内存中。真正执行的是经过JIT编译、位于代码缓存(code cache)中、进行插桩变换后的指令。 基于JIT具备的一些特性,我们可以从以下几个方面检测插桩是否正在进行。 #### 内存页权限WX WX即写入、执行属性,由于是动态编译,所以插桩的程序需要具备:将JIT编译后的指令**写入**内存而后**执行**这样的能力。 所以,对于插桩后的程序而言,其属性内存页的数量必然高于一般的程序。 基于JIT的这个特性,我们可以通过扫描整个进程的地址空间,计算出标记为RWX属性的内存页数量。如果得到的数量明显高于一般的程序,则基本可以判断,该程序存在插桩分析。 #### Memory Allocation 基于上一点当中提到的特性,即动态编译需要使用RWX的内存页来实现指令的写入与执行,我们不难想到:DBI平台需要通过申请内存来满足这一需求。 再者,所有的内存申请,都要通过底层的ZwAllocateVirtualMemory函数调用实现。因此,我们可以通过记录该函数的调用次数,然后与未插桩情况下的调用次数相比较,以此判断插桩是否进行。 #### DLL HOOK DBI需要使用HOOK函数,利用JIT技术,在某些函数的入口处插入jmp指令(即 Hook)。在pin插桩之后,函数的入口就会发生变化 存在类似情况的函数包括:KiUserApcDispatcher、KiUserCallbackDispatcher、KiUserExceptionDispatcher、LdrInitializeThunk 因此,我们也可以通过检测这些函数入口的变化,达到检测插桩分析是否存在的效果。 ### 基于代码缓存的反插桩技术 在DBI平台下,原始代码只是驻留在内存中作为参考副本,不会执行。真正执行的是代码缓存中的代码。 #### EIP检测: 在插桩状态下的EIP,将会指向代码缓存的内存区,而不是原程序所在的内存地址。这也就导致,插桩状态下的EIP将会与原始代码中预期的不同。 所以,我们可针对这个特性进行检测。假如我们获得了插桩状态下程序运行时时的真实EIP值,那么就可以与预期的原程序下的EIP值进行比较,若二者不相同,说明该程序处于插桩状态。 #### 自修改代码: 各类病毒躲避查杀的时候,一种常用的手段就是在程序动态运行期间,修改自身的指令,即自修改代码。 若程序处于动态插桩状态下,这种方法将会修改原代码,导致在代码缓存区真正执行的指令(未更改),会与原指令不同。所以通过检测执行代码是否存在差异,也能够判断程序是否处于插桩状态 ### 基于环境特征的反插桩技术 #### PE特征 pin平台在插桩的时候,会将pinvm.dll注入到进程内。因此,pinvm.dll内包含的特殊字符串、汇编代码片段、导出函数和section name等特征,均可以作为检测的依据。 #### 父进程 由于我们研究的目标进程是由pin平台启动分析的,因此目标进程会是pin平台的子进程。 也就是说,目标进程存在来自pin平台的父进程,因此,我们可以通过检测父进程来判断插桩平台是否存在。 ### 其他反插桩技术 #### 运行时开销 虽然DBI平台都在努力提高插桩分析的性能,但是插桩分析势必会增加程序运行时的开销。而开销的增加则可以从程序执行的时间上体现出来。 因此,我们通过NtQueryPerformanceCounter、GetTickCount、timeGetTime等API函数或者KUSER_SHARED_DATA数据结构,可以获取到Windows Time,通过分析执行的时间,我们就能判断插桩平台的存在。 ## DBI介绍 ### 介绍(一) 以下介绍来自[基于QEMU的动态二进制插桩技术](https://kns.cnki.net/kcms/detail/detail.aspx?filename=JFYZ201904006&dbcode=CJFD&dbname=CJFD2019&v=_wjlLW_iW3AyKiyllMfiD_dD3rM5xZGu7IIsapl-1t2zHcx4WSZuQ2sY7PMV_2GY) ​ 动态二进制插桩, 就是在执行客户机程序的流程中, 通过添加、修改和删除机器码等操作(引用Du M, Hill J H.Realtime dynamic binary instrumentation[D].Indianapolis, Indiana:Purdue University, 2016), 支持监控客户机软件的一种程序仿真运行技术.在二进制插桩领域, 通常以基本块 (basic block) 为单位进行插桩, 完成基本块运行信息收集, 生成程序分支 (arc) 和程序流图, 分析程序动态运行信息.所谓基本块, 就是程序运行中最基本的指令序列.在这个指令序列中, 所有指令顺序执行.停止语句和转向语句只能是基本块的最后1个语句.分支 (arc) 是指基本块之间的控制流, 它连接程序中所有有效基本块形成程序流图.分支表示基本块之间的结构关系, 通过分支可以知道程序在执行完基本块的所有语句后会转移到哪一个基本块继续执行.程序流图是程序结构的图形表示.基本块是流图中的节点, 程序的所有基本块组成了程序流图的节点集, 程序第1个语句所在的基本块称为首节点.把基本块之间的控制流向作为节点之间的有向边集合.对程序流图来说, 节点就是基本块, 代表了程序的执行语句;有向边就是分支, 代表了程序的控制流;首节点就是程序的起始点. ​ 依据插桩技术不同, 基本块插桩可以在编译时进行, 也可以在运行时进行.例如GNU (GNU’s not Unix) 的覆盖率统计工具Gcov就是通过编译选项在基本块上进行二进制插桩, 以实现对软件的覆盖统计.当插桩后的程序运行时, 动态填充程序内的基本块、分支和程序流图.当程序运行结束时, 将基本块、分支和程序流图输出到文件中, 最终由Gcov完成动态分析.而Pin, Valgrind, DynamoRIO等工具则是通过动态二进制翻译技术完全控制目标二进制程序的执行.它们在运行目标二进制程序时进行二进制翻译, 发现目标程序中的基本块并进行插桩, 最后在程序结束时给出程序运行动态信息.目前这些工具存在较大的局限性, 例如它们都只能完成应用级程序的动态分析, 还没有一种工具可以完成系统级动态二进制插桩, 由此可见, 系统级程序的动态二进制分析对二进制插桩技术来说是一个巨大的挑战. ![图片.png](https://s2.loli.net/2022/03/09/QjeGwSfat2R6nsH.png) ### 介绍(二) 以下介绍来自[基于控制流分析的隐藏代码动态捕获方法](https://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJC201121010&dbcode=CJFD&dbname=CJFD2011&v=XJWKtoFrmuoekkB0l7EEqIKLGaRPyPA0jU9RwZuHYg2LJpK9JNahMbDVmL3IUCgG) ​ 动态二进制插桩 (Dynamic Binary Instrumentation, DBI) 技术是目前动态二进制分析工具普遍采用的技术, 即在不影响程序执行结果的前提下, 根据用户分析的需求, 通过在程序动态执行过程中插入分析代码, 监视程序的执行过程。动态插桩有2种实现方式: (1) 修改现存的指令, 将其替换为一个转向包含原代码以及植入代码过程的跳转指令。这种方式不适用于变长指令, 因为变长指令可能与跳转指令的长度不匹配。 (2) 将原代码拷贝至一个单独的内存块中并添加插桩代码到这份拷贝中。由于需要对插桩版本中具有绝对目标的代码进行重定位, 因此需要对这些指令进行特殊处理。 ​ 动态二进制补丁码工具DynInst(注释 Buck B, Hollingsworth J K.An API for Runtime Code Patching[J].The International Journal of High Performance ComputingApplications, 2000, 14 (4) :317-329.) 是一款支持多操作系统的应用程序接口 (Application Programming Interface, API) , 可以实现动态二进制代码的插桩, 其插桩形式如图1所示。 ![图片.png](https://s2.loli.net/2022/03/09/hmzaSAfclDWp4Kw.png) ​ 图1 DynInst插桩示意图 ​ DynInst是平台无关的, 它建立在对可执行程序及状态抽象的基础上, 如Points (插桩点) 、snippets (插桩代码片段) 、进程、映像。DynInst程序结构如图2所示。其中, Mutator和Mutatee为2个主要进程。Mutator调用DynInst API完成对被调试进程Mutatee的控制与插桩。DynInst API库通过DynInst库及系统提供的调试接口完成运行时编译以及修改等工作。DynInst run-time library是在创建受控进程Mutatee时动态加载的, 包含了插桩代码运行所需的支持代码。 ![图片.png](https://s2.loli.net/2022/03/09/hlEugtPoIC5Msm8.png) 图2 DynInst程序结构 ### 用于漏洞挖掘 [基于二进制动态插装程序执行路径追踪](https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CJFD&filename=JSYJ201502036&v=MTc3MTNZOUdZb1FLREg4NHZSNFQ2ajU0TzN6cXFCdEdGckNVUjdpZlpPWm1GQ2ptV3J2Skx6N1NaTEc0SDlUTXI=&uid=WEEvREcwSlJHSldSdmVqMDh6cEFHWXFrR2toSlN4Yjk4L1pwVWZENWJBOD0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!) [基于执行路径的模糊测试漏洞挖掘方法](https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CJFD&filename=TXWL202001035&v=MjgyMDBNVFhjWXJHNEhOSE1ybzlHWVlRS0RIODR2UjRUNmo1NE8zenFxQnRHRnJDVVI3aWZaT1ptRkNqbVZiN0w=&uid=WEEvREcwSlJHSldSdmVqMDh6cEFHWXFrR2toSlN4Yjk4L1pwVWZENWJBOD0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!) [基于动态插桩的C/C++内存泄漏检测工具的设计与实现](https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CJFD&dbname=CJFDLAST2015&filename=JSYJ201506031&uniplatform=NZKPT&v=TTvzf204r-JqHH8nzi7iSp7zg9fTwvfqHn28kh83JhnsWPfOmD7JmtqcA255_WIX) ### 挖掘工具: [QBDI](https://github.com/QBDI/QBDI)(github项目) 用动态二进制插桩平台 Pin ### 用于攻击检测 [一种基于DBI的ROP攻击检测](https://kns.cnki.net/KXReader/Detail?invoice=K%2FiqdB7%2FLijd7%2Byzp1Xabqyr%2Bfdvp0jYLO8vEOsCV9SEKThfBcKH8qqbzG13D7WVj5h%2FeB0sqHN4PifI6%2BPZVXAdRg7EtcW8%2FfuXJqq%2FeqF%2F%2FMr22eWYLb4MTTs%2BbCNgqWlc55aWzeVF7%2BZTBQqz11RyBD8Ld1Fdpy0MwdHYXMA%3D&DBCODE=CJFD&FileName=JSJA201209030&TABLEName=cjfd2012&nonce=8217891544604A3195A4C55EA7ABC857&uid=&TIMESTAMP=1646833050410) [基于动态二进制插桩的密钥安全性检测](https://kns.cnki.net/kcms/detail/detail.aspx?filename=WXAQ201711006&dbcode=CJFD&dbname=CJFD2017&v=OQa0EA1VUjG5sH56bT5aW1Zt_eHqP80nD3rtuuO-EGP_pPabHDuy3Nq8Gc33QjDK) #### DBI的研究现状和研究意义 ### 研究现状 几年来,我们有了动态代码分析的替代方案:动态二进制检测 (DBI) 框架。这些在信息安全领域得到了普及,并且它在逆向工程任务中的使用正在增加。如今,我们拥有基于 DBI 的工具,使我们能够执行不同类型的工作,例如隐蔽调试、shellcode 检测、污点分析、指令跟踪、自动解包和自修改代码分析等。 DBI 技术在不同的研究社区中得到了广泛的普及,特别是在编程语言、软件安全和系统领域。他们得到了业界的大力支持,英特尔和谷歌等公司积极为社区开发 DBI 系统。 DBI 的**流行来自几个因素**。首先,易于使用的工具:添加监控序列,用户无需担心上下文保存和二进制代码操作,而只需注册指令类的回调(例如,控制传输、数据移动)。该引擎抽象出特定架构的特性,并为其编译有效的分析代码。归根结底,在大多数情况下,研究人员不需要成为 DBI 专家就能够编写体现他们想法的 DBI 工具。 ## 目前的DBI产生的一些问题 最近的一项工作观察到与 DBI 系统有关的透明度有两种含义。对于 DBI 架构师来说,透明度意味着确保程序在未检测的本地环境中完全一样地执行,保持与其他应用程序的互操作性。1 对于安全研究人员来说,透明度还意味着对手寻找执行环境的异常特征的可能性:而这些不会改变正常程序的语义,但是它们可以进行检测尝试。[这个也可以作为一个反插桩的切入点] 为了更好地理解为什么会首先出现透明度问题,我们简要概述了大多数现代 DBI 系统的工作原理。 DBI 引擎在二进制、用户空间代码上运行,并以进程级虚拟化方式包装其执行:引擎不直接执行原始指令;相反,它们会经历一个动态编译过程。即 (JIT) 编译器在原始程序指令将要执行时分析、检测和编码为可直接执行的形式。 JIT 在跟踪的粒度上运行,最终填充用于避免频繁重新编译和提高性能的代码缓存。此外,还可以在运行时中进行诸如跟踪链接之类的代码优化。 最值得注意的是,该引擎致力于提供架构状态透明度:它重写内省操作的输出,以向程序呈现在本机执行中可观察到的相同地址和数据。这意味着,例如,每当程序检查指令指针时,引擎都应该公开与当前从代码缓存中执行的 JIT 指令(真正的 EIP)相对应的 .text 地址。 [万恶之根。] 在这个特色设计中,我们可以指出透明度的三个主要关注点: 共享地址空间:被分析的应用程序和 DBI 引擎在相同的地址空间和相同的权限级别上运行,这为检测甚至颠覆企图打开了大门 [9]; 操作系统资源争用:应用程序和引擎可以访问同一组资源,例如文件描述符、内存映射文件、物理内存、信号等; JIT 编译的开销:与本机执行相比,代码部分的时间行为会减慢,但也会受到动态(重新)编译选择的变化。 虽然从安全的角度来看,共享地址空间和操作系统资源是 DBI 的内在限制,但同时它在实施研究工具时也代表了优势。例如,DBI 工具可以直接查询操作系统,以便在给定时间检索打开句柄或分配的堆区域的列表,而从虚拟机监视器运行的工具则需要一个可以说更复杂的检查过程。 [以上的研究现状和问题来自于 “Evaluating Dynamic Binary Instrumentation Systems for Conspicuous Features and Artifacts” 作者:Authors: Daniele Cono D’Elia, Lorenzo Invidia, Federico Palmaro, Leonardo Querzoni] ### DBI的历史背景 根据维基百科[1]与IBM的介绍[2],插桩是一种测试程序性能、检测错误、获取程序执行信息的技术。 根据百度百科[4],插桩技术最早由J.C. Huang提出[3]。在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针(probe),即添加一些代码,获得程序的控制流和数据流信息。例如通过自动工具或手动,在函数执行前后插入读取计时器的代码,获取函数执行时间。 动态仪表工作: 1. Pansy Arafa、Hany Kashif 和 Sebastian Fischmeister。 Dime:使用基于速率的资源分配的时间感知动态二进制检测。在诉讼中 第 13 届嵌入式软件国际会议 (EMSOFT),蒙特利尔, 加拿大,2013 年 9 月 [17]。 – 共同设计的 DIME; – 开发了 DIME 的三个实现; – 分析实验结果; – 共同进行案例研究; – 写了论文的一部分。 2. Pansy Arafa、Hany Kashif 和 Sebastian Fischmeister。时间感知动态二进制检测(期刊版)。在提交中。 – 共同设计并实施了冗余抑制功能; – 分析实验结果; – 进行案例研究; – 设计并进行了参数调优实验; – 分析参数调整结果; - 写了大部分论文。 3. Pansy Arafa、Guy Martin Tchamgoue、Hany Kashif 和 Sebastian Fischmeister。 QDIME:QoS 感知的动态二进制检测。在 25 日的诉讼中 计算机建模、分析和仿真国际研讨会 和电信系统 (MASCOTS),加拿大班夫,2017 年 9 月 [19]。 – 共同设计和实施 Qdime; iv – 共同设计和进行案例研究; – 分析结果; – 写了论文的一部分。 前期工作: 4. 潘西·阿拉法、丹尼尔·所罗门、萨马内·纳瓦博尔、塞巴斯蒂安·菲施迈斯特。嵌入式软件开发人员的调试行为:一项探索性研究。在视觉语言和以人为中心的计算研讨会论文集 (VL/HCC),美国罗利,2017 年 10 月 [18]。 – 与合著者一起对研究视频进行编码; – 分析实验结果; – 写论文。 5. Hany Kashif、Pansy Arafa 和 Sebastian Fischmeister。 INSTEP:用于保留额外功能属性的静态检测框架。在诉讼中 第十九届嵌入式与实时计算系统国际会议 和应用 (RTCSA),台北,台湾,2013 年 8 月 [55]。 – 为 INSTEP 的设计做出了贡献; – 执行基准的静态分析和 WCET 分析; – 写了论文的一部分。 6. Joachim Denil、Hany Kashif、Pansy Arafa、Hans Vangheluwe 和 Sebastian Fischmeister。 Simulink 额外功能特性的检测和保留 楷模。在建模与仿真理论研讨会论文集上—— DEVS 综合 M&S 研讨会,美国亚历山大,2015 年 4 月 [32]。 – 共同设计仪器框架; – 写了一部分论文。 v 抽象的 现代软件系统的复杂性一直在迅速增加。程序 调试和测试对于确保此类系统的正确性至关重要。程序 分析对于理解系统行为和分析性能至关重要。许多 程序分析工具使用仪器在运行时提取所需信息。 Instrumentation 自然会改变程序的时序属性并导致扰动 到正在分析的程序。软实时系统必须满足时序约束。 在软实时系统中错过最后期限会导致性能下降。因此,时间敏感系统需要专门的程序分析工具。时间感知仪器 保留程序的逻辑正确性并尊重其时序约束。当前的 时间感知检测方法依赖于静态源代码检测技术。虽然这些方法是合理有效的,但需要运行最坏的情况 仪器前后的执行时间 (WCET) 分析降低了适用性 仅适用于 WCET 分析很常见的硬实时系统。除了微控制器代码之外,它们变得不切实际,无法检测大型程序及其所有 库依赖项。 ### 程序插桩分类 由于程序插桩技术是在被测程序中插入探针,然后通过探针的执行来获得程序的控制流和数据流信息,以此来实现测试的目的。因此,根据探针插入的时间可以分为目标代码插桩和源代码插桩。 #### 目标代码 目标代码插桩的前提是对目标代码进行必要的分析以确定需要插桩的地点和内容。由于目标代码的格式主要和操作系统相关,和具体的编程语言及版本无关,所以得到了广泛的应用,尤其是在需要对内存进行监控的软件中。但是由于目标代码中语法、语义信息不完整,而插桩技术需要对代码词法语法的分析有较高的要求,故在覆盖测试工具中多采用源代码插桩。 #### 源代码 源代码插桩是在对源文件进行完整的词法分析和语法分析的基础上进行的,这就保证对源文件的插桩能够达到很高的准确度和针对性。但是源代码插桩需要接触到源代码,使得工作量较大,而且随着编码语言和版本的不同需要做一定的修改。在后面我们所提到的程序插桩均指源代码插桩。 https://baike.baidu.com/item/%E7%A8%8B%E5%BA%8F%E6%8F%92%E6%A1%A9/242087