diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | hypodermic/process.py | 29 | ||||
| -rw-r--r-- | hypodermic/shellcode.py | 40 |
3 files changed, 70 insertions, 1 deletions
@@ -46,6 +46,7 @@ stack in an attempt to trick the RTLD. * [Dynamic Loader Operation][8] * [About ELF Auxiliary Vectors][9] * [Code Injection into Running Linux Application][10] +* [Special Sections][11] [1]: https://github.com/gaffe23/linux-inject @@ -58,3 +59,4 @@ stack in an attempt to trick the RTLD. [8]: https://sourceware.org/glibc/wiki/DynamicLoader [9]: http://articles.manugarg.com/aboutelfauxiliaryvectors [10]: https://www.codeproject.com/Articles/33340/Code-Injection-into-Running-Linux-Application +[11]: http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/specialsections.html diff --git a/hypodermic/process.py b/hypodermic/process.py index 1e2c1d4..bfb1013 100644 --- a/hypodermic/process.py +++ b/hypodermic/process.py @@ -22,7 +22,7 @@ import os.path import re from hypodermic.memory import Region, maps -from hypodermic.shellcode import assemble +from hypodermic.shellcode import assemble, open_shellcode _AMD64_INDICES = { "r15": 0, @@ -338,6 +338,33 @@ class Process(object): after = [self.get_register(reg) for reg in preserve] return before, after + def open(self, path: str) -> int: + """Attempts to open a file descriptor within the inferior. + + Args: + path (str): The path of the file to open. + + Raises: + OSError: If the path cannot be opened. + + Returns: + The file descriptor. + """ + if self.arch == "x64": + old_rax = self.get_register("rax") + self.run_code(open_shellcode(path), preserve=["rax"]) + fd = self.get_register("rax") + self.set_register("rax", old_rax) + else: + old_eax = self.get_register("eax") + self.run_code(open_shellcode(path, arch="i386"), preserve=["eax"]) + fd = self.get_register("eax") + self.set_register("eax", old_eax) + + if fd < 0: + raise OSError("Couldn't open {}".format(path)) + return fd + @property def arch(self) -> str: """Returns the architecture of the host processor. diff --git a/hypodermic/shellcode.py b/hypodermic/shellcode.py index 0a35e0a..75ab4ad 100644 --- a/hypodermic/shellcode.py +++ b/hypodermic/shellcode.py @@ -39,3 +39,43 @@ def assemble(code: str, arch="amd64", syntax="att") -> bytes: ks.syntax = keystone.KS_OPT_SYNTAX_ATT encoded, _ = ks.asm(code) return bytes(encoded) + + +# FIXME: Relative addressing is untested in i386. +def open_shellcode(path: str, flags=0, arch="amd64") -> bytes: + """Generates shellcode to open a file descriptor. + + Args: + path (str): The path of the file to open. + flags (:obj:`int`, optional): Flags to pass to open. Defaults to + O_RDONLY. + arch (:obj:`str`, optional): The target architecture. + Defaults to "amd64". + + Returns: + The assembled shellcode, as a `bytes` object. + """ + if arch == "amd64": + asm = " jmp __path_end;" \ + "__path:" \ + " .asciz \"{}\";" \ + "__path_end:" \ + " movq $0x02, %rax;" \ + " leaq (%rip), %rdi;" \ + " subq $. - __path, %rdi;" \ + " movq ${}, %rsi;" \ + " movq $0x00, %rdx;" \ + " syscall;".format(path, flags) + else: + asm = " jmp __path_end;" \ + "__path:" \ + " .asciz \"{}\";" \ + "__path_end:" \ + " movl $0x05, %eax;" \ + " call $. + 5;" \ + " popl %ebx;" \ + " subl $. - 4 - __path, %ebx;" + " movl ${}, %ecx;" \ + " movl $0x00, %edx;" \ + " int $0x80;".format(path, flags) + return assemble(asm, arch) |