/
itrace.c
173 lines (143 loc) · 4.26 KB
/
itrace.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
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
/*
* itrace.c: attches to an already existing process and
* prints the x86 intructions currently being executed
*
* Name: Brandon Brien
* ID: 10079883
* CPSC 457 Assignment 1, Part 1
* Due: Oct 17, 2014
* Last Edited: Oct 16, 2014
*
*
* *It should be noted that this program was based off Dr. Locasto's
* example of ptrace. Some functions are very similar. Those sections
* are heavily commented to show understanding of whats happening.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/user.h>
#include <asm/ptrace-abi.h>
#include <asm/ptrace.h>
#include <udis86.h>
/* The process ID to trace. */
long int tr_pid = 0;
static void do_trace();
static void init_attach(char*);
void sigintHandler(int);
/*
* Handles the the event that a SIGINT is send kill
* the process. Destroys itself and the tracee process
*/
void sigintHandler(int sig_num)
{
int killed_status;
ptrace(PTRACE_KILL, tr_pid, NULL, NULL);
printf("\nitrace and traced program killed\n");
waitpid(tr_pid,&killed_status, WUNTRACED | WCONTINUED);
exit(0);
}
/*
* Attempts to attach to tracee
*/
static void
init_attach(char* tpid)
{
int stopped = 0; /* used to determine if the process as been stopped via attach */
long atch_success = 0; /*used to determine if there was an error attaching */
pid_t p = 0;
int attach_status = 0;
/*
* Because the arg value is a string, must cast to long
*/
tr_pid = strtol(tpid, NULL, 10);
printf("itrace is now attempting to trace the process: %ld\n",tr_pid);
atch_success = ptrace(PTRACE_ATTACH,tr_pid,NULL,NULL);
if(atch_success==-1)
{
fprintf(stderr,"itrace has failed to attach to the process\n");
exit(-1);
}
/*
* waits until the traced process has ACTUALLY stopped
* because sometimes the signal takes longer than expected
*/
p = waitpid(tr_pid, &attach_status, WUNTRACED | WCONTINUED);
/*
* Prints the appropirate message to stdout depdning on results
*/
if(WIFSTOPPED(attach_status))
{
stopped = WSTOPSIG(attach_status);
printf("Attaching to the tracee has been succesful");
}else{
printf("The attempt to attach to process has failed");
exit(-2);
}
return;
}
/*
* Function do_trace assumes that itrace as been attached (successfully)
* to a process. It then output to stdout all the x86 instructions being
* executed by traced program
*/
static void
do_trace()
{
struct user_regs_struct registers; /* A struct to hold all registers of process */
size_t read_size = 15; /* how many bytes the disassembler should read */
unsigned char *buff;
long eip_data[4]; /* a holding place for all the 15 bytes of eip (max intruction size) */
buff = (unsigned char *) malloc(sizeof(unsigned char)*15);
int stop_status = 0;
/* Loops until no more instructinos are being read */
do
{
ptrace(PTRACE_GETREGS, tr_pid, NULL, ®isters);
eip_data[0]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip, NULL);
eip_data[1]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+4, NULL);
eip_data[2]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+8, NULL);
eip_data[3]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+12, NULL);
memcpy(buff, eip_data, 15);
/* Initialization of 3rd part disassembler */
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_mode(&ud_obj, 32);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
ud_set_input_buffer(&ud_obj, buff, read_size);
ud_disassemble(&ud_obj);
/* Prints the disassembled x86 code */
printf("\t%s\n", ud_insn_asm(&ud_obj));
/* Tells the tracee to go to the next instruction, then wait */
ptrace(PTRACE_SINGLESTEP,tr_pid, 0,NULL);
/* Waits until the tracee program as gon to the next intSruction
and STOPPED before itrace continues */
waitpid(tr_pid, &stop_status, WUNTRACED|WCONTINUED);
if(!stop_status)
{
printf("Something has gone wrong");
}
}while (eip_data[0] != -1);
return;
}
/* Main function for itrace that
* sets up the attached to process ID
* given on commmand line and then
* calls do_trace to do the tracing
*/
int main(int argc,
char* argv[])
{
if(3==argc)
{
init_attach(argv[2]);
signal(SIGINT, sigintHandler);
do_trace();
}
return 0;
}