无法为 Linux ELF 二进制

问题描述

我正在使用最新版本的 angr (9,'gitrollling')。 [我在 angr 版本 (9,4663) 中得到相同的行为]。

我使用 gcc 9.3.0 为这个简单的 C 程序创建了一个 ELF 二进制文件

float func3(float y) {
  float temp = 5.5; // expected angr to find this constant
  return y + temp;
}

int main(int argc,char *argv[]) {
  float ans;
  ans = func3(2.2); // expected angr to find this constant
}

然后我使用 angr 提取函数中的常量(即“func3”和“main”)以及函数的参数数量。不幸的是,我为常量(下面输出中的“const”)或“argc”得到的答案毫无意义。我得到:

name main const [8,32,8,18446744073709551596,18446744073709551584,4202504,4198767,128,4198697,18446744073709551612,128] argc -1 

name func3 const [8,4202500,128] argc -1 

我的 angr 代码

#!/usr/bin/env python3

import angr
from angrutils import *

def get_attributes(cfg,addr):
    if addr in cfg.kb.functions:
        func = cfg.kb.functions.get_by_addr(addr)
        if func:
            name = func.demangled_name
            if name != 'main' and name != 'func3':
                return # only care about these 2 funcs
            const = func.code_constants
            argc = len(func.arguments) if func.arguments else -1
            print('  name %s const %s argc %s ' % (name,const,argc))
    return

proj = angr.Project('simple',main_opts={'backend': 'elf'},load_options={'auto_load_libs':False})
main = proj.loader.main_object.get_symbol('main')

start_state = proj.factory.blank_state(addr=main.rebased_addr)
start_state.stack_push(0x0)
with hook0(proj):
    cfg = proj.analyses.CFGFast()  # using CFGEmulated() also does not change the answer!
    #cfg = proj.analyses.CFGEmulated(fail_fast=False,starts=[main.rebased_addr],context_sensitivity_level=1,enable_function_hints=False,keep_state=True,enable_advanced_backward_slicing=False,enable_symbolic_back_traversal=False,normalize=True)

d=dict()
for src,dst in cfg.kb.functions.callgraph.edges():
    if not d.get(src):             # only need to do this once.
        src_attr = get_attributes(cfg,src)
        d[src] = True              # mark completed
    if not d.get(dst):             # only need to do this once.
        dst_attr = get_attributes(cfg,dst)
        d[dst] = True              # mark completed

我哪里出错了?

解决方法

我没有使用 angr 的经验,但根据检查为您的程序生成的程序集,我对出了什么问题有一些假设:

  1. func3 没有副作用并且 main 不使用 ans 的值,因此编译器可以完全消除对 func3 的调用,例如在 x86-64 上,main

    main:
        movl $0,%eax
        ret
    

    所以常量 2.2 可能根本不在可执行文件中。

  2. 浮点常量通常必须发送到内存中并通过引用加载,例如在 x86-64 上,我得到了 func3 的这个程序集:

    .section .text
    func3:
        addss   .LC0(%rip),%xmm0
        ret
    .section .rodata
    .LC0:
        .long 1085276160
    

    在完全链接的可执行文件中,交叉引用 .LC0 变成了相对偏移:

    1125:       f3 0f 58 05 d7 0e 00 00  addss  0xed7(%rip),%xmm0
    112d:       c3                       retq   
    

    有可能 angr 不将此偏移量识别为要提取的常量,或者它可以提取此偏移量而不是它引用的 .rodata 中的值。即使它可以提取 .rodata 中的值,它知道该值应该被解释为单精度浮点数而不是整数的唯一方法是它是否解码了使用该值的指令。