xref: /linux-tools/ptrace/syscall_connect_lb.cpp (revision c995a2d01ec016e07a0052d1d0b650e51fec4753)
1*c995a2d0SDavid Wang #include <stdio.h>
2*c995a2d0SDavid Wang #include <stdlib.h>
3*c995a2d0SDavid Wang #include <unistd.h>
4*c995a2d0SDavid Wang #include <sys/types.h>
5*c995a2d0SDavid Wang #include <sys/wait.h>
6*c995a2d0SDavid Wang #include <sys/ptrace.h>
7*c995a2d0SDavid Wang #include <sys/user.h>
8*c995a2d0SDavid Wang #include <sys/syscall.h>
9*c995a2d0SDavid Wang #include <netinet/in.h>
10*c995a2d0SDavid Wang #include <netinet/ip.h>
11*c995a2d0SDavid Wang #include <errno.h>
12*c995a2d0SDavid Wang 
13*c995a2d0SDavid Wang #include <set>
14*c995a2d0SDavid Wang using namespace std;
15*c995a2d0SDavid Wang 
16*c995a2d0SDavid Wang #define exiterr(err, msg) do{ if(err<0) { perror(msg); exit(1); }} while(0)
17*c995a2d0SDavid Wang 
18*c995a2d0SDavid Wang 
19*c995a2d0SDavid Wang // TODO: should load vip<->rips maps somewhere
20*c995a2d0SDavid Wang unsigned int vip4 = 0x28282828;
21*c995a2d0SDavid Wang unsigned int rip4s[] = {
22*c995a2d0SDavid Wang     0x50112ac,
23*c995a2d0SDavid Wang     0x40112ac,
24*c995a2d0SDavid Wang     0x30112ac,
25*c995a2d0SDavid Wang };
26*c995a2d0SDavid Wang 
main(int argc,char * argv[])27*c995a2d0SDavid Wang int main(int argc, char *argv[]) {
28*c995a2d0SDavid Wang     int pid, err, status, x;
29*c995a2d0SDavid Wang     unsigned long cpid;
30*c995a2d0SDavid Wang     struct user_regs_struct regs;
31*c995a2d0SDavid Wang     if (argc<2) { printf("need pid\n"); return 1; }
32*c995a2d0SDavid Wang     pid = atoi(argv[1]);
33*c995a2d0SDavid Wang     if (pid<=0) { printf("invalid pid %s\n", argv[1]); return 1; }
34*c995a2d0SDavid Wang     err = ptrace(PTRACE_ATTACH, pid, 0, 0);
35*c995a2d0SDavid Wang     exiterr(err, "fail to attach");
36*c995a2d0SDavid Wang     printf("attached with %d\n", pid);
37*c995a2d0SDavid Wang     x = waitpid(-1, &status, __WALL);
38*c995a2d0SDavid Wang     if (x != pid) {
39*c995a2d0SDavid Wang         printf("expect pid %d, got %d\n", pid, x);
40*c995a2d0SDavid Wang         return 1;
41*c995a2d0SDavid Wang     }
42*c995a2d0SDavid Wang     // set opts
43*c995a2d0SDavid Wang     err = ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE|PTRACE_O_TRACEFORK|PTRACE_O_TRACEVFORK|PTRACE_O_TRACESYSGOOD);
44*c995a2d0SDavid Wang     exiterr(err, "fail to set trace options");
45*c995a2d0SDavid Wang     // resume
46*c995a2d0SDavid Wang     err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
47*c995a2d0SDavid Wang     exiterr(err, "fail to resume tracee");
48*c995a2d0SDavid Wang     // loop
49*c995a2d0SDavid Wang     while(1) {
50*c995a2d0SDavid Wang         x = waitpid(-1, &status, __WALL);
51*c995a2d0SDavid Wang         exiterr(x, "fail to wait for tracee event");
52*c995a2d0SDavid Wang         if (WSTOPSIG(status)==(SIGTRAP|0x80)) {
53*c995a2d0SDavid Wang             // syscalls
54*c995a2d0SDavid Wang             err = ptrace(PTRACE_GETREGS, x, 0, &regs);
55*c995a2d0SDavid Wang             if (err<0) {
56*c995a2d0SDavid Wang                 perror("fail to copy process registers");
57*c995a2d0SDavid Wang                 continue;
58*c995a2d0SDavid Wang             }
59*c995a2d0SDavid Wang             // printf("syscall(%d) %lld(%llx, %llx, %llx)\n", x, regs.orig_rax, regs.rdi, regs.rsi, regs.rdx);
60*c995a2d0SDavid Wang             switch(regs.orig_rax) {
61*c995a2d0SDavid Wang                 case SYS_connect:
62*c995a2d0SDavid Wang                     // on x86, rax == -ENOSYS in  syscall-enter-stop
63*c995a2d0SDavid Wang                     if (regs.rax == -ENOSYS) {
64*c995a2d0SDavid Wang                         // change
65*c995a2d0SDavid Wang                         struct sockaddr_in *p;
66*c995a2d0SDavid Wang                         unsigned long w = ptrace(PTRACE_PEEKDATA, x, regs.rsi, 0);
67*c995a2d0SDavid Wang                         // 64bit enough for ipv4
68*c995a2d0SDavid Wang                         p = (struct sockaddr_in*)&w;
69*c995a2d0SDavid Wang                         if (p->sin_family == AF_INET) {
70*c995a2d0SDavid Wang                             // printf("ipv4 connect to %x\n", p->sin_addr.s_addr);
71*c995a2d0SDavid Wang                             if (p->sin_addr.s_addr == vip4) {
72*c995a2d0SDavid Wang                                 p->sin_addr.s_addr = rip4s[rand()%(sizeof(rip4s)/sizeof(rip4s[0]))];
73*c995a2d0SDavid Wang                                 // write back
74*c995a2d0SDavid Wang                                 ptrace(PTRACE_POKEDATA, x, regs.rsi, w);
75*c995a2d0SDavid Wang                             }
76*c995a2d0SDavid Wang                         }
77*c995a2d0SDavid Wang                     }
78*c995a2d0SDavid Wang                     ptrace(PTRACE_SYSCALL, x, 0, 0);
79*c995a2d0SDavid Wang                     break;
80*c995a2d0SDavid Wang                 default:
81*c995a2d0SDavid Wang                     err = ptrace(PTRACE_SYSCALL, x, 0, 0);
82*c995a2d0SDavid Wang                     // exiterr(err, "fail to resume tracee after a syscall event");
83*c995a2d0SDavid Wang             }
84*c995a2d0SDavid Wang         } else if (WIFSTOPPED(status)) {
85*c995a2d0SDavid Wang             // mostly signal
86*c995a2d0SDavid Wang             if (WSTOPSIG(status) != SIGSTOP&&WSTOPSIG(status) != SIGTRAP) ptrace(PTRACE_SYSCALL, x, 0, WSTOPSIG(status));
87*c995a2d0SDavid Wang             else ptrace(PTRACE_SYSCALL, x, 0, 0);
88*c995a2d0SDavid Wang         } else {
89*c995a2d0SDavid Wang             // others
90*c995a2d0SDavid Wang             ptrace(PTRACE_SYSCALL, x, 0, 0);
91*c995a2d0SDavid Wang         }
92*c995a2d0SDavid Wang     }
93*c995a2d0SDavid Wang     // no need to deattach if exit?
94*c995a2d0SDavid Wang     return 0;
95*c995a2d0SDavid Wang }
96