oyente 符号执行和检测部分代码分析
符号执行和检测部分
oyente.symExec:run
前面讲到 oyente.oyente:analyze_bytecode 中为 symExec.run 传入反汇编文件,进行后续操作。
在不是 is_testing_evm 测试 evm
的情况下,关键函数有以下三个:
analyze()、 detect_vulnerabilities()、closing_message()
oyente.symExec:analyze
好多函数中都有一个函数内的嵌套函数定义: timeout_cb() ,
其内容为 DEBUG mode 时的 traceback1,作用:便于调试时,一层层显示信息。
Ps: 这里还使用的是嵌套函数,
Python 嵌套函数 在 Python 函数中定义嵌套函数
analyze() 函数的作用时,生成 CFG 控制流图,并分析
run_build_cfg_and_analyze ,如有异常,则抛出。而
run_build_cfg_and_analyze 函数中
initGlobalVars()初始化约束求解器,设置超时2
如果是并行的话,设置 simplify(简化)、solve-eqs(高斯消元)、smt(提供一个基于 SMT 的 solver)策略,还会把 goal 分解成子 goal
ParThen:Return a tactic that applies t1 and then t2 to every subgoal produced by t1. The subgoals are processed in parallel. The tactic split-clause will select a clause (or f_1 ... f_n) in the input goal, and split it n subgoals.
如果反汇编文件中有 MSIZE,则将对应标志设置为 True
MSIZE 为操作码之一,含义为:size of memory, i.e. largest accessed memory index。 0.4.24 的 opcode 列表
初始化 explorer 相关
大致有一下(没写全): | 变量 | 含义| |----|---| |
visited_pcs| 访问过的路径的集合| |vertices|顶点字典| |edges|边字典| |visited_edges|访问过的边的字典| |calls_affect_state| call 影响的状态?不太清楚| |money_flow_all_paths| 金钱流列表| |reentrancy_all_paths| 重入流列表| |path_conditions| 路径条件列表| |global_problematic_pcs| 检测的漏洞的列表组成的字典|符号变量的名字生成器 还有 USE_GLOBAL_BLOCKCHAIN: 是否使用区块链全局状态 和 REPORT_MODE:是否生成报告
instructions: capturing all the instructions, keys are corresponding addresses
build_cfg_and_analyze()timeout to run symbolic execution
在
global_params.py中定义的GLOBAL_TIMEOUT = 50, 如果超时,则标记超时,且抛出超时异常change_format()整理、简化反汇编文件的格式- 替换一些 evm 未实现的反汇编为指令
- 简化每一行
00002: PUSH1 0x80变成2 PUSH1 => 0x80 - 然后写回反汇编源文件
读取上一步处理好的反汇编文件,并去除首行 runtimecode
tokenize 模块提供语法、语义扫描解析3
it breaks a stream of bytes into Python tokens. It decodes the bytes according to PEP-0263 fordetermining source file encoding
collect_vertices貌似看不太懂?- Parse the disassembled file
- Then identify each basic block (i.e. one-in, one-out)
- Store them in vertices
construct_bb构建基本块construct_static_edges构建静态边full_sym_exec符号执行检测get_init_global_state初始化当前状态global_state 有调用与被调用者余额,
global_state["balance"]["Is"或"Ia"],pc(程序计数器),接受和发送者地址,时间戳等init_analysis初始化分析相关参数创建 params 对象,而且把上两步的全局状态和 analysis 对象增加为该对象的属性。
sym_exec_block符号执行块, 是个递归计数和检查最大边界
- 对 current_edge 的访问次数计数
- 判断 current_edge 访问次数是否超过 LOOP_LIMIT,如果超过,则返回 stack - [ ] 这里为什么要返回 stack
- 判断使用的 gas 是否超过 GAS_LIMIT,如果超过,则返回 stack
执行块中的指令
循环遍历块的指令列表,每次执行一条,执行指令调用:
sym_exec_ins()将当前块标记为已访问
漏洞路径更新
将路径加入重入漏洞路径?(怎么就直接加入了,哪里检测了?) 如果当前 money_flow 路径在全部 money 漏洞中不存在,则更新相关路径。
Go to next Basic Block(s)
根据跳转类型,选择块,然后更新相关条件,然后递归。 跳转类型:
terminal、unconditional、falls_to、conditional1. 终止类型或者深度超过 DEPTH_LIMIT,则终止该路径,并 display_analysis money flow相关? - [ ] 为什么 2. 无条件,则更新相关参数,然后直接跳转 3. follow to 的同上 4. 有条件跳转 采用 DFS 深度优先搜索递归遍历 先检查左节点,如果约束有解,则向左递归,直到叶子节点,然后回退一个节点,走右边节点,若约束有解,则进入右边节点。
sym_exec_ins 符号执行指令
模拟执行指令 opcode
detect_vulnerabilities instruction 是一个以
{指令地址:指令}的字典- 计算代码覆盖率,evm_code_coverage
- 分别检测漏洞,将结果放如 result 二维列表
- vulnerability_found 没有看懂
closing_message 分析结束,根据全局变量 STORE_RESULT 觉得那个是否存储分析结果。