十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于熵特征的跨架构二进制漏洞搜索:从控制流图到行为指纹

基于熵特征的跨架构二进制漏洞搜索:从控制流图到行为指纹 1. 项目概述当二进制安全遇上跨架构搜索最近在整理安全研究方向的论文笔记VulHawk这篇关于跨架构漏洞检测的论文让我眼前一亮。它解决的是一个非常实际且棘手的问题在物联网IoT和嵌入式设备安全分析中我们常常面对的是不同指令集架构如ARM、MIPS、x86编译的二进制程序手里可能只有一份有漏洞的x86二进制样本却需要在海量的ARM或MIPS固件中快速、准确地找到存在相同漏洞的“兄弟姐妹”。传统的基于文本或简单特征码的搜索方法在跨架构场景下基本失效因为指令集、寄存器、调用约定完全不同代码“看起来”天差地别。VulHawk的核心思路是绕过表象的指令差异直接捕捉程序更深层的、与架构无关的“行为指纹”从而实现精准的跨架构漏洞代码搜索。这不仅仅是学术上的精巧设计更是实战中的刚需。想象一下一个在路由器x86版本固件中发现的栈溢出漏洞其危害可能远不止于此同一厂商生产的、采用ARM或MIPS芯片的数十款不同型号设备很可能共享着同一份有缺陷的源代码。手动进行跨架构的逆向分析与比对工作量如同大海捞针。VulHawk提出的基于熵的二进制代码搜索框架正是为了自动化、规模化地解决这类问题将安全研究员从繁重的跨平台逆向工作中解放出来极大地提升了漏洞影响的评估效率和漏洞修复的响应速度。接下来我就结合论文和自己的理解拆解一下VulHawk是如何做到的以及我们在复现或借鉴其思想时需要注意哪些坑。2. 核心思路拆解从指令迷宫到行为图谱VulHawk的聪明之处在于它没有试图去直接理解或翻译不同架构的汇编指令——那是一条极其复杂且容易出错的路。相反它选择了一个更高层、更稳定的抽象层次控制流图CFG和函数内的基本块Basic Block序列所蕴含的信息熵。2.1 为何选择“熵”作为度量这里需要先理解“熵”在信息论中的概念它衡量的是一个系统的不确定性或信息含量。在程序分析中一个基本块或一段代码序列的“熵”可以反映其内部指令组合的复杂度和独特性。VulHawk的假设是漏洞代码所在的函数或代码片段由于其特定的逻辑如复杂的条件判断、循环、特定的内存操作模式往往会表现出与众不同的熵值特征。这种特征相对于函数整体的代码布局如指令的具体内容、寄存器分配而言对编译器和架构变化的鲁棒性更强。举个例子一个实现复杂解析逻辑的函数无论被编译成x86还是ARM其内部各个基本块之间的跳转关系CFG结构和每个基本块内指令的“混乱程度”熵分布模式应该是相对稳定的。而一些简单的、模板化的函数如内存拷贝函数memcpy的通用实现其熵特征可能就比较普通缺乏辨识度。因此基于熵的搜索本质上是在寻找那些具有“高辨识度行为指纹”的代码区域而漏洞代码恰恰常常属于这类区域。2.2 跨架构搜索的三层抽象策略为了实现跨架构的比对VulHawk构建了一个三层抽象模型层层递进过滤掉架构相关的“噪声”保留架构无关的“信号”指令级抽象首先它完全剥离了操作数如具体的寄存器名、内存地址、立即数。对于每一条指令只保留其操作码Opcode类别。例如无论是MOV EAX, EBX还是MOV R0, R1都被抽象为同一个“移动”操作类别。这一步极大地消除了因架构不同导致的指令集语法差异。基本块级抽象接着它将一个基本块内所有抽象后的指令序列转化为一个固定长度的数值向量。这里用到了自然语言处理NLP中常用的n-gram模型。比如将基本块内的指令类别序列视为“句子”提取连续的2个或3个指令类别组合bi-gram, tri-gram的出现频率作为该基本块的特征。这样一个基本块就被表示成了一个高维特征向量刻画了其内部的指令组合模式。函数级抽象与熵计算最后对一个函数的所有基本块特征向量进行聚类分析。VulHawk发现一个函数内通常包含几种不同类型的“代码模式”例如数据处理块、控制转移块、计算密集型块。通过聚类可以将功能相似的基本块归为一类。然后关键的一步来了计算每一类基本块的特征向量之间的平均余弦相似度这个相似度值被定义为该类基本块的“熵”。熵值越低说明该类基本块内部的代码模式越统一、越简单熵值越高则说明该类基本块内部的代码模式越多样、越复杂。最终一个函数可以用其所有基本块类别的熵值分布来表征。通过这三层抽象VulHawk成功地将一个二进制函数从依赖于具体架构和编译选项的指令流转化为了一个仅反映其内在逻辑复杂度的、架构无关的“熵签名”。这个签名就是后续进行相似性搜索的基石。注意这个过程的成功高度依赖于第一步操作码分类的准确性和粒度。如果分类太粗如所有算术指令归为一类会丢失太多信息如果分类太细又会引入架构依赖性。论文中需要设计一个精心定义的指令分类表这是一个需要大量先验知识和调优的环节。3. 系统架构与工作流程详解理解了核心思想我们来看VulHawk系统具体是如何运作的。整个流程可以清晰地分为离线索引构建和在线搜索查询两个阶段这和我们常用的搜索引擎如Google或代码搜索引擎如GitHub Code Search的思路是一致的。3.1 离线阶段为二进制数据库建立“熵指纹”索引假设我们有一个庞大的二进制文件集合例如从各种设备固件中提取出的所有可执行文件离线阶段的目标就是为这个集合中的每一个函数预先计算好它的“熵签名”并建立高效的索引以便快速检索。二进制解析与函数提取使用反汇编引擎如IDA Pro的API、Ghidra或radare2加载二进制文件。进行函数识别Function Recognition。这一步至关重要识别不准会直接导致后续分析对象错误。VulHawk需要依赖这些工具的基础识别能力可能还需要一些启发式规则来处理剥离了符号stripped的二进制文件。为每个识别出的函数生成其控制流图CFG。函数特征提取对CFG中的每一个基本块执行前述的三层抽象过程指令操作码归类 -n-gram特征向量生成。使用聚类算法如K-means或DBSCAN对该函数所有基本块的特征向量进行聚类。计算每个簇即每一类基本块内部向量的平均余弦相似度得到该簇的熵值。最终该函数的特征表示为一个熵值的集合或分布直方图。论文中可能会将其进一步编码为一个定长的特征向量。索引构建将所有函数的特征向量存入一个数据库。为了支持高效的最近邻搜索即找到特征最相似的函数通常会使用诸如局部敏感哈希LSH或球树Ball Tree等数据结构来构建索引。LSH特别适合高维空间中的近似最近邻搜索它能以很高的概率将相似的特征向量哈希到同一个“桶”中从而在搜索时只需检查少数几个桶极大地加快了速度。3.2 在线阶段输入漏洞代码输出相似函数当安全研究员发现一个漏洞例如在x86的libc.so中找到一个有问题的函数vuln_func并希望在其他架构的二进制中搜索类似代码时就进入在线阶段。查询生成对漏洞函数vuln_func执行完全相同的特征提取流程得到它的“熵签名”特征向量Q。相似性搜索使用离线阶段构建的索引如LSH在目标二进制数据库中进行检索。索引系统会快速返回一组与查询向量Q距离最近例如余弦距离最小或欧氏距离最小的候选函数列表。结果排序与验证初始搜索可能会返回大量候选。VulHawk会用一个更精确但计算量也更大的相似度度量如直接计算特征向量间的余弦相似度对Top-K个候选进行重新排序。最终输出一个按相似度降序排列的函数列表每个结果都附带了其所在的二进制文件、函数地址或名称如果有的话以及相似度分数。重要提示搜索结果是一个“相似性”列表而非“等同性”判定。排名第一的函数不一定就是漏洞的1:1移植它可能是一个功能类似、代码复杂度也类似的函数。研究员需要结合逆向工程对高排名结果进行人工验证这是自动化工具无法完全替代的一步。整个流程的威力在于一旦离线索引构建完成在线搜索的速度会非常快可以实现近乎实时的跨海量二进制代码库的漏洞影响面评估。4. 关键技术细节与实现难点纸上谈兵终觉浅要实现或复现VulHawk的思想有几个技术细节必须啃下来这里分享一些我的理解和可能遇到的坑。4.1 指令归一化与分类表设计这是整个系统的基石也是最需要领域知识的部分。不同指令集架构的指令数量和语义差异巨大。一个实用的分类表需要平衡通用性和区分度。通用类别如算术运算ADD, SUB、逻辑运算AND, OR, XOR、数据移动MOV, LOAD, STORE、控制流JUMP, CALL, RETURN、比较CMP、栈操作PUSH, POP等。这些类别在大多数架构中都有对应。架构特有指令的处理例如ARM的IT块条件执行、x86的字符串操作指令REP MOVSB、MIPS的延迟槽指令。对于这些要么将其归入一个更宽泛的类别如将IT块内的指令与其条件指令合并考虑要么为其创建特殊的类别但这可能会降低跨架构的匹配能力。一个可行的策略是在初始分类时忽略那些极度特有的指令或者将其映射到功能最近似的通用类别。实现心得最好不要从头开始造轮子。可以利用现有的反汇编框架如Capstone引擎提供的指令分组group信息作为起点然后根据跨架构匹配的需求进行自定义的合并与调整。构建一个覆盖x86、ARM32/64、MIPS等常见架构的统一分类词典是一个需要反复迭代测试的过程。4.2 基本块特征表示与n-gram选择将基本块表示为n-gram向量时有几个参数需要仔细考量n的选择n越大捕捉的上下文信息越多但特征向量会越稀疏且对代码微小变动的容忍度越低。论文中可能使用了n2或n3。在实践中bi-gram2-gram是一个不错的起点它能捕捉到如“比较后跳转”这类常见的指令对模式。向量化方法简单统计n-gram频率是一种方法。也可以使用TF-IDF加权让那些在一个基本块中出现频繁但在所有基本块中出现也频繁的常见n-gram如MOV-MOV权重降低提升具有区分度的n-gram的权重。基本块长度差异短的基本块可能无法产生有意义的n-gram。对于过短的基本块例如只有一条指令可能需要特殊的处理策略比如将其与前后基本块合并或者使用一个特殊的“短块”类别。4.3 聚类算法与熵的计算聚类算法选择K-means需要预先指定簇的数量K这对于不同大小和复杂度的函数来说是个挑战。DBSCAN不需要指定K能自动发现任意形状的簇并剔除噪声点那些不属于任何簇的基本块可能更适合这种场景。噪声点可以不参与熵的计算或者赋予一个固定的熵值。“熵”的具体计算论文中将一个簇内所有特征向量两两之间的平均余弦相似度作为“熵”。余弦相似度取值范围是[-1, 1]1表示完全相同。那么平均相似度越高说明簇内成员越一致该簇的“不确定性”或“混乱度”反而越低。因此VulHawk定义的“熵”更像是“一致性分数”值越高表示该簇模式越统一。这一点需要理解清楚它和传统信息熵的概念是反直觉的但作为特征度量是有效的。函数特征向量构建得到每个簇的熵值后如何组合成一个代表整个函数的向量简单的方法是将所有熵值排序后拼接成一个向量。但函数间簇的数量可能不同。解决方案可以是固定一个维度N只取熵值最大或最小的前N个簇不足的补零或者使用一个固定长度的直方图将熵值划分到几个区间进行统计。4.4 相似性度量与索引构建距离度量在搜索阶段需要计算查询函数向量与数据库中函数向量的距离。由于特征向量可能是直方图形式卡方距离Chi-square distance或直方图相交距离Histogram Intersection通常比欧氏距离更适合衡量分布之间的差异。余弦相似度也是一个经典选择。索引技术如果数据库规模巨大数百万个函数线性扫描是不可行的。局部敏感哈希LSH是解决高维空间近似最近邻搜索的利器。对于余弦相似度可以使用基于随机超平面投影的LSHSimHash。它的好处是相似的向量有高概率哈希到相同的桶中。调参的重点在于哈希函数的数量和哈希表的个数这需要在召回率找到所有相似项的能力和精度返回结果中真正相似的比例以及查询速度之间做权衡。5. 实验评估与效果分析视角读论文时我们不仅要看它声称的效果更要看它是如何设计和评估实验的。对于VulHawk这类工具一个有说服力的评估应该包含以下几个方面数据集构建论文通常会使用一个包含多个架构x86, ARM, MIPS、多个优化等级-O0, -O1, -O2, -Os编译的相同源代码程序的数据集。例如用Coreutils、Busybox等开源项目分别用不同编译器和选项为不同架构编译形成“已知正确答案”的测试集。这样一个在x86的grep中发现的函数可以在ARM的grep中找到其对应项用于验证搜索的准确性。评估指标召回率Recall在所有真实存在的跨架构匹配函数中系统成功找出了多少比例。这是衡量漏报的关键。准确率/精度Precision在系统返回的搜索结果中真正正确的匹配占多少比例。这是衡量误报的关键。平均排名Mean Reciprocal Rank, MRR对于每个查询正确结果在返回列表中的排名的倒数如排名第一则得1分排名第二得0.5分然后对所有查询取平均。这个指标衡量系统把正确答案排在前面的能力。搜索时间在线查询的响应速度体现了系统的实用性。对比基线VulHawk需要与已有的跨架构二进制相似性检测方法对比例如基于图形同构或图嵌入的CFG匹配方法。基于机器学习模型如Gemini, Asm2Vec学习汇编指令嵌入的方法。简单的基于字符串或常量引用的搜索。 通过对比才能凸显其基于熵的方法在精度、速度或跨架构鲁棒性上的优势。案例研究Case Study论文一般会提供几个真实的漏洞跨架构搜索案例例如从一个架构的库文件中找到的已知CVE漏洞函数是否能在其他架构的固件中被成功定位。这能最直观地展示其工具在真实安全任务中的价值。实操心得在复现论文实验时最大的挑战往往是数据集的准备和基线系统的实现。收集、编译、整理跨架构的二进制数据集非常耗时。此外很多对比方法可能没有开源代码需要自己根据论文描述重新实现这本身就是一个巨大的工程。因此对于工业界或独立研究员更务实的做法可能是借鉴VulHawk的核心思想熵特征将其整合或改进到现有的二进制分析流水线中而不是追求完全复现。6. 优势、局限与未来改进方向任何技术都有其边界清醒地认识VulHawk的优缺点才能更好地应用它。6.1 核心优势架构无关性这是其最大亮点。通过高层次的熵特征有效屏蔽了指令集差异实现了真正的跨架构搜索。对编译器优化的鲁棒性不同的优化等级-O0, -O2会大幅改变指令序列和寄存器分配但函数整体的控制流结构和核心代码块的逻辑复杂度相对稳定。因此基于熵的方法对编译器优化有一定抵抗力。效率高离线索引构建后在线搜索基于高效的索引结构如LSH速度很快适合大规模二进制代码库的扫描。无需源代码完全基于二进制符合安全分析尤其是对闭源软件或设备固件分析的常态。6.2 现有局限与挑战对代码混淆抵抗力有限如果代码经过了严重的混淆如控制流扁平化、虚假分支插入CFG的结构会被极大破坏基本块的划分和指令序列也会变得面目全非。这会从根本上影响特征提取的有效性。VulHawk可能难以处理经过强混淆的恶意软件或商业保护的程序。语义理解深度不足它捕捉的是“模式复杂度”而非“语义等价性”。两个熵特征相似的函数可能在功能上完全不同例如一个加密函数和一个压缩函数可能都有复杂的循环和位操作。这会导致误报。它更擅长找到“代码模式相似”的函数而非“漏洞语义等价”的函数。函数识别依赖前置工具整个流程始于反汇编和函数识别。如果IDA Pro/Ghidra等工具在某个架构或特定编译选项下函数识别失败或错误VulHawk的输入就是错误的后续分析自然失效。特征可解释性一般最终用于比对的熵特征向量是一个高度抽象的数字表示。为什么两个函数相似研究员很难从这个向量本身得到直观的解释不利于人工复核和深度分析。6.3 可能的改进与融合思路结合最新的研究趋势比如你提到的热词“vuldiac: vulnerability detection and interpretation based on augmented cfg”我认为VulHawk的思路可以朝以下几个方向演进与更丰富的程序表征结合Vuldiac提到了“增强的CFG”。我们可以不仅仅依赖熵还可以在CFG节点基本块上附着更多语义信息例如数据流特征记录变量的定义-使用关系。值集分析Value Set Analysis结果了解指令操作数的可能取值。API/系统调用序列函数调用了哪些外部API这些API序列是强大的语义标签。 将这些信息与熵特征融合形成多模态的函数表征可以同时捕捉结构复杂度和语义信息提高搜索的准确性。引入深度学习使用图神经网络GNN来学习CFG的表示。GNN可以端到端地学习如何将带有节点特征如指令n-gram、熵值和边特征控制流类型的CFG映射到一个低维向量。这个向量能同时编码图结构和节点属性信息可能比手工设计的熵特征更有表现力。训练数据可以来自不同架构编译的同一份源代码让模型学会忽略架构差异关注功能本质。聚焦漏洞特异性模式VulHawk是通用的代码搜索。我们可以针对特定类型的漏洞如栈溢出、格式化字符串、整数溢出总结其更具体的模式。例如栈溢出漏洞函数常包含对strcpy、gets等不安全函数的调用且其缓冲区大小可能在代码中有所体现。将这类漏洞签名Vulnerability Signature与熵特征结合构建针对性的漏洞检测模型而不仅仅是代码相似性搜索。提升结果可解释性在返回相似函数的同时尝试给出“为什么相似”的解释。例如高亮两个函数中熵值最高的、且匹配上的基本块或者展示它们简化后的、归一化的指令流对比。这能极大帮助安全研究员快速验证结果。7. 实战应用场景与工具链设想理论最终要服务于实践。基于VulHawk的思想我们可以设想一个在真实安全团队中可能的工作流和工具链场景应急响应与影响面评估漏洞爆发某开源网络库libfoo的x86/64版本被曝出高危漏洞CVE-2023-XXXX漏洞位于函数parse_packet()中。提取特征安全工程师使用集成VulHawk核心组件的内部工具对含有漏洞的libfoo.sox86_64进行分析提取出parse_packet函数的“熵签名”向量Q。全网扫描团队维护着一个所有线上产品、历史版本固件、第三方SDK的二进制文件数据库并已预先建立好熵特征索引。工程师将Q作为查询输入系统在几分钟内返回一个列表显示在ARM32架构的智能摄像头固件、MIPS架构的老款路由器固件中存在多个与Q高度相似的函数。人工研判与修复工程师对排名前几的候选进行重点逆向分析快速确认它们确实是漏洞的跨架构实现。随后团队可以精准定位受影响的产品型号和版本制定修补和升级策略发布安全公告。构建内部工具链的要点自动化流水线将二进制文件上传到存储系统后自动触发反汇编、函数提取、特征计算和索引更新。集成现有平台与漏洞管理系统、固件分析平台打通支持一键式漏洞影响查询。可视化界面提供Web界面允许输入二进制文件或函数地址可视化展示搜索结果和相似度对比。可扩展架构设计插件化系统方便集成新的指令集支持、新的特征提取算法或相似度度量方法。VulHawk论文为我们提供了一条清晰且实用的技术路径将信息论中的熵概念巧妙地应用于跨架构二进制分析这一难题。它可能不是终点而是一个重要的里程碑。其核心启示在于在二进制分析的深水区绕过表象的指令差异去捕捉程序更本质、更稳定的行为属性是通往更通用、更鲁棒的分析工具的必经之路。在实际工作中我们不必追求完全复现而是应该吸收其思想精髓——构建架构无关的、反映代码内在复杂度的特征并将其与我们已有的二进制分析经验、对特定漏洞模式的认知相结合从而打造出真正能提升安全运营效率的自动化武器。
返回列表