-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathpivot.cpp
201 lines (165 loc) · 4.44 KB
/
pivot.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
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/**
@author Edward J. Schwartz
This module contains code to test if various pivot gadgets will be
effective. A list of gadgets is given as input. The target of each
gadget is checked to see if it is tainted. If so, that gadget is a
potential pivot, since it transfers control to user-modifiable memory.
*/
#include "pivot.h"
#include "pin.H"
#include <cassert>
#include <fstream>
#include <iostream>
using namespace pintrace;
/** Pivot comparison */
bool operator<(const struct pivot_s &a, const struct pivot_s &b) {
return (&a < &b);
}
static pivottype_t PIVOT_parse_pivottype(string s) {
if (s == "switchstack") return SWITCHSTACK;
if (s == "mempivot") return MEMPIVOT;
cerr << "Invalid pivot type: " << s << endl;
return UNKNOWN;
}
static const string switchstack_str = string("Switchstack");
static const string mempivot_str = string("Mempivot");
static const string unknown_str = string("Unknown");
static string PIVOT_pivottype_string(pivottype_t t) {
switch (t) {
case SWITCHSTACK:
return switchstack_str;
case MEMPIVOT:
return mempivot_str;
default:
return unknown_str;
}
return string("Invalid");
}
/**
Convert a few REGs to strings.
*/
#define CASE(r) case LEVEL_BASE::REG_##r: return string(#r); break;
static string PIVOT_reg_string(REG ri) {
switch(ri) {
CASE(EAX);
CASE(EBX);
CASE(ECX);
CASE(EDX);
CASE(ESI);
CASE(EDI);
CASE(ESP);
CASE(EBP);
default:
cerr << "Unknown REG: " << ri << endl;
assert(false);
break;
}
return string("Invalid");
}
#undef CASE
/**
Convert a few strings to REGs
*/
#define CASE(r) if (ri == "R_" #r) { return LEVEL_BASE::REG_##r; }
static REG PIVOT_string_reg(string ri) {
CASE(EAX);
CASE(EBX);
CASE(ECX);
CASE(EDX);
CASE(ESI);
CASE(EDI);
CASE(ESP);
CASE(EBP);
cerr << "Unknown register: " << ri << endl;
return REG_INVALID_;
}
#undef CASE
/**
Print pivot.
*/
ostream& operator<<(ostream &o, const pivot_s &p) {
o << "@" << p.address << ": "
<< PIVOT_pivottype_string(p.t) << " "
<< PIVOT_reg_string(p.base) << " "
<< p.offset;
return o;
}
/**
Parses an input stream. The file has format: <gadget type> <reg> <offset>.
*/
pivot_set PIVOT_parseinput(istream &f) {
pivot_set ps;
while (f.good()) {
pivot_t p;
string s;
/* Read gadget address. */
f >> hex >> p.address;
if (!f.good()) break;
/* Set pivot type. */
f >> s;
p.t = PIVOT_parse_pivottype(s);
if (p.t == UNKNOWN) {
break;
}
/* Read register name. */
f >> s;
p.base = PIVOT_string_reg(s);
/* Read offset. */
f >> hex >> p.offset;
/* Add pivot to pivot set. */
ps.insert(p);
}
return ps; /* return by value; slow but easy */
}
/**
Given a set of pivots, return the address of memory they will transfer to esp.
*/
void PIVOT_testpivot(pivot_set ps, CONTEXT *ctx, TaintTracker &tt) {
pivot_set::iterator i;
cerr << "gaddr" << "\tpivot" << "\teaddr" << "\tconsec" << "\ttval" << "\tmapped" << endl;
for (i = ps.begin(); i != ps.end(); i++) {
intptr_t a = PIN_GetContextReg(ctx, (*i).base);
a += (*i).offset;
/* Put the address of our bytes in a. */
switch((*i).t) {
case SWITCHSTACK:
/* We want to look at reg + offset. */
break;
case MEMPIVOT:
/* We want to look at M[reg + offset] +?. */
intptr_t ptr;
size_t bytes;
bytes = PIN_SafeCopy(&ptr, (void*)a, sizeof(intptr_t));
if (bytes == sizeof(intptr_t)) {
a = ptr;
}
break;
default:
cerr << "Unknown pivot type" << endl;
break;
}
/* Check if the bytes are tainted. */
switch((*i).t) {
case SWITCHSTACK:
case MEMPIVOT:
{
char tempbuf[1];
uint32_t t = tt.getMemTaint(a, pintrace::INVALIDREGMEM);
size_t consecTainted = 0;
uint32_t readable = PIN_SafeCopy(tempbuf, (void*)a, 1);
for (ADDRINT base = a; tt.getMemTaint(base, pintrace::INVALIDREGMEM) != NOTAINT; base++, consecTainted++) {
/* .... */
}
cerr << *i << "\t" << a << "\t" << consecTainted << "\t" << t << "\t" << readable << endl;
break;
}
default:
/* Impossible. */
assert(false);
break;
}
}
}
/*parse input -> set of pivots
test pivots -> map of pivots to result
output pivots -> writes to file*/