[Ptrace]Linux内存替换(三)运行控制
来源:互联网 发布:灵界基友网络剧第一集 编辑:程序博客网 时间:2024/05/18 01:56
在上一节中利用Ptrace实现了B程序对A程序进程信息的读取,下面一个实例将实现B进程对A进程的运行控制,即利用B进程暂停A进程固定时间后再恢复运行(以操作者手动输入任意字符后恢复执行的方式,A始终恢复失败,报段错误,具体原因请好心人指点)。
【环境】
CentOS 6.6 (Final)
Linux version 2.6.32-504.el6.i686
Gcc version 4.4.7 20120313
【A程序:counter.c】
#include <sys/time.h>#include <stdio.h>long long timeum(){ struct timeval tim; gettimeofday (&tim , NULL); return (long long)tim.tv_sec*1000000+tim.tv_usec;}int main(){ int i; long long start,tmp; start = timeum(); for(i = 0; i < 60; ++i){ printf("My Counter: %d\n", i); sleep(1); tmp = timeum(); printf("Time Interval: %lld\n",tmp-start); start = tmp; } return 0;}
gcc -o counter counter.c
【B程序:pause.c】
#include <sys/ptrace.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/user.h>#include <stdio.h>#include <string.h>const int long_size = sizeof(long);void getdata(pid_t child, long addr, char *str, int len){ char *laddr; int i,j; union u{ long 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] = ' ';}void putdata(pid_t child, long addr, char *str, int len){ char *laddr; int i,j; union u{ long val; char chars[long_size]; }data; long rst; i = 0; j = len / long_size; laddr = str; while(i < j){ memcpy(data.chars, laddr, long_size); rst = ptrace(PTRACE_POKEDATA, child, addr + i*4, data.val); if (rst < 0) printf("Putdata Failed! \n"); ++i; laddr += long_size; } j = len % long_size; if(j != 0){ memcpy(data.chars, laddr, j); rst = ptrace(PTRACE_POKEDATA, child, addr + i*4, data.val); if (rst < 0) printf("Putdata Failed! \n"); }}int main(int argc, char *argv[]){ pid_t traced_process; struct user_regs_struct regs, newregs; /* int 0x80, int3 */ char code[] = {0xcd,0x80,0xcc,0}; //char code[] = {0,0,0,0}; //TEST char backup[4]; if(argc != 2) { printf("PID?\n"); return 1; } traced_process = atoi(argv[1]); ptrace(PTRACE_ATTACH, traced_process, NULL, NULL); int pid = wait(NULL); printf("Attach Pid: %d\n",pid); ptrace(PTRACE_GETREGS, traced_process, NULL, ®s); /* Copy instructions into a backup variable */ getdata(traced_process, regs.eip, backup, 3); /* Put the breakpoint */ putdata(traced_process, regs.eip, code, 3); /* Let the process continue and execute the int 3 instruction */ ptrace(PTRACE_CONT, traced_process, NULL, NULL); wait(NULL); sleep(5); /*Segmentation fault (core dumped) printf("The process stopped, putting back " "the original instructions "); printf("Press <enter> to continue "); getchar();*/ putdata(traced_process, regs.eip, backup, 3); //putdata(traced_process, regs.eip, backup, 3); //TEST /* Setting the eip back to the original instruction to let the process continue */ ptrace(PTRACE_SETREGS, traced_process, NULL, ®s); ptrace(PTRACE_DETACH, traced_process, NULL, NULL); return 0;}
gcc -o pause pause.c
【执行】
1. run counter
./counter
2. find pid of counter
ps aux | grep counter
3. run pause(root)
./pause %pid%
【结果】
A进程部分输出如下,从时间间隔上可以明显区分出B程序控制A程序运行的时机。
My Counter: 0
1000217
My Counter: 1
6001265
My Counter: 2
1000604
My Counter: 3
1000585
My Counter: 4
6001558
My Counter: 5
1000564
…
【补充说明】
通过进一步思考,作者认为以上测试只能说明A程序被成功暂停和恢复(只利用ptrace的附加和脱离操作也可实现以上测试结果)。
基于以上测试,作者又做了两项尝试:一是只去除恢复原代码函数(putdata(traced_process, regs.eip, backup, 3)),测试结果发现A程序崩溃,提示Trace/breakpoint trap;二是将替换代码int80/int3 (char code[] = {0,0,0,0})全部修改成零,再去除恢复原代码函数,测试结果发现A程序崩溃,提示Segmentation Fault;
结合以上两项附加测试,作者认为可以充分证明代码注入成功。
【参考】
http://www.cnblogs.com/wangkangluo1/archive/2012/06/05/2535484.html
- [Ptrace]Linux内存替换(三)运行控制
- [Ptrace]Linux内存替换(六)动态链接库函数替换
- [Ptrace]Linux内存替换(一)函数介绍
- [Ptrace]Linux内存替换(二)信息获取
- [Ptrace]Linux内存替换(四)代码注入
- [Ptrace]Linux内存替换(五)x86_64平台代码注入
- LINUX 3.5.4 PTRACE(系列三)
- linux 分析 ptrace()
- linux 分析 ptrace()
- linux 分析 ptrace()
- linux 分析 ptrace()
- linux 分析 ptrace()
- linux ptrace
- linux ptrace
- linux ioctl与ptrace(转载+整理)
- LINUX 3.5.4 PTRACE(系列五)
- linux流量控制(三)
- linux并发控制(三)
- C# 协变逆变(泛型修饰符in和out)
- UVA 1572 Self-Assembly 拓扑排序
- eclipse快捷键
- hdu 1251 统计难题(字典树)
- PHPcms 安装
- [Ptrace]Linux内存替换(三)运行控制
- 南邮 OJ 1057 封杀病毒
- Web Service修炼之二Xfire+Spring
- Android自动化测试:Robotium在Android Studio中的使用
- 数据采集仪器-界面呈现1
- C语言和C++的区别与对比
- BP单隐层神经网络 代码实现 以及 详细步骤
- caffe下跑自己的数据
- ajax的datatype选项的值