diff options
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | hypodermic/main.py | 5 | ||||
| -rw-r--r-- | hypodermic/ptrace.py | 26 |
3 files changed, 33 insertions, 3 deletions
@@ -31,7 +31,8 @@ memory is far more complicated than calling mmap(2) on the file. The second iteration also involves injecting code into the inferior process, but instead maps the Linux runtime linker into memory to make use of its existing -GOT/PLT setup functionality. +GOT/PLT setup functionality. This involves injecting auxiliary vectors onto the +stack in an attempt to trick the RTLD. ## Important Resources @@ -40,6 +41,7 @@ GOT/PLT setup functionality. * [Runtime Process Infection][5] * [ELF Program Header][6] * [Dynamic Loader Operation][7] +* [About ELF Auxiliary Vectors][8] [1]: https://github.com/gaffe23/linux-inject @@ -49,3 +51,4 @@ GOT/PLT setup functionality. [5]: http://phrack.org/issues/59/8.html [6]: http://www.sco.com/developers/gabi/latest/ch5.pheader.html [7]: https://sourceware.org/glibc/wiki/DynamicLoader +[8]: http://articles.manugarg.com/aboutelfauxiliaryvectors diff --git a/hypodermic/main.py b/hypodermic/main.py index 0f77de5..635e3a7 100644 --- a/hypodermic/main.py +++ b/hypodermic/main.py @@ -55,9 +55,14 @@ def main(): usage="%(prog)s [-a pid] [-c path] [options]", description="Don't share needles, brah!" ) + parser._positionals.title = "Positional Arguments" parser._optionals.title = "Optional Arguments" parser.add_argument( + "target", + help="The target shared object to inject." + ) + parser.add_argument( "-q", "--quiet", help="Suppress everything but critical output" diff --git a/hypodermic/ptrace.py b/hypodermic/ptrace.py index c77fb8e..714b567 100644 --- a/hypodermic/ptrace.py +++ b/hypodermic/ptrace.py @@ -19,8 +19,9 @@ import ctypes import os.path +import re -from hypodermic.memory import maps +from hypodermic.memory import Region, maps class Process(object): @@ -103,5 +104,26 @@ class Process(object): raise OSError("Could not continue") @property - def maps(self): + def maps(self) -> list: + """Obtain the process' memory map. + + Returns: + A list of Region objects. + """ return maps(self.pid) + + # FIXME: This approach does not work outside of seeing if the + # process has an RTLD page. The reality is that the RTLD is + # broken up into independent several pages. + @property + def rtld(self) -> Region: + """Obtain the region of memory for the process' RTLD, if it + exists. + + Returns: + The Region object belonging to the RTLD, or None if no + RTLD was found. + """ + for region in self.maps: + if re.search(r"ld.+\.so", region.path): + return region |