-
Notifications
You must be signed in to change notification settings - Fork 0
/
target.inc
124 lines (99 loc) · 2.83 KB
/
target.inc
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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <ucontext.h>
#if (defined (__x86_64__))
#ifndef REG_RIP
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#ifndef REG_INDEX
#define REG_INDEX(NAME) (offsetof(struct sigcontext, NAME) / sizeof(greg_t))
#endif
#define REG_RIP REG_INDEX(rip) /* seems to be 16 */
#endif
#endif
unsigned __count = 0;
volatile void* __bp;
volatile void* __after_bp;
volatile char __org_inst;
volatile char __org_after_bp;
volatile char __phase = 0;
volatile unsigned __target_dynamic_instance = 0;
static void sigtrap_handler(int sig, siginfo_t* siginfo, void* dummy)
{
//fprintf(stderr, "sigtrap_handler\n");
if (__phase == 0)
{
size_t pagesize = sysconf(_SC_PAGE_SIZE);
size_t mask = 0xffffffffffffffff - (pagesize - 1);
__count += 1;
struct ucontext* u = (struct ucontext*)dummy;
unsigned char* pc = (unsigned char *)u->uc_mcontext.gregs[REG_RIP];
// remember original breakpoint
__bp = (void*)(pc-1);
// set codepage writable
size_t codepage = ( (size_t)pc ) & mask;
if(mprotect((void*) codepage, (size_t) pagesize, PROT_EXEC | PROT_READ | PROT_WRITE)==-1)
{
perror("mprotect");
exit(1);
}
//printf("pc: %p, __org_inst: %x\n", pc, __org_inst);
// retreive original instuction
*(pc-1) = __org_inst;
// set breakpoint at next instruction
// to do that, first set the page read and writable
size_t after_bp_page = ( (size_t)__after_bp) & mask;
if(mprotect((void*) after_bp_page, (size_t) pagesize, PROT_EXEC | PROT_READ | PROT_WRITE)==-1)
{
perror("mprotect");
exit(1);
}
// set sw breakpoint
__org_after_bp = *( (char*)__after_bp);
*( (char*)__after_bp ) = 0xcc;
// fix PC
u->uc_mcontext.gregs[REG_RIP] = (greg_t)(pc-1);
// phase change
__phase = 1;
}
else // __phase == 1
{
//printf("sig handler phase 1\n");
// retreive original instruction
*( (char*)__after_bp ) = __org_after_bp;
// fix PC
struct ucontext* u = (struct ucontext*)dummy;
u->uc_mcontext.gregs[REG_RIP] -= 1;
//printf("pc: %lx\n", u->uc_mcontext.gregs[REG_RIP]);
// set breakpoint again
*( (char*)__bp ) = 0xcc;
// check count
if (__count == (__target_dynamic_instance-1))
{
printf("reattach\n");
ptrace(PTRACE_TRACEME,0,0,0);
}
__phase = 0;
}
}
static void install_sigtrap_handler()
{
struct sigaction o, r;
r.sa_flags = SA_SIGINFO;
sigemptyset( &r.sa_mask );
r.sa_sigaction = &sigtrap_handler;
sigaction( SIGTRAP, &r, &o);
}
__attribute__((destructor)) void end(void)
{
printf("__count: %u\n", __count);
}