forked from JonathanSalwan/VMProtect-devirtualization
-
Notifications
You must be signed in to change notification settings - Fork 1
/
VMP_Trace.cpp
129 lines (103 loc) · 3.73 KB
/
VMP_Trace.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
#include "pin.H"
#include <fstream>
#include <iostream>
#include <list>
std::ostream* out = &std::cerr;
bool start = false;
static KNOB<UINT32> KnobStart(KNOB_MODE_WRITEONCE, "pintool", "start", "0", "Start the tracing at this address");
static KNOB<UINT32> KnobEnd(KNOB_MODE_WRITEONCE, "pintool", "end", "0", "Stop the tracing at this address");
VOID cb_inst(CONTEXT* ctx, const unsigned char* addr, UINT32 size) {
std::ios_base::fmtflags f(out->flags());
UINT64 buffer = 0;
std::list<LEVEL_BASE::REG> regs;
regs.push_back(LEVEL_BASE::REG_RAX);
regs.push_back(LEVEL_BASE::REG_RBX);
regs.push_back(LEVEL_BASE::REG_RCX);
regs.push_back(LEVEL_BASE::REG_RDX);
regs.push_back(LEVEL_BASE::REG_RDI);
regs.push_back(LEVEL_BASE::REG_RSI);
regs.push_back(LEVEL_BASE::REG_RBP);
regs.push_back(LEVEL_BASE::REG_RSP);
regs.push_back(LEVEL_BASE::REG_R8);
regs.push_back(LEVEL_BASE::REG_R9);
regs.push_back(LEVEL_BASE::REG_R10);
regs.push_back(LEVEL_BASE::REG_R11);
regs.push_back(LEVEL_BASE::REG_R12);
regs.push_back(LEVEL_BASE::REG_R13);
regs.push_back(LEVEL_BASE::REG_R14);
regs.push_back(LEVEL_BASE::REG_R15);
// Registers
*out << "r";
for (const auto& reg : regs) {
PIN_GetContextRegval(ctx, reg, reinterpret_cast<unsigned char*>(&buffer));
*out << ":" << std::hex << "0x" << buffer << std::dec;
}
*out << std::endl;
// Instruction
*out << "i:" << std::hex << "0x" << reinterpret_cast<unsigned long>(addr) << std::dec << ":" << size << ":";
for (size_t i = 0; i < size; ++i)
*out << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (((int)addr[i]) & 0xFF);
*out << std::endl;
out->flags(f);
}
VOID cb_memread(UINT64 addr, UINT32 size) {
std::ios_base::fmtflags f(out->flags());
*out << "mr:" << std::hex << "0x" << addr << std::dec << ":" << size << ":";
switch (size) {
case 1: *out << std::hex << "0x" << static_cast<const int>(*reinterpret_cast<const unsigned char*>(addr)) << std::dec; break;
case 2: *out << std::hex << "0x" << *reinterpret_cast<const short*>(addr) << std::dec; break;
case 4: *out << std::hex << "0x" << *reinterpret_cast<const UINT32*>(addr) << std::dec; break;
case 8: *out << std::hex << "0x" << *reinterpret_cast<const UINT64*>(addr) << std::dec; break;
}
*out << std::endl;
out->flags(f);
}
VOID Trace(TRACE trace, VOID* v) {
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
/* Skip libs */
if (INS_Address(ins) >= 0x7f0000000000) {
continue;
}
/* Start of instrumentation */
if (INS_Address(ins) == KnobStart) {
start = true;
}
/* End of instrumentation */
if (INS_Address(ins) == KnobEnd) {
start = false;
return;
}
if (start && INS_IsMemoryRead(ins)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)cb_memread,
IARG_MEMORYREAD_EA,
IARG_MEMORYREAD_SIZE,
IARG_END);
}
if (start && INS_HasMemoryRead2(ins)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)cb_memread,
IARG_MEMORYREAD2_EA,
IARG_MEMORYREAD_SIZE,
IARG_END);
}
if (start) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)cb_inst, IARG_CONTEXT, IARG_INST_PTR, IARG_UINT32, INS_Size(ins), IARG_END);
}
}
}
}
int usage(void) {
std::cerr << "Usage: ./pin -t VMP_Trace.so -start <start addr> -end <end addr> -- <vmp_binary> <vmp_binary_arg>" << std::endl;
return -1;
}
int main(int argc, char* argv[]) {
if (PIN_Init(argc, argv)) {
return usage();
}
if (!KnobStart || !KnobEnd) {
return usage();
}
TRACE_AddInstrumentFunction(Trace, 0);
PIN_StartProgram();
return 0;
}