question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot successfully end Symbolic execution for statically compiled 64bit ELF

See original GitHub issue

Hello, I have a 64biy ELF compiled statically with GCC, not stripped. Source can be viewed here, C program below. I’m trying to log all syscalls from symbolic execution.

Using strace in linux I’m getting following syscalls:

execve("./if_else_static", ["./if_else_static"], ...OMITTED...) = -1 EINVAL (Invalid argument)
brk(NULL)                               = 0x1c23000
brk(0x1c241c0)                          = 0x1c241c0
arch_prctl(ARCH_SET_FS, 0x1c23880)      = 0
uname({sysname="Linux", nodename="OMITTED", release="5.4.0-72-generic", version="OMITTED", machine="x86_64", domainname="(none)"}) = 0
readlink("/proc/self/exe", "/home/OMITTED/OMITTED/if_else_static", 4096) = 70
brk(0x1c451c0)                          = 0x1c451c0
brk(0x1c46000)                          = 0x1c46000
mprotect(0x4dc000, 12288, PROT_READ)    = 0
fstat(0, {OMITTED}) = 0
read(0, "4\n", 1024)                    = 2
fstat(1, {OMITTED}) = 0
write(1, "ne, 52\n", 7)                 = 7
lseek(0, -1, SEEK_CUR)                  = -1 ESPIPE (Illegal seek)
exit_group(0)                           = ?

First issue I ran into was that the readlink system call was not implemented so program stuck at the infinite loop. I have implemented readlink syscall (SimProcedure is below), and added it successfully to the framework.

class readlink(SimProcedure):
    def run(self, pathname, buf, bufsiz):
        elf_path = (os.getcwd() + "/" + self.state.project.filename).encode('utf-8')
        buffsize_int = self.state.solver.eval(bufsiz)
        elf_path_bvv = claripy.BVV(value=elf_path, size=len(elf_path) * 8)
        store_size = min(buffsize_int, len(elf_path))
        #addr, data, size=None
        self.state.memory.store(addr=buf, data=elf_path_bvv, size=store_size)
        l.debug('readlink: {} : {} : {} | {}'.format(pathname, buf, buffsize_int, buffsize_int))
        return len(elf_path)

Later on, I’ve tried to run a simulation with following code:

def syscall_action_builder(fd):
    # Function logs syscall name, params and return value
    def syscall_action_func(state):
        simproc = state.inspect.simprocedure
        return_value = ret_val_to_str(simproc.ret_expr)
        args_string = ','.join([bitvec_to_str(simproc.arg(i)) for i in range(0, simproc.num_args)])
        fd.write("{}:{}:{}:{}\n".format(simproc.library_name, simproc.display_name, args_string, return_value))
        fd.flush()
    return syscall_action_func


if __name__ == '__main__':
    RESULTS_DIR = 'results/'
    BIN_DIR = 'examples/bin/'
    FILE_NAME = 'if_else_static'

    trace_fd = open(RESULTS_DIR + FILE_NAME + '_bp.systrace', 'w')

    proj = angr.Project(BIN_DIR + FILE_NAME, load_options={'auto_load_libs': True, 'except_missing_libs': True},
                        use_sim_procedures=False)

    start_state = proj.factory.entry_state()

    start_state.inspect.b('syscall', when=angr.BP_AFTER, action = syscall_action_builder(trace_fd))

    simgr = proj.factory.simgr(start_state)
    simgr.explore()

But simulation ends with 14 ‘errored’ states.

First 12 are <State errored with “Page is already mapped”> at the address 0x70018e. Block of the states looks like: 0x70018e: add byte ptr [rax], al, from address 0x70018e to 0x700228. Following syscalls are logged:

linux:geteuid::int,1000
linux:getuid::int,1000
linux:getegid::int,1000
linux:getgid::int,1000
linux:arch_prctl:<64,12289>,<64,576460752303357648>:int,22
linux:brk:<64,0>:BVV,64,5124096
linux:brk:<64,5128640>:BVV,64,5128640
linux:arch_prctl:<64,4098>,<64,5126272>:int,0
linux:uname:<64,576460752303357104>:int,0
linux:readlink:<64,5036867>,<64,576460752303353232>,<64,4096>:int,67
linux:readlink:<64,5036867>,<64,576460752303353232>,<64,4096>:int,67
linux:mprotect:<64,5095424>,<64,12288>,<64,1>:int,0
linux:mprotect:<64,5095424>,<64,12288>,<64,1>:int,0

As you can see, execution didn’t reach scanf function. With objectdump I cannot access these addresses, and I don’t see what’s happening.

The other 2 states have <State errored with "IR decoding error at 0x46cca9>, and that IR is rdsspq %rax. It seems like VEX doesn’t support this IR.

Do you have any ideas?

Later I tried to start from main function. I’ve set start_state = proj.factory.blank_state(addr=0x401d05). This time I only logged: <SimProcedure fstat (syscall)> syscall, and it ended with only one ‘errored’ state: <State errored with "Cannot execute following jumpkind Ijk_SigSEGV">. State got error 0x410f76 on block:

0x410f76:	movaps	xmmword ptr [rbp - 0x600], xmm1
0x410f7d:	mov	qword ptr [rbp - 0x598], rax
0x410f84:	mov	eax, dword ptr [rdi + 0xc0]
0x410f8a:	test	eax, eax
0x410f8c:	jne	0x411610

How can I fix this?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:12 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
rhelmotcommented, Apr 29, 2021

I found a bug in our implementation of brk which allows the execution to continue. Now it produces a large number of active paths. Try out the branch linked above.

1reaction
rhelmotcommented, Apr 29, 2021

I am not sure. I will look into your example. I missed that part of your original post until just now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot successfully end Symbolic execution for statically compiled ...
Hello, I have a 64biy ELF compiled statically with GCC, not stripped. Source can be viewed here, C program below. I'm trying to...
Read more >
How to wrap run functions? · Issue #2603 · angr/angr - GitHub
Hello, I'm trying to log system call traces which are simulated during symbolic execution of ELF file.
Read more >
Docker Alpine executable binary not found even if in PATH
Use statically linked executables. Static executables don't carry dynamic dependencies and could run on any Linux.
Read more >
The 101 of ELF files on Linux: Understanding and Analysis
An step-by-step introduction into ELF files. Learn the structure and format, to understand how binaries and libraries on Linux systems work.
Read more >
Close Encounters with Symbolic Execution (Part 2)
This is part two of a two-part blog post that shows how to use KLEE with mcsema to symbolically execute Linux binaries (see...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found