#include <stdio.h>
#include <fcntl.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
using namespace std;
#if __WORDSIZE == 64
#define REG(reg) reg.orig_rax
#else
#define REG(reg) reg.orig_eax
#endif
const int long_size = sizeof(int);
//获取addr处也就是buf参数
void getdata(pid_t child, long addr,
char *str, int len)
{ char *laddr;
int i, j;
union u {
int val;
char chars[long_size];
}data;
i = 0;
j = len / long_size;
laddr = str;
while(i < j) {
data.val = ptrace(PTRACE_PEEKDATA, child,
addr + i * 4, NULL);
memcpy(laddr, data.chars, long_size);
++i;
laddr += long_size;
}
j = len % long_size;
if(j != 0) {
data.val = ptrace(PTRACE_PEEKDATA, child,
addr + i * 4, NULL);
memcpy(laddr, data.chars, j);
}
str[len] = '\0';
}
int main(int argc, char *argv[]){
int fp;
fp = open("./a.txt",O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH);
pid_t child;
int status;
int64_t sys_num = -1;
child = fork();
if(child == 0){
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL); //子进程标记为trace,并执行ls
}else{
while(1){
struct user_regs_struct regs;
wait(&status);
if(WIFEXITED(status))
break;
ptrace(PTRACE_SYSCALL, child, NULL, NULL); //在系统调用处发送信号到父进程
waitpid(child, &status, 0);
ptrace(PTRACE_GETREGS, child, NULL, ®s); //获取寄存器参数
sys_num=REG(regs);
if(sys_num==1){ //write调用的系统调用号
printf("syscall write\n");
printf("change I/O from %llu to file\n",regs.rdi);
size_t size = regs.rdx;
char * buffer = new char[size]; //存储write的数据
getdata(child, regs.rsi, buffer, size);
printf("%s\n",buffer);
regs.rdi = fp;
ptrace(PTRACE_SETREGS, child, 0, ®s); //将write的输出从标准输出改为fp
}
ptrace(PTRACE_SYSCALL, child, NULL, NULL); //继续trace
}
}
close(fp);
return 0;
}