trailofbits / maat

Open-source symbolic execution framework: https://maat.re
Other
614 stars 44 forks source link

Improvements needed to run `/bin/id` from binutils #93

Open thealberto opened 2 years ago

thealberto commented 2 years ago

Hi, I would like to use maat with simple projects but I have troubles running, for instance, id. My code is the following:

from maat import *
m = MaatEngine(ARCH.X64, OS.LINUX)  
m.load("/bin/id", BIN.ELF64, libdirs=["/usr/lib/x86_64-linux-gnu/"])
m.run()

and the output is the following

➜  maat python3 id.py
[Info] Adding object 'ld-linux-x86-64.so.2' to virtual fs at '/usr/lib/ld-linux-x86-64.so.2'
[Info] Adding object 'libc.so.6' to virtual fs at '/usr/lib/libc.so.6'
[Info] Adding object 'libdl.so.2' to virtual fs at '/usr/lib/libdl.so.2'
[Info] Adding object 'libpcre2-8.so.0' to virtual fs at '/usr/lib/libpcre2-8.so.0'
[Info] Adding object 'libpthread.so.0' to virtual fs at '/usr/lib/libpthread.so.0'
[Info] Adding object 'libselinux.so.1' to virtual fs at '/usr/lib/libselinux.so.1'
[Info] Adding object 'id' to virtual fs at '/id'
[Error] Exception in CALLOTHER handler: SYSCALL: EnvEmulator: syscall '218' not supported for emulation
[Error] Unexpected error when processing IR instruction, aborting...
➜  maat 

Would it be hard to add the support for the missing system call?

Thanks

Boyan-MILANOV commented 2 years ago

Hi Alberto,

Syscall 218 is set_tid_address which is related to thread management. Maat doesn't support multithreading yet so this type of syscall should be safe to ignore.

We can probably implement some trivial handlers that make it seem like this syscall (and some related ones like gettid, maybe some others) behaves as if it succeeded in the kernel. It's fairly easy to add new syscalls (https://github.com/trailofbits/maat/blob/master/src/env/emulated_syscalls/linux_syscalls.cpp) so I put this in the TODO list but tag it as "good first issue" if someone wants to make an easy first contribution :)

integeruser commented 2 years ago

After some tests, running /bin/id seems to require (at least):

Boyan-MILANOV commented 2 years ago

Adding Python bindings to map /etc/shadow, /etc/group to the virtual fs

I can take care of this

Supporting directories in fstatat() (e.g. newfstatat(AT_FDCWD, "/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) as seen in strace /bin/id)

I thought we supported those when AT_FDCWD is passed but will look into it.

Supporting CMOV, CX8, FPU, FXSR CPU features to reach the baseline ISA level (otherwise /usr/lib/libc.so.6: CPU ISA level is lower than required)

They are described in table 2-27 of Intel Advanced Vector Extensions Programming Reference. I think Maat/sleigh already support them, but we should also set the corresponding flags to 1 in the CPUID handler.

integeruser commented 2 years ago

(FYI I also tried enabling the CPU features in X86_CPUID_handler() by setting the missing bits, but then running /usr/bin/whoami symbolically triggers:

FATAL: Error in sleigh translate(): Can not lift instruction at 0x40b4aad: PMAXUB XMM3, XMM0 (unsupported callother occurence)
[Fatal] Lifter error: MaatEngine::run(): failed to lift instructions

and I didn't investigate further.)

Boyan-MILANOV commented 2 years ago

Ugh - some instructions must still be unsupported by sleigh then. We should check whether updating to latest sleigh would add support for those (see #105), and if not we can write the sleigh spec for missing instructions.

Boyan-MILANOV commented 2 years ago

FYI: I renamed the issue since we are actually discussing several issues in here

integeruser commented 2 years ago

With the latest additions from the related PR emulation of /bin/id on my Debian machine completes successfully, although with a slightly different output than the typical (e.g. uid=0 gid=0 groups=0 instead of uid=0(root) gid=0(root) groups=0(root)). I think a different code path is taken because the emulated fstatat(AT_FDCWD, "/", ...) returns ENOENT instead of success.

integeruser commented 2 years ago

After some more tests, the last fixes required to properly emulate /bin/id are:

Tested with the following snippet:

m = MaatEngine(ARCH.X64, OS.LINUX)
m.env.fs.add_real_file("/lib/x86_64-linux-gnu/libnss_files.so.2", "/usr/lib/libnss_files.so.2")
m.env.fs.add_real_file("/etc/nsswitch.conf", "/etc/nsswitch.conf")
m.env.fs.add_real_file("/etc/group", "/etc/group")
m.env.fs.add_real_file("/etc/passwd", "/etc/passwd")
m.load("/bin/id", BIN.ELF64, libdirs=["/lib/x86_64-linux-gnu/"])
m.run()