From a4365445d4d32001362f6e8bfae93a3b8f152fde Mon Sep 17 00:00:00 2001 From: jakob Date: Mon, 28 Aug 2017 14:32:57 -0400 Subject: Initial implementation of the ptrace wrapper --- .gitignore | 1 + hypodermic/ptrace.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- wrapper/Makefile | 12 +++++++++ wrapper/ptrace.c | 51 +++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 hypodermic/ptrace.py create mode 100644 wrapper/Makefile create mode 100644 wrapper/ptrace.c diff --git a/.gitignore b/.gitignore index d77a563..e7ffb10 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dist/ *.egg-info *.pyc *.egg +libptracew.so diff --git a/hypodermic/ptrace.py b/hypodermic/ptrace.py new file mode 100644 index 0000000..fdfe5b8 --- /dev/null +++ b/hypodermic/ptrace.py @@ -0,0 +1,75 @@ +# Copyright (C) 2017 Jakob Kreuze, All Rights Reserved. +# +# This file is part of Hypodermic. +# +# Hypodermic is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# Hypodermic is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Hypodermic. If not, see . + +"""Wrapper for the ptrace system call, since python-ptrace sucks.""" + +import ctypes + + +# TODO: Instantiate from binary path, as well. +class Process(object): + """Process attached via ptrace. + + Note: + The process is implicitly detached from upon destruction of this + object. + + Args: + pid (int): The pid of the process to attach to. + + Raises: + TypeError: If the pid argument is not an int. + OSError: If the pid cannot be attached to. + """ + + def __init__(self, pid: int): + if not isinstance(pid, int): + raise TypeError("pid argument must be an int") + self._load_ffi_methods() + + if self._attach(ctypes.c_int(pid)): + raise OSError("Could not attach to pid {}".format(pid)) + self.pid = pid + + def __del__(self): + if hasattr(self, "pid"): + self.detach() + + def _load_ffi_methods(self): + # FIXME: How are we going to deal with the path? + self._so = ctypes.cdll.LoadLibrary("/tmp/libptracew.so") + self._attach = self._so.attach + self._detach = self._so.detach + self._cont = self._so.cont + + def detach(self): + """Explicitly detaches from the process. + + Raises: + OSError: If the process cannot be detached from. + """ + if self._detach(ctypes.c_int(self.pid)): + raise OSError("Could not detach from pid {}".format(self.pid)) + + def cont(self): + """Continues until the program is haulted. + + Raises: + OSError: If the process cannot be continued. + """ + if self._cont(ctypes.c_int(self.pid)): + raise OSError("Could not continue") diff --git a/setup.py b/setup.py index 82a2754..118ca85 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ setup( download_url="https://github.com/TsarFox/hypodermic", packages=["hypodermic"], include_package_data=True, - install_requires=["python-ptrace"], + install_requires=[], extras_require={}, tests_require=[], entry_points={"console_scripts": ["hypodermic = hypodermic.main:main"]}, diff --git a/wrapper/Makefile b/wrapper/Makefile new file mode 100644 index 0000000..1019833 --- /dev/null +++ b/wrapper/Makefile @@ -0,0 +1,12 @@ +CC := gcc + +CFLAGS = -Wall -Wextra -Os -std=c99 -pedantic -fstack-protector-all +CFLAGS += $(USER_CFLAGS) + +LDFLAGS = -shared +LDFLAGS += $(USER_LDFLAGS) + +all: libptracew.so + +libtestw.so: ptrace.c + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) diff --git a/wrapper/ptrace.c b/wrapper/ptrace.c new file mode 100644 index 0000000..3ce42a1 --- /dev/null +++ b/wrapper/ptrace.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2017 Jakob Kreuze, All Rights Reserved. + + This file is part of Hypodermic. + + Hypodermic is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + Hypodermic is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Hypodermic. If not, see . */ + +#include +#include + +#include + + +int attach(int pid) { + if ((ptrace(PTRACE_ATTACH, pid, NULL, NULL)) < 0) { + return -1; + } + + waitpid(pid, NULL, WUNTRACED); + return 0; +} + + +int detach(int pid) { + return ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0; +} + + +int cont(int pid) { + int s; + + if ((ptrace(PTRACE_CONT, pid, NULL, NULL)) < 0) { + return -1; + } + + while (!WIFSTOPPED(s)) { + waitpid(pid, &s, WNOHANG); + } + + return 0; +} -- cgit v1.3