-
Notifications
You must be signed in to change notification settings - Fork 8
/
rnr_loader.cpp
121 lines (107 loc) · 3.03 KB
/
rnr_loader.cpp
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
#include <dlfcn.h>
#include <sys/types.h>
#include "rnr_loader.hpp"
#include "util.hpp"
#include "utilSystemCalls.hpp"
using namespace std;
// TODO: Currently passing PID into prehook and posthook for both PID and TIG
// arguments. Fix this.
// Fingerprinter State
static bool isNoop = false;
static int noopSyscall = -1;
static long noopRetval = -1;
extern "C" {
static long rnr_nop_sysenter(
struct SyscallState* s,
int pid,
int tid,
int syscallno,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5) {
return -ENOSYS;
}
static long rnr_nop_sysexit(
struct SyscallState* s,
int pid,
int tid,
int syscallno,
unsigned long retval,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5) {
return 0;
}
}
/* override by `--rnr` command line flag */
static rnr_loader __rnr__ = {
.rnr_sysenter = rnr_nop_sysenter,
.rnr_sysexit = rnr_nop_sysexit,
};
bool rnr::callPreHook(
int syscallNumber,
globalState& gs,
state& s,
ptracer& t,
scheduler& sched) {
struct SyscallState syscallState;
syscallState.noop = false;
auto regs = t.getRegs();
auto sysenter = __rnr__.rnr_sysenter;
long prehook_retval = sysenter(
&syscallState, s.traceePid, s.traceePid, syscallNumber, regs.rdi,
regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9);
// If fingerprinter indicates that the syscall shouldn't be run,
// cancel the syscall and set the return value
if (syscallState.noop) {
isNoop = true;
noopSyscall = syscallNumber;
noopRetval = prehook_retval;
replaceSystemCallWithNoop(gs, s, t);
t.setReturnRegister((uint64_t)prehook_retval);
}
// Return flag indicating whether to run post-hook
return true;
}
void rnr::callPostHook(
int syscallNumber,
globalState& gs,
state& s,
ptracer& t,
scheduler& sched) {
struct SyscallState syscallState;
syscallState.noop = false;
if (isNoop) {
t.changeSystemCall((uint64_t)noopSyscall);
t.setReturnRegister((uint64_t)noopRetval);
isNoop = false;
}
auto regs = t.getRegs();
auto sysexit = __rnr__.rnr_sysexit;
sysexit(
&syscallState, s.traceePid, s.traceePid, regs.orig_rax, (long)regs.rax,
regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9);
}
/* must be called early, no lock is provied */
void rnr::loadRnr(const string& dso) {
void* handle = dlopen(dso.c_str(), RTLD_NOW);
auto sysenter = dlsym(handle, "rnr_sysenter");
if (!sysenter) {
runtimeError("could not find rnr_sysenter");
}
auto sysexit = dlsym(handle, "rnr_sysexit");
if (!sysexit) {
runtimeError("could not find rnr_sysexit");
}
__rnr__.rnr_sysenter = reinterpret_cast<decltype(rnr_nop_sysenter)*>(
reinterpret_cast<unsigned long>(sysenter));
__rnr__.rnr_sysexit = reinterpret_cast<decltype(rnr_nop_sysexit)*>(
reinterpret_cast<unsigned long>(sysexit));
// NB: no dlclose to keep keep the symbols intact.
}