-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathaarch64.c
135 lines (119 loc) · 6.13 KB
/
aarch64.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/mman.h>
#include "../trampolines.h"
#include "aarch64.h"
void initCall(struct SymbolData *data) {
memcpy(data->address, data->beginning_org, ARCHDEP_TRAMPOLINE_LENGTH);
memcpy(data->address + ARCHDEP_TRAMPOLINE_LENGTH, data->step_2_trampoline, ARCHDEP_UNTRAMPOLINE_LENGTH);
__builtin___clear_cache(data->address, data->address + ARCHDEP_UNTRAMPOLINE_LENGTH + ARCHDEP_TRAMPOLINE_LENGTH);
}
void finiCall(struct SymbolData *data) {
memcpy(data->address, data->beginning_trampoline, ARCHDEP_TRAMPOLINE_LENGTH);
memcpy(data->address + ARCHDEP_TRAMPOLINE_LENGTH, data->beginning_org + ARCHDEP_TRAMPOLINE_LENGTH, ARCHDEP_UNTRAMPOLINE_LENGTH);
__builtin___clear_cache(data->address, data->address + ARCHDEP_UNTRAMPOLINE_LENGTH + ARCHDEP_TRAMPOLINE_LENGTH);
}
extern void untrampolineStep2(void);
struct SymbolData *pivotSymbol(const char *symbol, void *newaddr) {
static int pagesize = 0;
if(pagesize == 0) pagesize = getpagesize();
void *symboladdr = dlsym(RTLD_NEXT, symbol);
if(symboladdr == NULL) {
printf("!! CANNOT FIND %s !!\n", symbol);
return NULL;
}
struct SymbolData *s = malloc(sizeof(struct SymbolData));
uint32_t addr4 = (((unsigned long long int) newaddr) >> 48) & 0xFFFF;
uint32_t addr3 = (((unsigned long long int) newaddr) >> 32) & 0xFFFF;
uint32_t addr2 = (((unsigned long long int) newaddr) >> 16) & 0xFFFF;
uint32_t addr1 = (((unsigned long long int) newaddr) >> 0) & 0xFFFF;
instr_t trampoline[] = {
0xD2800008 | (addr1 << 5), // First mov x8
0xF2A00008 | (addr2 << 5), // Second mov x8
0xF2C00008 | (addr3 << 5), // Third mov x8
0xF2E00008 | (addr4 << 5), // Forth mov x8
0xd61f0100 // BR x8
};
addr4 = (((unsigned long long int) untrampolineStep2) >> 48) & 0xFFFF;
addr3 = (((unsigned long long int) untrampolineStep2) >> 32) & 0xFFFF;
addr2 = (((unsigned long long int) untrampolineStep2) >> 16) & 0xFFFF;
addr1 = (((unsigned long long int) untrampolineStep2) >> 0) & 0xFFFF;
uint32_t addr4f = (((unsigned long long int) s) >> 48) & 0xFFFF;
uint32_t addr3f = (((unsigned long long int) s) >> 32) & 0xFFFF;
uint32_t addr2f = (((unsigned long long int) s) >> 16) & 0xFFFF;
uint32_t addr1f = (((unsigned long long int) s) >> 0) & 0xFFFF;
instr_t s2trampoline[] = {
0xD2800010 | (addr1f << 5), // First mov x16
0xF2A00010 | (addr2f << 5), // Second mov x16
0xF2C00010 | (addr3f << 5), // Third mov x16
0xF2E00010 | (addr4f << 5), // Forth mov x16
0xD2800011 | (addr1 << 5), // First mov x17
0xF2A00011 | (addr2 << 5), // Second mov x17
0xF2C00011 | (addr3 << 5), // Third mov x17
0xF2E00011 | (addr4 << 5), // Forth mov x17
0xd61f0220 // BR x17
};
// During the restore-call, there will be 2 trampolines at the start of the function.
uint8_t *funcstart = malloc(ARCHDEP_TRAMPOLINE_LENGTH + ARCHDEP_UNTRAMPOLINE_LENGTH);
// Place the beginning of the function into the allocated region
memcpy(funcstart, symboladdr, ARCHDEP_TRAMPOLINE_LENGTH + ARCHDEP_UNTRAMPOLINE_LENGTH);
s->address = symboladdr;
s->beginning_org = funcstart;
s->page_address = (void*) (((unsigned long long int) symboladdr) & ~(pagesize - 1));
s->size = ARCHDEP_TRAMPOLINE_LENGTH + ARCHDEP_UNTRAMPOLINE_LENGTH;
s->beginning_trampoline = malloc(ARCHDEP_TRAMPOLINE_LENGTH);
s->step_2_trampoline = malloc(ARCHDEP_UNTRAMPOLINE_LENGTH);
pthread_mutex_init (&s->mutex, NULL);
mprotect(s->page_address, pagesize, PROT_READ | PROT_EXEC | PROT_WRITE);
memcpy(s->beginning_trampoline, trampoline, ARCHDEP_TRAMPOLINE_LENGTH);
memcpy(s->step_2_trampoline, s2trampoline, ARCHDEP_UNTRAMPOLINE_LENGTH);
finiCall(s);
return s;
}
#define CALL(x, ...) ({ \
init_call(x); \
unsigned long long int res = \
((unsigned long long int (*)()) x->address)(__VA_ARGS__); \
fini_call(x); \
res; \
})
int untrampolineInit(struct SymbolData *symbol) {
pthread_mutex_lock(&symbol->mutex);
initCall(symbol);
}
int untrampolineFini(struct SymbolData *symbol) {
finiCall(symbol);
pthread_mutex_unlock(&symbol->mutex);
}
extern void untrampolineFunction(void);
void generateUntrampoline(void *function, struct SymbolData *symbol, int bytesRemaining) {
uint32_t addr4 = (((unsigned long long int) symbol) >> 48) & 0xFFFF;
uint32_t addr3 = (((unsigned long long int) symbol) >> 32) & 0xFFFF;
uint32_t addr2 = (((unsigned long long int) symbol) >> 16) & 0xFFFF;
uint32_t addr1 = (((unsigned long long int) symbol) >> 0) & 0xFFFF;
uint32_t addr4f = (((unsigned long long int) untrampolineFunction) >> 48) & 0xFFFF;
uint32_t addr3f = (((unsigned long long int) untrampolineFunction) >> 32) & 0xFFFF;
uint32_t addr2f = (((unsigned long long int) untrampolineFunction) >> 16) & 0xFFFF;
uint32_t addr1f = (((unsigned long long int) untrampolineFunction) >> 0) & 0xFFFF;
instr_t trampoline[] = {
0xD2800008 | (addr1 << 5), // First mov x8
0xF2A00008 | (addr2 << 5), // Second mov x8
0xF2C00008 | (addr3 << 5), // Third mov x8
0xF2E00008 | (addr4 << 5), // Forth mov x8
0xD2800009 | (addr1f << 5), // First mov x9
0xF2A00009 | (addr2f << 5), // Second mov x9
0xF2C00009 | (addr3f << 5), // Third mov x9
0xF2E00009 | (addr4f << 5), // Forth mov x9
0xd61f0120 // BR x9
};
if(sizeof(trampoline) > bytesRemaining) {
printf("[F]: Fatal error - too little space to generate a trampoline!\n");
exit(1);
}
memcpy(function, trampoline, sizeof(trampoline));
}