Nan ZoE <zoen...@gmail.com> wrote: > Additionally, it's reasonable to assess the correctness of the ROP payloads > we generate for a program by injecting vulnerabilities. Firstly, the > original gadget set in the program remains intact and usable. Secondly, > this method of injecting vulnerabilities is equivalent to assuming the > existence of easily exploitable ROP attack vulnerabilities in the program.
You are using the word "exploitable" again, which is incorrect terminology. It is not the same at all. You have not just disabled all address space layout control, but also pledge and unveil, and I'm sure there are other things you have disabled but not mentioned. The syntheticness of your test is removing mitigations you aren't even aware of. > In both cases, the ROP payloads can be executed, and the gadgets in these > ROP payloads are all from the original program. In other words, if a > program has vulnerabilities that require ROP attack techniques, then the > ROP payloads generated by our tool are entirely applicable. > > In our experiments, we extracted over a thousand programs from OpenBSD, and > while most of them do not have syscall instruction gadgets, there are still > more than 240 programs that contain syscall instruction gadgets. This is > confirmed by various tools such as ropper <https://github.com/sashs/Ropper>and > ROPgadget <https://github.com/JonathanSalwan/ROPgadget> that we used to > extract gadget sets. Even in cases where programs are dynamically linked, > the syscall instructions are not solely located within their ld.so. The following diff will be commited soon. I forgot to run pinsyscall() in static binaries which don't actually call execve(), as a result in those static binaries any syscall instruction would work, rather than just the precise one assigned by pinsyscall(SYS_execve, ...). With this diff such programs no longer have a viable syscall instructions which will reach execve(2). The programs improved tend to be boring programs which run without any privilege which could be "exploited". This change makes it impossible to call execve() syscall in most of /bin and /sbin (your list of 240 will shrink), and a couple static binaries in /usr/*bin/. A majority of those programs call pledge() without "exec" early during startup, so your synthetic results of exploiting programs before they actually run main() was already highly misleading. Index: dlfcn/init.c =================================================================== RCS file: /cvs/src/lib/libc/dlfcn/init.c,v retrieving revision 1.18 diff -u -p -u -r1.18 init.c --- dlfcn/init.c 27 Feb 2023 15:00:17 -0000 1.18 +++ dlfcn/init.c 12 Oct 2023 14:22:09 -0000 @@ -154,6 +154,11 @@ _libc_preinit(int argc, char **argv, cha extern const int _execve_size; pinsyscall(SYS_execve, &HIDDEN(execve), _execve_size); + } else { + static const int not_syscall; + + /* Static binary which does not use execve() */ + pinsyscall(SYS_execve, (void *)¬_syscall, 1); } #endif }