ptrace可以修改和读取一个进程的数据
long ptrace(enum __ptrace_request request,pid_t pid,void *addr,void *data);
PTRACE_TRACEME, 本进程被其父进程所跟踪。其父进程应该希望跟踪子进程
PTRACE_PEEKTEXT, 从内存地址中读取一个字节,内存地址由addr给出
PTRACE_PEEKDATA, 同上
PTRACE_PEEKUSER, 可以检查用户态内存区域(USER area),从USER区域中读取一个字节,偏移量为addr
PTRACE_POKETEXT, 往内存地址中写入一个字节。内存地址由addr给出
PTRACE_POKEDATA, 往内存地址中写入一个字节。内存地址由addr给出
PTRACE_POKEUSER, 往USER区域中写入一个字节,偏移量为addr
PTRACE_GETREGS, 读取寄存器
PTRACE_GETFPREGS, 读取浮点寄存器
PTRACE_SETREGS, 设置寄存器
PTRACE_SETFPREGS, 设置浮点寄存器
PTRACE_CONT, 重新运行
PTRACE_SYSCALL, 重新运行
PTRACE_SINGLESTEP, 设置单步执行标志
PTRACE_ATTACH,追踪指定pid的进程
PTRACE_DETACH, 结束追踪
读取修改进程数据的样例
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
int main(int argc, char* argv[])
{
pid_t attack_pid = -1;
long val = 66;
if (argc < 2 || argv[1] <= 0)
{
printf("usage: ./main pid(pid > 0)\n");
return 0;
}
attack_pid = strtoul(argv[1], 0, 10);
if (ptrace(PTRACE_ATTACH, attack_pid, NULL, NULL) < 0)
{
printf("attach failed\n");
return 0;
}
//读取数据
printf("global1 %d\n", ptrace(PTRACE_PEEKDATA , attack_pid, (void*)0x804a028, NULL));
printf("stack_var %d\n", ptrace(PTRACE_PEEKDATA , attack_pid, (void*)0xbfa4195c, NULL));
//修改数据
ptrace(PTRACE_POKEDATA , attack_pid, (void*)0x804a028, val);
ptrace(PTRACE_POKEDATA , attack_pid, (void*)0xbfa4195c, val);
ptrace (PTRACE_DETACH, attack_pid, NULL, NULL);
waitpid(attack_pid, NULL, WUNTRACED);
return 0;
}
//main.c被改写的进程
#include <stdio.h>
int global1 = 11; //
int main(void)
{
long stack_var = 10;
char c = 'a';
while(1)
{
printf("global1 addrss 0x%lx, global1=%d\n", &global1, global1);
printf("stack_var addrss 0x%lx, stack_var=%d\n", &stack_var, stack_var);
scanf("%c", &c);
getchar();
if (c != 'c')
{
break;
}
}
return 0;
}
进程号是10093。ptrace程序读取全局变量和局部变量的值(我提前把这两个变量的地址打印出来了)
可以看到等待ptrace修改完成之后,再去读取数据已经变成我们改写的66了
所以ptrace是不是能够随便改写其他进程的值哦