summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakob <jakob@memeware.net>2017-08-28 15:15:01 -0400
committerjakob <jakob@memeware.net>2017-08-28 15:15:01 -0400
commite687f96e883af18ef293b6844ef28f0c829d6e3c (patch)
treedc34dc46e384071e962694f5a5ac5f01cec8f08e
parenta4365445d4d32001362f6e8bfae93a3b8f152fde (diff)
Updated ptrace wrapper to allow creation of new processes.
-rw-r--r--hypodermic/ptrace.py27
-rw-r--r--wrapper/Makefile2
-rw-r--r--wrapper/ptrace.c33
3 files changed, 54 insertions, 8 deletions
diff --git a/hypodermic/ptrace.py b/hypodermic/ptrace.py
index fdfe5b8..d073930 100644
--- a/hypodermic/ptrace.py
+++ b/hypodermic/ptrace.py
@@ -29,29 +29,42 @@ class Process(object):
object.
Args:
- pid (int): The pid of the process to attach to.
+ pid (:obj:`int`, optional): The pid of the process to attach to.
+ Defaults to 0, which means that it will not be used.
+ path (:obj:`str`, optional): The path of the binary to run.
+ Defaults to "", which will be used if no pid is specified.
Raises:
TypeError: If the pid argument is not an int.
OSError: If the pid cannot be attached to.
"""
- def __init__(self, pid: int):
+ def __init__(self, pid=0, path=""):
if not isinstance(pid, int):
raise TypeError("pid argument must be an int")
+ elif not isinstance(path, str):
+ raise TypeError("path argument must be a string")
self._load_ffi_methods()
- if self._attach(ctypes.c_int(pid)):
- raise OSError("Could not attach to pid {}".format(pid))
- self.pid = pid
+ if pid != 0:
+ self._is_parent = False
+ if self._attach(ctypes.c_int(pid)):
+ raise OSError("Could not attach to pid {}".format(pid))
+ else:
+ self._is_parent = True
+ self.pid = self._new_proc(ctypes.c_char_p(path.encode()))
+ if self.pid < 0:
+ raise OSError("Could not create process {}".format(path))
+
def __del__(self):
- if hasattr(self, "pid"):
+ if hasattr(self, "_is_parent") and not self._is_parent:
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._new_proc = self._so.new_proc
self._attach = self._so.attach
self._detach = self._so.detach
self._cont = self._so.cont
@@ -62,7 +75,7 @@ class Process(object):
Raises:
OSError: If the process cannot be detached from.
"""
- if self._detach(ctypes.c_int(self.pid)):
+ if not self._is_parent and self._detach(ctypes.c_int(self.pid)):
raise OSError("Could not detach from pid {}".format(self.pid))
def cont(self):
diff --git a/wrapper/Makefile b/wrapper/Makefile
index 1019833..026f4ba 100644
--- a/wrapper/Makefile
+++ b/wrapper/Makefile
@@ -8,5 +8,5 @@ LDFLAGS += $(USER_LDFLAGS)
all: libptracew.so
-libtestw.so: ptrace.c
+libptracew.so: ptrace.c
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
diff --git a/wrapper/ptrace.c b/wrapper/ptrace.c
index 3ce42a1..caf510f 100644
--- a/wrapper/ptrace.c
+++ b/wrapper/ptrace.c
@@ -16,9 +16,42 @@
along with Hypodermic. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/ptrace.h>
+#include <sys/types.h>
#include <sys/wait.h>
#include <stddef.h>
+#include <unistd.h>
+
+
+static void run_target(const char *path) {
+ if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
+ return;
+ }
+
+ execl(path, path, 0);
+}
+
+
+int new_proc(const char *path) {
+ int wait_stat;
+ pid_t pid;
+
+ if (path == NULL) {
+ return -1;
+ }
+
+ pid = fork();
+
+ if (pid == 0) {
+ run_target(path);
+ } else if (pid > 0) {
+ wait(&wait_stat);
+ } else {
+ return -1;
+ }
+
+ return pid;
+}
int attach(int pid) {