CN116775127A - 一种基于RetroWrite框架的静态符号执行插桩方法 - Google Patents

一种基于RetroWrite框架的静态符号执行插桩方法 Download PDF

Info

Publication number
CN116775127A
CN116775127A CN202310598471.6A CN202310598471A CN116775127A CN 116775127 A CN116775127 A CN 116775127A CN 202310598471 A CN202310598471 A CN 202310598471A CN 116775127 A CN116775127 A CN 116775127A
Authority
CN
China
Prior art keywords
expression
instruction
modeling
operand
register
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN202310598471.6A
Other languages
English (en)
Other versions
CN116775127B (zh
Inventor
叶麟
严明
刘念
武跃
吴雨伦
朱若彬
余翔湛
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Harbin Institute of Technology
Original Assignee
Harbin Institute of Technology
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Harbin Institute of Technology filed Critical Harbin Institute of Technology
Priority to CN202310598471.6A priority Critical patent/CN116775127B/zh
Publication of CN116775127A publication Critical patent/CN116775127A/zh
Application granted granted Critical
Publication of CN116775127B publication Critical patent/CN116775127B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/30Arrangements for executing machine instructions, e.g. instruction decode
    • G06F9/30145Instruction analysis, e.g. decoding, instruction word fields
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software
    • G06F11/3668Software testing
    • G06F11/3672Test management
    • G06F11/3688Test management for test execution, e.g. scheduling of test suites
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/30Creation or generation of source code
    • G06F8/31Programming languages or programming paradigms
    • G06F8/315Object-oriented languages
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/30Arrangements for executing machine instructions, e.g. instruction decode
    • G06F9/30098Register arrangements
    • G06F9/3012Organisation of register space, e.g. banked or distributed register file
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/30Arrangements for executing machine instructions, e.g. instruction decode
    • G06F9/38Concurrent instruction execution, e.g. pipeline or look ahead
    • G06F9/3836Instruction issuing, e.g. dynamic instruction scheduling or out of order instruction execution
    • G06F9/3851Instruction issuing, e.g. dynamic instruction scheduling or out of order instruction execution from multiple instruction streams, e.g. multistreaming
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/48Program initiating; Program switching, e.g. by interrupt
    • G06F9/4806Task transfer initiation or dispatching
    • G06F9/4843Task transfer initiation or dispatching by program, e.g. task dispatcher, supervisor, operating system
    • G06F9/4881Scheduling strategies for dispatcher, e.g. round robin, multi-level priority queues

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Software Systems (AREA)
  • General Engineering & Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Hardware Design (AREA)
  • Quality & Reliability (AREA)
  • Multimedia (AREA)
  • Computing Systems (AREA)
  • Executing Machine-Instructions (AREA)

Abstract

本发明公开了一种基于RetroWrite框架的静态符号执行插桩方法,属于计算机技术领域。解决了现有技术中符号执行插桩方法在闭源程序运行时开销较大的问题;本发明包括以下步骤:S1.访问闭源的C/C++程序中的各个用户自定义函数;S2.访问函数中的各个基本块;S3.顺序访问指令;S4.进行指令级插桩,为赋值、调用、运算和条件类指令进行功能插桩;S5.进行基本块插桩,在基本块的出口进行辅助插桩;S6.进行函数级插桩,在函数的入口和出口进行辅助插桩。本发明面向闭源程序通用高效,有效降低了运行时非求解开销,在扩展使用范围的同时,提高了混合模糊测试的速度,可以应用于软件测试。

Description

一种基于RetroWrite框架的静态符号执行插桩方法
技术领域
本发明涉及插桩方法,尤其涉及一种基于RetroWrite框架的静态符号执行插桩方法,属于计算机技术领域。
背景技术
符号执行插桩方法一般用于解决符号执行运行时非求解阶段开销过大的问题,非求解阶段包括准备、分析、建模三个部分,KLEE等经典符号执行器的模拟执行需要对每条表示语句均进行分析建模,在三个部分均会产生时间开销,严重降低整体测试性能,下面对现有的几种符号执行插桩方法进行简述:
QSYM:该方法使用Pin框架,在运行过程中对特定机器码指令进行动态插桩,省略了转换到中间语言模拟的开销;
SymCC:该方法提出,在程序源码编译期间对LLVMIR进行分析,插桩建模函数,链接为目标插桩程序,在混合模糊测试的过程中,符号执行可以在运行中直接调用建模函数为约束生成表达式,传递给求解器,进一步节省了运行时的分析开销,同时解决指令集依赖问题;
SymQEMU:该方法消除了SymCC的源码依赖,基于QEMU实现,该方法实现与QSYM基本一致,不同的是,SymQEMU需要将目标程序指令转换为QEMU的中间表示TCG,在TCG上进行插桩,再编译为机器码执行,仿真器的使用实际上会产生高于QSYM的分析开销;
QSYM方法运行于机器码,能够较大地降低非求解开销,但存在平台兼容问题,此外,该技术仍存在运行时的动态分析开销。SymCC技术过度依赖于源码,无法解决闭源程序的非求解开销问题。SymQEMU方法使用QEMU仿真器,且同样地存在运行时的动态转换和分析开销,实际上会产生高于QSYM的非求解开销;
总体而言,上述现有的符号执行插桩方法存在QSYM平台兼容性差、SymCC过度依赖源码、SymQEMU运行时开销大的缺陷,可见,需要一种可以实现面向闭源程序的通用高效且降低运行时非求解开销的符号执行插桩方法,扩展使用范围的同时,提高混合模糊测试的速度。
发明内容
在下文中给出了关于本发明的简要概述,以便提供关于本发明的某些方面的基本理解。应当理解,这个概述并不是关于本发明的穷举性概述。它并不是意图确定本发明的关键或重要部分,也不是意图限定本发明的范围。其目的仅仅是以简化的形式给出某些概念,以此作为稍后论述的更详细描述的前序。
鉴于此,为解决现有技术中符号执行插桩方法在闭源程序运行时开销较大的问题,本发明提供一种基于RetroWrite框架的静态符号执行插桩方法,面向闭源的C/C++程序,从指令、基本块和函数三个级别进行插桩;本发明依次处理程序中的各个用户自定义函数,访问函数中的各个基本块,对基本块中与约束有关的指令做相应的功能插桩,实现建模函数的配套调用,并分别在基本块和函数的入口和出口做相应的辅助插桩,保证约束表达式的完整存储和程序的正常运行,减少闭源程序运行时的开销。
技术方案如下:一种基于RetroWrite框架的静态符号执行插桩方法,包括以下步骤:
S1.访问闭源的C/C++程序中的各个用户自定义函数;
S2.访问函数中的各个基本块;
S3.顺序访问指令;
S4.进行指令级插桩,为赋值、调用、运算和条件类指令进行功能插桩;
S5.进行基本块插桩,在基本块的出口进行辅助插桩;
S6.进行函数级插桩,在函数的入口和出口进行辅助插桩。
进一步地,所述S4中,包括以下步骤:
S41.按照建模需要不同,将汇编指令分为赋值类指令、调用类指令、运算类指令和条件类指令;
S42.判断指令对应的操作数类型,为操作数建模生成表达式,再建模生成整个约束的表达式;
进一步地,所述S41中,赋值类指令为助记符为mov、lea的汇编指令,包括内存读取指令、内存写入指令、寄存器赋值和立即数赋值四种指令;调用类指令为助记符为call的指令,以及少部分助记符为jmp的指令;运算类指令为汇编中具有运算功能的所有整型指令,忽略浮点运算指令;条件类指令为条件跳转指令,忽略与路径约束不匹配的条件跳转指令。
所述S42中,在为操作数建模生成表达式、再建模生成整个约束的表达式时,建模过程中插桩调用的函数均称为建模函数,运算类指令中称为运算建模函数,条件类指令中称为条件比较建模函数;
赋值类指令:内存读取指令中,源操作数为内存,目的操作数为寄存器,插桩调用_sym_read_memory获取源操作数对应的约束表达式,sym_read_memory建模函数返回内存对应的表达式,若不存在则返回空指针,内存写入指令中,源操作数为立即数或寄存器,目的操作数为内存,将立即数或寄存器对应的约束表达式作为内存对应的表达式进行存储,插桩调用_sym_write_memory,_sym_write_memory建模函数会把源操作数对应的表达式写入目的操作数的预留空间内,作为目的操作数的表达式,寄存器赋值指令中,源操作数为寄存器,目的操作数为寄存器,需要插桩复制源操作数的表达式到目的操作数的预留空间内,立即数赋值指令可以留待后续约束需要时再进行建模;
调用类指令:采用过量匹配的原则,对于函数参数,在所属基本块内且不包含其他调用的情况下,按照汇编的参数传递规则,对寄存器rdi、rsi、rdx、rcx的赋值或运算将被视为存在寄存器形式的参数传递,当前四个参数存在时,若还存在push指令,将进行入栈形式的参数传递,并按照倒序确定该参数的次序,根据参数传递信息,对相应指令插桩,调用_sym_set_parameter_expression,_sym_set_parameter_expression建模函数会按照参数次序将相应表达式写入特定的地址,给予被调用者使用,对于函数返回值,在所属基本块及其后继基本块中寻找是否存在寄存器rax的use-not-define的使用,若存在,则插桩调用_sym_get_return_expression,_sym_get_return_expression建模函数会返回被调用者返回值的表达式;
运算类指令:插桩调用_sym_build_integer进行操作数建模生成表达式,_sym_build_integer运算建模函数会以操作数取值、指定的表达式位数、字节序为输入,返回生成的表达式,根据操作数的不同情况,将采取不同的建模方式,当操作数为立即数,建模生成32位或64位的立即数的表达式,当操作数为寄存器或内存,判断是否已关联表达式,若该操作数不具有相应的表达式,则需要建模生成对应位数的寄存器值的表达式,否则需要先对相应的表达式进行判空,若表达式非空,则可以直接用于后续运算的建模,否则跳过该运算的建模,完成操作数的检查或建模工作后,根据助记符选择特定的运算建模函数生成表达式,并存储在目的操作数的预留空间;
条件类指令:当操作数的表达式位数不一致,且助记符尾缀位数小于32位时,立即数操作数直接建模生成相应表达式,寄存器或内存操作数判断该操作数是否已关联表达式,若该操作数不具有相关表达式,则按照32位对操作数建模生成表达式,否则对表达式判空,若非空,则进一步扩展表达式位数,插桩调用_sym_build_sext,_sym_build_sext条件比较建模函数以表达式、扩展位数、字节序为输入,返回扩展位数后的表达式,用于后续条件比较的建模,否则,跳过该条件比较的建模,其他情况下,按照运算类指令中的操作数建模方式处理,完成操作数的检查或建模工作后,根据助记符选择特定的条件比较建模函数生成表达式,随后插桩调用_sym_push_path_constraint,_sym_push_path_constraint条件比较建模函数将以表达式为输入,把表达式传递给约束求解器并收集求解结果,用于生成新的测试用例。
进一步地,所述S5中,包括以下步骤:
S51.为当前基本块传递给后继基本块的可能被使用的表达式预留空间;
S52.进行空表达式区分,在基本块的出口进行辅助插桩;
进一步地,所述S51中,在访问各个函数时,预先收集基本块中use-not-define且参与赋值类指令、调用类指令、运算类指令和条件类指令的寄存器,为可能被使用的表达式预留空间,用于存放可能传递的表达式;
所述S52中,预留空间的同时赋予该地址一个特殊值,用于判断该寄存器对应的表达式是否在前驱中被建模生成,在运算或条件类指令的操作数建模中,在判空的同时进一步判断表达式取值是否为特殊值,若是,则说明表达式并未在前驱中建模,需要在此处插桩建模生成,在基本块出口处,根据其后继基本块的use-not-define寄存器信息,将可能被使用的表达式复制到后继基本块的指定预留空间中。
进一步地,所述S6中,默认插桩的栈内存访问方式为基于寄存器rbp向下访问,使用rbp寄存器时,修改函数的栈调整指令subq$xx,%rsp和addq$xx,%rsp,栈空间大小变更为原栈空间和插桩需使用的空间之和;使用rsp寄存器时,将寄存器rbp的值伪造为栈基址,将真实值存放在-8(rbp)位置上,当指令使用rbp真实值时,选择当前指令下处于空闲状态的寄存器作为rbp的替换对象,将其值压入栈中,随后将rbp真实值赋到该替换对象,并对指令中的操作数进行替换,在完成指令执行后,将替换对象此时的值赋到rbp真实值位置上,若存在表达式的更新,同样地将更新赋到rbp对应的表达式中,保证原函数逻辑的正常执行。
本发明的有益效果如下:为了评估本发明的有效性进行实验,使用已有插桩方法SymCC、SymQEMU与本发明进行对比,本发明实现称为RWSym,实验以三个程序作为基准进行评估,程序1只涉及多个简单约束、程序2涉及一些逻辑约束,程序3涉及多种运算组合约束;
参考图6,在求解耗时上,RWSym的耗时几乎不会超出另外两种方法,说明RWSym基本不会产生额外的求解,SymQEMU在三组程序中的求解耗时始终最高,是因为SymCC和RWSym直接运行插桩程序,而SymQEMU将目标程序作为参数输入自身程序中运行,存在运行转换上的开销;
参考图7,在非求解耗时上,RWSym可以保持与SymCC基本一致的耗时平均值,意味着通过RWSym,闭源程序经过插桩后也能获得与源码插桩基本相同的非求解开销,即有效地降低了运行时非求解开销,与SymQEMU对比可以看到,在程序1中,SymQEMU的非求解耗时平均是RWSym的3.01倍,在程序2中,SymQEMU的非求解耗时平均是RWSym的2.49倍,在程序3中,SymQEMU的非求解耗时平均是RWSym的33.4倍,这说明了动态插桩方法会在运行时额外产生分析、转换、插桩的开销,大幅降低整体运行速度,程序3的对比结果也说明了,面对多种运算组合的约束,SymQEMU会花费更多的时间进行分析,导致远超于SymCC和RWSym的耗时,从方差上看,RWSym在非求解开销上总体上变化不大,说明RWSym的优化是稳定的;
综上所述,本发明实现了RWSym通过插桩使闭源程序获得与源码几乎一致的非求解开销,有效地降低了运行时非求解开销,保证了约束表达式的完整存储和程序的正常运行,在扩展使用范围的同时,提高了混合模糊测试的速度,可以应用于软件测试。
附图说明
此处所说明的附图用来提供对本发明的进一步理解,构成本发明的一部分,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1为一种基于RetroWrite框架的静态符号执行插桩方法流程示意图;
图2为RetroWrite框架实现流程示意图;
图3为符号执行插桩方法非求解阶段示意图;
图4为进行函数级插桩使用rbp寄存器的情况示意图;
图5为进行函数级插桩使用rsp寄存器的情况示意图;
图6为SymCC、SymQEMU和RWSym求解耗时对比示意图,其中,(a)为程序1中SymCC、SymQEMU和RWSym求解耗时对比示意图,(b)为程序2中SymCC、SymQEMU和RWSym求解耗时对比示意图,(c)为程序3中SymCC、SymQEMU和RWSym求解耗时对比示意图;
图7为SymCC、SymQEMU和RWSym非求解耗时对比示意图,其中,(a)为程序1中SymCC、SymQEMU和RWSym非求解耗时对比示意图,(b)为程序2中SymCC、SymQEMU和RWSym非求解耗时对比示意图,(c)为程序3中SymCC、SymQEMU和RWSym非求解耗时对比示意图。
具体实施方式
为了使本发明实施例中的技术方案及优点更加清楚明白,以下结合附图对本发明的示例性实施例进行进一步详细的说明,显然,所描述的实施例仅是本发明的一部分实施例,而不是所有实施例的穷举。需要说明的是,在不冲突的情况下,本发明中的实施例及实施例中的特征可以相互组合。
参考图1-图7详细说明本实施例,一种基于RetroWrite框架的静态符号执行插桩方法,具体包括以下步骤:
S1.访问各个用户自定义函数;
S2.访问函数中的各个基本块;
S3.顺序访问指令;
S4.进行指令级插桩,为赋值、调用、运算和条件类指令进行功能插桩;
具体步骤为:
S41.按照建模需要不同,将汇编指令分为赋值类指令、调用类指令、运算类指令和条件类指令;
所述S41中,赋值类指令为助记符为mov、lea的汇编指令,包括内存读取指令、内存写入指令、寄存器赋值和立即数赋值四种指令;调用类指令为助记符为call的指令,以及少部分助记符为jmp的指令;运算类指令为汇编中具有运算功能的所有整型指令,忽略浮点运算指令;条件类指令为条件跳转指令,忽略与路径约束不匹配的条件跳转指令;
S42.判断指令对应的操作数类型,为操作数建模生成表达式,再建模生成整个约束的表达式;
所述S42中,在为操作数建模生成表达式、再建模生成整个约束的表达式时,建模过程中插桩调用的函数均称为建模函数,运算类指令中称为运算建模函数,条件类指令中称为条件比较建模函数;
赋值类指令:内存读取指令中,源操作数为内存,目的操作数为寄存器,插桩调用_sym_read_memory获取源操作数对应的约束表达式,_sym_read_memory建模函数返回内存对应的表达式,若不存在则返回空指针,内存写入指令中,源操作数为立即数或寄存器,目的操作数为内存,将立即数或寄存器对应的约束表达式作为内存对应的表达式进行存储,插桩调用_sym_write_memory,_sym_write_memory建模函数会把源操作数对应的表达式写入目的操作数的预留空间内,作为目的操作数的表达式,寄存器赋值指令中,源操作数为寄存器,目的操作数为寄存器,需要插桩复制源操作数的表达式到目的操作数的预留空间内,立即数赋值指令可以留待后续约束需要时再进行建模;
调用类指令:采用过量匹配的原则,对于函数参数,在所属基本块内且不包含其他调用的情况下,按照汇编的参数传递规则,对寄存器rdi、rsi、rdx、rcx的赋值或运算将被视为存在寄存器形式的参数传递,当前四个参数存在时,若还存在push指令,将进行入栈形式的参数传递,并按照倒序确定该参数的次序,根据参数传递信息,对相应指令插桩,调用_sym_set_parameter_expression,_sym_set_parameter_expression建模函数会按照参数次序将相应表达式写入特定的地址,给予被调用者使用,对于函数返回值,在所属基本块及其后继基本块中寻找是否存在寄存器rax的use-not-define的使用,若存在,则插桩调用_sym_get_return_expression,_sym_get_return_expression建模函数会返回被调用者返回值的表达式;
运算类指令:插桩调用_sym_build_integer进行操作数建模生成表达式,_sym_build_integer建模函数会以操作数取值、指定的表达式位数、字节序为输入,返回生成的表达式,根据操作数的不同情况,将采取不同的建模方式,当操作数为立即数,建模生成32位或64位的立即数的表达式,当操作数为寄存器或内存,判断是否已关联表达式,若该操作数不具有相应的表达式,则需要建模生成对应位数的寄存器值的表达式,否则需要先对相应的表达式进行判空,若表达式非空,则可以直接用于后续运算的建模,否则跳过该运算的建模,完成操作数的检查或建模工作后,根据助记符选择特定的运算建模函数生成表达式,并存储在目的操作数的预留空间;
条件类指令:当操作数的表达式位数不一致,且助记符尾缀位数小于32位时,立即数操作数直接建模生成相应表达式,寄存器或内存操作数判断该操作数是否已关联表达式,若该操作数不具有相关表达式,则按照32位对操作数建模生成表达式,否则对表达式判空,若非空,则进一步扩展表达式位数,插桩调用_sym_build_sext,_sym_build_sext建模函数以表达式、扩展位数、字节序为输入,返回扩展位数后的表达式,用于后续条件比较的建模,否则,跳过该条件比较的建模,其他情况下,按照运算类指令中的操作数建模方式处理,完成操作数的检查或建模工作后,根据助记符选择特定的条件比较建模函数生成表达式,随后插桩调用_sym_push_path_constraint,_sym_push_path_constraint建模函数将以表达式为输入,把表达式传递给约束求解器并收集求解结果,用于生成新的测试用例;
具体的,参考图1,RetroWrite框架是一个具有平台兼容性的静态重写框架,在x86、arm等架构中均可使用,该框架以位置无关可执行代码为输入,以汇编代码为输出,位置无关代码(PositionIndependentCode,PIC),指的是一种可以直接加载而无需重定位的代码,此类程序加载到内存时将使用相对地址,所有对固定地址的访问都需要通过全局偏移表(globaloffsettable,GOT)来实现,对函数地址的访问需要关联过程链接表(Procedure LinkageTable,PLT),该访问方式解决了动态库支持的问题,因而通常被用于共享库中,编译选项为“-fPIC”,位置无关可执行代码,是具有位置无关特性的可执行文件,需要使用编译选项“-fPIE”,RetroWrite框架通过加载和分析位置无关可执行代码中的GOT、PLT表,将数据和代码段的访问方式从确定性的硬编码地址转换为具有可伸缩性的汇编标签,从而获得可重组的汇编代码,可重组性意味着,汇编指令之间不再具有硬关联关系,对任何一条汇编指令进行插桩均不会影响后续汇编的执行效果;
本实施例基于RetroWrite框架,对汇编指令做插桩处理,将每一条汇编指令视为一个具有独立语义的语句,若一条指令与约束有关,其操作数即为该约束的参与变量,因此需要先为操作数建模生成表达式,再建模生成整个约束的表达式,在汇编指令中,操作数主要分为三种:立即数、寄存器、内存,其中,立即数的值是固定的,不存在来源的变化,且在约束中常常作为幻数(magicnumber)仅使用一次,因而无需记录其表达式;寄存器常常涉及诸多操作,如内存读取、算术和逻辑运算、传递函数参数和返回值等,其生成的表达式被重复使用的概率很大,且来源有利于约束求解器的正确运算,因此,本实施例会记录寄存器建模生成的表达式;内存是一种宽泛的说法,实际上包含了间接寻址的内存值和编译优化的快速算术运算两种,后者常用于lea指令,由于快速运算的复杂性,本实施例不会建模该类运算,但会按照基本块访问顺序依次记录内存值建模生成的表达式,便于后续使用,使用汇编记录表达式,只需在栈内存中为操作数预留空间,随后将表达式地址写入即可;
调用类指令中,由于汇编存在语义缺失的特性,很难确定某个调用的函数数量,为了避免传递表达式时存在遗漏,将始终采用过量匹配的原则;
运算类指令中,由于建模函数库不支持浮点数的表达式建模,浮点运算指令会被忽略,运算类指令必须首先对所有的源操作数进行建模,才能进一步生成目的操作数的表达式,因为表达式为空意味着该操作数无需参与约束求解,例如,操作数A是一个与输入无关的具体值,此时由操作数A得到的运算结果同样无需参与约束求解,完成操作数的检查或建模工作后,根据助记符选择特定的运算建模函数生成表达式,并存储在目的操作数的预留空间即可;
条件跳转指令中,对于可生成约束表达式的条件跳转指令,需要根据其所依赖的运算类指令采取不同的建模方式,被条件类指令所依赖的指令可能存在操作数的表达式位数不一致的情况,主要出现在cmp指令中一个操作数为立即数、另一个操作数为寄存器或内存的场景下,因为立即数总是生成32位或64位的表达式,而寄存器或内存生成的表达式的位数由助记符的尾缀位数决定。
S5.进行基本块插桩,在基本块的出口进行辅助插桩;
具体步骤为:
S51.为当前基本块传递给后继基本块的可能被使用的表达式预留空间;
所述S51中,在访问各个函数时,预先收集基本块中use-not-define且参与赋值类指令、调用类指令、运算类指令和条件类指令的寄存器,为可能被使用的表达式预留空间,用于存放可能传递的表达式;
S52.进行空表达式区分,在基本块的出口进行辅助插桩;
所述S52中,预留空间的同时赋予该地址一个特殊值,用于判断该寄存器对应的表达式是否在前驱中被建模生成,在运算或条件类指令的操作数建模中,在判空的同时进一步判断表达式取值是否为特殊值,若是,则说明表达式并未在前驱中建模,需要在此处插桩建模生成,在基本块出口处,根据其后继基本块的use-not-define寄存器信息,将可能被使用的表达式复制到后继基本块的指定预留空间中
具体的,基本块之间的跳转可能存在隐式的数据流传递,一般来说,内存对应的表达式很少发生改变,但寄存器因其取值的频繁变化,对应的表达式也需要持续更新,一方面为了避免重复建模表达式,另一方面为了保证表达式始终具备来源信息,因此,将在跳转的同时为当前基本块的后继基本块传递可能被使用的表达式。
S6.进行函数级插桩,在函数的入口和出口进行辅助插桩;
所述S6中,默认插桩的栈内存访问方式为基于寄存器rbp向下访问,使用rbp寄存器时,修改函数的栈调整指令subq$xx,%rsp和addq$xx,%rsp,栈空间大小变更为原栈空间和插桩需使用的空间之和;使用rsp寄存器时,将寄存器rbp的值伪造为栈基址,将真实值存放在-8(rbp)位置上,当指令使用rbp真实值时,选择当前指令下处于空闲状态的寄存器作为rbp的替换对象,将其值压入栈中,随后将rbp真实值赋到该替换对象,并对指令中的操作数进行替换,在完成指令执行后,将替换对象此时的值赋到rbp真实值位置上,若存在表达式的更新,同样地将更新赋到rbp对应的表达式中,保证原函数逻辑的正常执行;
具体的,在汇编程序中,当函数内部使用栈存放局部变量,在函数的入口和出口都需要进行栈调整,程序对栈内存的访问通常有两种方式:一种是以寄存器rbp为标准向下访问,另一种是以栈顶寄存器rsp为标准向上访问,在前者中,寄存器rbp作为栈基址使用,而在后者中,寄存器rbp仅仅作为一个数据寄存器使用,为了避免插桩的栈内存访问和原函数的栈内存访问的冲突,在两种方式下,需要采取不同的手段进行栈调整和栈内存访问,本实施例默认插桩的栈内存访问方式为基于寄存器rbp向下访问,因为该方式不受栈顶变化的影响,从而简化插桩工作;
参考图4,对于使用rbp寄存器的情况,此时插桩的栈内存访问方式与原函数相同,只需在原有栈空间基础上继续向下扩展,扩展部分用于插桩存储,插桩的访问会在原空间的基础上做偏移;
参考图5,对于使用rsp寄存器的情况,此时插桩的栈访问方式与原函数相反,需要从返回地址与函数的访问空间之间扩展出一个新的空间用于插桩,在函数的入口和出口额外插入插桩的栈调整指令,以保证插桩的访问不会影响当前函数的运行、退出以及数据访问,因插桩的栈访问需要使用栈基址。
尽管根据有限数量的实施例描述了本发明,但是受益于上面的描述,本技术领域内的技术人员明白,在由此描述的本发明的范围内,可以设想其它实施例。此外,应当注意,本说明书中使用的语言主要是为了可读性和教导的目的而选择的,而不是为了解释或者限定本发明的主题而选择的。因此,在不偏离所附权利要求书的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。对于本发明的范围,对本发明所做的公开是说明性的,而非限制性的,本发明的范围由所附权利要求书限定。

Claims (8)

1.一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,包括以下步骤:
S1.访问闭源的C/C++程序中的各个用户自定义函数;
S2.访问函数中的各个基本块;
S3.顺序访问指令;
S4.进行指令级插桩,为赋值、调用、运算和条件类指令进行功能插桩;
S5.进行基本块插桩,在基本块的出口进行辅助插桩;
S6.进行函数级插桩,在函数的入口和出口进行辅助插桩。
2.根据权利要求1所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S4中,包括以下步骤:
S41.按照建模需要不同,将汇编指令分为赋值类指令、调用类指令、运算类指令和条件类指令;
S42.判断指令对应的操作数类型,为操作数建模生成表达式,再建模生成整个约束的表达式。
3.根据权利要求2所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S41中,赋值类指令为助记符为mov、lea的汇编指令,包括内存读取指令、内存写入指令、寄存器赋值和立即数赋值四种指令;调用类指令为助记符为call的指令,以及少部分助记符为jmp的指令;运算类指令为汇编中具有运算功能的所有整型指令,忽略浮点运算指令;条件类指令为条件跳转指令,忽略与路径约束不匹配的条件跳转指令。
4.根据权利要求3所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S42中,在为操作数建模生成表达式、再建模生成整个约束的表达式时,建模过程中插桩调用的函数均称为建模函数,运算类指令中称为运算建模函数,条件类指令中称为条件比较建模函数;
赋值类指令:内存读取指令中,源操作数为内存,目的操作数为寄存器,插桩调用_sym_read_memory获取源操作数对应的约束表达式,_sym_read_memory建模函数返回内存对应的表达式,若不存在则返回空指针,内存写入指令中,源操作数为立即数或寄存器,目的操作数为内存,将立即数或寄存器对应的约束表达式作为内存对应的表达式进行存储,插桩调用_sym_write_memory,_sym_write_memory建模函数会把源操作数对应的表达式写入目的操作数的预留空间内,作为目的操作数的表达式,寄存器赋值指令中,源操作数为寄存器,目的操作数为寄存器,需要插桩复制源操作数的表达式到目的操作数的预留空间内,立即数赋值指令可以留待后续约束需要时再进行建模;
调用类指令:采用过量匹配的原则,对于函数参数,在所属基本块内且不包含其他调用的情况下,按照汇编的参数传递规则,对寄存器rdi、rsi、rdx、rcx的赋值或运算将被视为存在寄存器形式的参数传递,当前四个参数存在时,若还存在push指令,将进行入栈形式的参数传递,并按照倒序确定该参数的次序,根据参数传递信息,对相应指令插桩,调用_sym_set_parameter_expression,_sym_set_parameter_expression建模函数会按照参数次序将相应表达式写入特定的地址,给予被调用者使用,对于函数返回值,在所属基本块及其后继基本块中寻找是否存在寄存器rax的use-not-define的使用,若存在,则插桩调用_sym_get_return_expression,_sym_get_return_expression建模函数会返回被调用者返回值的表达式;
运算类指令:插桩调用_sym_build_integer进行操作数建模生成表达式,_sym_build_integer运算建模函数会以操作数取值、指定的表达式位数、字节序为输入,返回生成的表达式,根据操作数的不同情况,将采取不同的建模方式,当操作数为立即数,建模生成32位或64位的立即数的表达式,当操作数为寄存器或内存,判断是否已关联表达式,若该操作数不具有相应的表达式,则需要建模生成对应位数的寄存器值的表达式,否则需要先对相应的表达式进行判空,若表达式非空,则可以直接用于后续运算的建模,否则跳过该运算的建模,完成操作数的检查或建模工作后,根据助记符选择特定的运算建模函数生成表达式,并存储在目的操作数的预留空间;
条件类指令:当操作数的表达式位数不一致,且助记符尾缀位数小于32位时,立即数操作数直接建模生成相应表达式,寄存器或内存操作数判断该操作数是否已关联表达式,若该操作数不具有相关表达式,则按照32位对操作数建模生成表达式,否则对表达式判空,若非空,则进一步扩展表达式位数,插桩调用_sym_build_sext,_sym_build_sext条件比较建模函数以表达式、扩展位数、字节序为输入,返回扩展位数后的表达式,用于后续条件比较的建模,否则,跳过该条件比较的建模,其他情况下,按照运算类指令中的操作数建模方式处理,完成操作数的检查或建模工作后,根据助记符选择特定的条件比较建模函数生成表达式,随后插桩调用_sym_push_path_constraint,_sym_push_path_constraint条件比较建模函数将以表达式为输入,把表达式传递给约束求解器并收集求解结果,用于生成新的测试用例。
5.根据权利要求4所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S5中,包括以下步骤:
S51.为当前基本块传递给后继基本块的可能被使用的表达式预留空间;
S52.进行空表达式区分,在基本块的出口进行辅助插桩。
6.根据权利要求5所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S51中,在访问各个函数时,预先收集基本块中use-not-define且参与赋值类指令、调用类指令、运算类指令和条件类指令的寄存器,为可能被使用的表达式预留空间,用于存放可能传递的表达式。
7.根据权利要求6所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S52中,预留空间的同时赋予该地址一个特殊值,用于判断该寄存器对应的表达式是否在前驱中被建模生成,在运算或条件类指令的操作数建模中,在判空的同时进一步判断表达式取值是否为特殊值,若是,则说明表达式并未在前驱中建模,需要在此处插桩建模生成,在基本块出口处,根据其后继基本块的use-not-define寄存器信息,将可能被使用的表达式复制到后继基本块的指定预留空间中。
8.根据权利要求7所述的一种基于RetroWrite框架的静态符号执行插桩方法,其特征在于,所述S6中,默认插桩的栈内存访问方式为基于寄存器rbp向下访问,使用rbp寄存器时,修改函数的栈调整指令subq$xx,%rsp和addq$xx,%rsp,栈空间大小变更为原栈空间和插桩需使用的空间之和;使用rsp寄存器时,将寄存器rbp的值伪造为栈基址,将真实值存放在-8(rbp)位置上,当指令使用rbp真实值时,选择当前指令下处于空闲状态的寄存器作为rbp的替换对象,将其值压入栈中,随后将rbp真实值赋到该替换对象,并对指令中的操作数进行替换,在完成指令执行后,将替换对象此时的值赋到rbp真实值位置上,若存在表达式的更新,同样地将更新赋到rbp对应的表达式中,保证原函数逻辑的正常执行。
CN202310598471.6A 2023-05-25 2023-05-25 一种基于RetroWrite框架的静态符号执行插桩方法 Active CN116775127B (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN202310598471.6A CN116775127B (zh) 2023-05-25 2023-05-25 一种基于RetroWrite框架的静态符号执行插桩方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN202310598471.6A CN116775127B (zh) 2023-05-25 2023-05-25 一种基于RetroWrite框架的静态符号执行插桩方法

Publications (2)

Publication Number Publication Date
CN116775127A true CN116775127A (zh) 2023-09-19
CN116775127B CN116775127B (zh) 2024-05-28

Family

ID=87988714

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202310598471.6A Active CN116775127B (zh) 2023-05-25 2023-05-25 一种基于RetroWrite框架的静态符号执行插桩方法

Country Status (1)

Country Link
CN (1) CN116775127B (zh)

Citations (13)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104375941A (zh) * 2014-12-11 2015-02-25 无锡江南计算技术研究所 可执行程序测试用例集二进制代码覆盖率自动化评估方法
WO2015062369A1 (zh) * 2013-11-04 2015-05-07 华为技术有限公司 轮廓技术编译的优化方法及装置
CN104794401A (zh) * 2015-04-15 2015-07-22 南京大学 一种静态分析辅助的符号执行漏洞检测方法
CN104965788A (zh) * 2015-07-03 2015-10-07 电子科技大学 一种代码静态检测方法
CN106354630A (zh) * 2016-08-23 2017-01-25 电子科技大学 一种基于动态符号执行的软件缺陷检测方法
US20180068121A1 (en) * 2016-09-02 2018-03-08 Bae Systems Information And Electronic Systems Integration Inc. Automated reverse engineering
CN110187884A (zh) * 2019-06-04 2019-08-30 中国科学技术大学 一种多线程应用场景下的访存指令插桩优化方法
CN111859388A (zh) * 2020-06-30 2020-10-30 广州大学 一种多层次混合的漏洞自动挖掘方法
CN112162932A (zh) * 2020-10-30 2021-01-01 中国人民解放军国防科技大学 一种基于线性规划预测的符号执行优化方法及装置
CN112905184A (zh) * 2021-01-08 2021-06-04 浙江大学 一种基于插桩的基本块粒度下工控协议语法逆向分析方法
CN115237405A (zh) * 2022-06-14 2022-10-25 华中科技大学 指令级代码复用分析方法及指令级代码复用方法
CN115712568A (zh) * 2022-11-22 2023-02-24 中国人民解放军国防科技大学 一种基于浮点格式感知模糊测试的浮点异常检测方法
CN115878498A (zh) * 2023-03-03 2023-03-31 中国电子科技集团公司第三十研究所 一种基于机器学习预测程序行为的关键字节提取方法

Patent Citations (13)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
WO2015062369A1 (zh) * 2013-11-04 2015-05-07 华为技术有限公司 轮廓技术编译的优化方法及装置
CN104375941A (zh) * 2014-12-11 2015-02-25 无锡江南计算技术研究所 可执行程序测试用例集二进制代码覆盖率自动化评估方法
CN104794401A (zh) * 2015-04-15 2015-07-22 南京大学 一种静态分析辅助的符号执行漏洞检测方法
CN104965788A (zh) * 2015-07-03 2015-10-07 电子科技大学 一种代码静态检测方法
CN106354630A (zh) * 2016-08-23 2017-01-25 电子科技大学 一种基于动态符号执行的软件缺陷检测方法
US20180068121A1 (en) * 2016-09-02 2018-03-08 Bae Systems Information And Electronic Systems Integration Inc. Automated reverse engineering
CN110187884A (zh) * 2019-06-04 2019-08-30 中国科学技术大学 一种多线程应用场景下的访存指令插桩优化方法
CN111859388A (zh) * 2020-06-30 2020-10-30 广州大学 一种多层次混合的漏洞自动挖掘方法
CN112162932A (zh) * 2020-10-30 2021-01-01 中国人民解放军国防科技大学 一种基于线性规划预测的符号执行优化方法及装置
CN112905184A (zh) * 2021-01-08 2021-06-04 浙江大学 一种基于插桩的基本块粒度下工控协议语法逆向分析方法
CN115237405A (zh) * 2022-06-14 2022-10-25 华中科技大学 指令级代码复用分析方法及指令级代码复用方法
CN115712568A (zh) * 2022-11-22 2023-02-24 中国人民解放军国防科技大学 一种基于浮点格式感知模糊测试的浮点异常检测方法
CN115878498A (zh) * 2023-03-03 2023-03-31 中国电子科技集团公司第三十研究所 一种基于机器学习预测程序行为的关键字节提取方法

Non-Patent Citations (3)

* Cited by examiner, † Cited by third party
Title
CHEN RD等: "Analysis of the Automatic Test Generation Tool:CREST", 《IEEE》, 27 March 2018 (2018-03-27) *
牛伟纳;丁雪峰;刘智;张小松;: "基于符号执行的二进制代码漏洞发现", 计算机科学, no. 10, 15 October 2013 (2013-10-15) *
陈荔城;崔泽汉;包云岗;陈明宇;沈林峰;梁祺;: "一种监测函数语义信息访存地址序列的方法", 计算机研究与发展, no. 05, 15 May 2013 (2013-05-15) *

Also Published As

Publication number Publication date
CN116775127B (zh) 2024-05-28

Similar Documents

Publication Publication Date Title
US7380242B2 (en) Compiler and software product for compiling intermediate language bytecodes into Java bytecodes
US8276130B2 (en) Method and compiler of compiling a program
US9495136B2 (en) Using aliasing information for dynamic binary optimization
JPH09330233A (ja) 最適目的コード生成方法
US8997066B2 (en) Emulating pointers
US7949848B2 (en) Data processing apparatus, method and computer program product for reducing memory usage of an object oriented program
US7823140B2 (en) Java bytecode translation method and Java interpreter performing the same
US20040003377A1 (en) Converting byte code instructions to a new instruction set
US20070011664A1 (en) Device and method for generating an instruction set simulator
Hummel et al. Annotating the Java bytecodes in support of optimization
AU2891900A (en) Method and apparatus for handling exceptions as normal control flow
JP2007286671A (ja) ソフトウェア/ハードウェア分割プログラム、および分割方法。
US7028293B2 (en) Constant return optimization transforming indirect calls to data fetches
Aho Compilers: Principles, Techniques and Tools (for VTU)
US20050015754A1 (en) Method and system for multimode simulator generation from an instruction set architecture specification
JP2005501334A (ja) Javaコンピューティング環境におけるJavaマクロインストラクションの生成のためのフレームワーク
CN117591174A (zh) 一种基于编译器拓展的avx2sve代码移植及优化方法
CN107729118A (zh) 面向众核处理器的修改Java虚拟机的方法
US11886839B2 (en) Non-transitory computer-readable recording medium, function generation method, and information processing device
CN116775127B (zh) 一种基于RetroWrite框架的静态符号执行插桩方法
US11635947B2 (en) Instruction translation support method and information processing apparatus
JPH10320212A (ja) キャッシュ向け最適化方法
Dillig et al. SAIL: Static analysis intermediate language with a two-level representation
Brunthaler Purely interpretative optimizations
US20040098708A1 (en) Simulator for software development and recording medium having simulation program recorded therein

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination
GR01 Patent grant
GR01 Patent grant