-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsysemu.c
102 lines (89 loc) · 2.35 KB
/
sysemu.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
#include <linux/limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <asm/ptrace-abi.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static int
child()
{
struct timeval tv;
struct timespec ts;
ptrace(PTRACE_TRACEME, 0, 0, 0);
raise(SIGSTOP);
gettimeofday(&tv, NULL);
clock_gettime(CLOCK_MONOTONIC, &ts);
return 0;
}
static int
dump_status(pid_t p, int status)
{
if (WIFSTOPPED(status)) {
char cmd[PATH_MAX];
printf("%d stopped by signal %d\n", p, WSTOPSIG(status));
snprintf(cmd, sizeof(cmd), "cat /proc/%d/syscall", p);
system(cmd);
return 1;
} else if (WIFCONTINUED(status)) {
printf("%d continued by SIGCONT\n", p);
return 1;
} else if (WIFEXITED(status)) {
printf("%d exited with code %d\n", p, WEXITSTATUS(status));
return 0;
} else if (WIFSIGNALED(status)) {
printf("%d terminated by signal %d\n", p, WTERMSIG(status));
return 0;
} else {
printf("%d seems to be running normally\n", p);
return 1;
}
}
static int
parent(pid_t c)
{
int status;
struct user_regs_struct regs;
waitpid(c, &status, 0);
dump_status(c, status);
ptrace(PTRACE_GETREGS, c, 0, ®s);
printf(" orig_eax: %ld\n", regs.orig_eax);
ptrace(PTRACE_SYSEMU, c, 0, 0);
waitpid(c, &status, 0);
dump_status(c, status);
ptrace(PTRACE_GETREGS, c, 0, ®s);
printf(" orig_eax: %ld\n", regs.orig_eax);
ptrace(PTRACE_SYSEMU, c, 0, 0);
waitpid(c, &status, 0);
dump_status(c, status);
ptrace(PTRACE_GETREGS, c, 0, ®s);
printf(" ip:%#lx; orig_eax:%ld\n", regs.eip, regs.orig_eax);
/* finish ? ->*/
ptrace(PTRACE_SYSEMU_SINGLESTEP, c, 0, 0);
waitpid(c, &status, 0);
dump_status(c, status);
ptrace(PTRACE_GETREGS, c, 0, ®s);
printf(" ip:%#lx; orig_eax:%ld\n", regs.eip, regs.orig_eax);
ptrace(PTRACE_SYSEMU, c, 0, 0);
waitpid(c, &status, 0);
dump_status(c, status);
ptrace(PTRACE_GETREGS, c, 0, ®s);
printf(" orig_eax: %ld\n", regs.orig_eax);
return 0;
}
int
main(int argc, char** argv)
{
pid_t c;
if (0 == (c = fork())) {
return child();
}
return parent(c);
}