diff options
Diffstat (limited to 'hypodermic')
| -rw-r--r-- | hypodermic/process.py | 29 | ||||
| -rw-r--r-- | hypodermic/shellcode.py | 40 |
2 files changed, 68 insertions, 1 deletions
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) |