3 ms·
Always cool to see people hacking ELF! I see you're using argv[0] to find the executable file. This is fragile because argument vector contents are arbitrary an
by matheusmoreira 1y ago
Always cool to see people hacking ELF! I see you're using argv[0] to find the executable file. This is fragile because argument vector contents are arbitrary and controlled entirely by the parent process. In other words, argv[0] could contain anything, even an empty string. If you're targeting Linux specifically, there's a better way: /proc/self/exe.
I created something similar to your tool: an ELF embedder. It's for arbitrary data rather than native code injection.
I leveraged ELF segments to get the kernel to mmap the data into memory on my behalf, no file I/O needed. The auxvec allows the program to reach its own program header table. From there it's just a matter of finding the right segment.
https://www.matheusmoreira.com/articles/self-contained-lone-lisp-applications https://www.matheusmoreira.com/articles/self-contained-lone-...
My programming language's interpreter introspects into its own ELF header, finds the embedded segments and uses them to load data and code from inside itself.
I'm not entirely sure whether this approach is applicable to your case but it might be worth a try. My embedding tool could just as easily map in executable segments.
- dillstead 1y agoGood point! I was aware that there are certain circumstances in which argv[0] might not contain the path to the executable but I didn't bother to look for an alternative. When I get a chance, I'll incorporate your suggestion. Thanks. Thanks for sending your link, I'll take a look.
- wahern 1y agoIME it's far more likely for a program to run in an environment lacking /proc (e.g. some containers) than for argv[0] to be NULL, empty, or lying. Even /proc/self/exe can been used in an exploit chain (https://lwn.net/Articles/920384/ https://lwn.net/Articles/920384/). And there have been many other /proc-related exploits, which is why it's often a good idea to not even mount /proc at all rather than just mask /proc subtrees. But even if /proc/self/exe is visible, it might not be possible to open it. For example, you can execute a binary residing in anonymous memory (memfd) using fexecve(2), or the executable file could have been deleted immediately after execution. AFAIU, /proc/self/exec is generated as a symlink rather than exposing the file object directly (cf. BSD /dev/fd), so opening it can fail. The easy fix is to just simply fail if argv[0] is NULL or empty, but if one is a glutton for punishment and wants to be "robust", /proc/self/exe support could be added as a (preferred) alternative rather than a substitute mechanism.
- wahern 1y agoEDIT: I was wrong, /proc/self/exe is directly openable, even if the path returned by readlink doesn't exist.