注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

widebright的个人空间

// 编程和生活

 
 
 

日志

 
 

重定向已经运行进程的标准输出到文件的办法(通过ptrace注入代码到其他进程并运行)  

2010-05-11 20:19:44|  分类: linux相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

上次看到CSDN里面有人问这个问题,我觉得用ptrace这个系统调用是可以实现的。前两天在IBM developworks看到中兴工程师写的一篇文章是用ptrace来挂钩系统调用然后获取已运行进程的网络包的,他文章里面把程序之间通讯用的网络包分离出来然后在wireshrark中分析。通过这篇文档,证实我之前的想法应该也是可行的。最近工作偷懒,就试试这个吧。

1、重定向标准输出,用dup2系统调用,dup2(file,1)把一个打开的文件描述符的复制到标准输出1去应该就可以了吧。参考“Understanding+The+Linux+Kernel+3rd.pdf” 一书关于管道使用那一章举的ls| more 例子。

2、ptrace这个系统调用功能很强大,可以用来调试进程,挂钩系统调用函数,等待。Windows上面的read/writeprocessmemory以及hook api技术都可以通过这个来实现。调试器也都可以使用这个来做了,不知道GDB是不是也是用ptrace来实现的?

   我们用重定向标准输出,就用ptrace注入一段调试代码到目标进程,然后在里面调用dup2等几个函数就可以了。

3、ptrace也有一个缺陷,就是如果要attach的进程如果本来就有父进程的话,那么被我们用ptrace处理之后,他原本的父进程是没有办法再受到来自被attach进程的消息了。好像也没有办法恢复。自己看一下ptrace的文档吧,不知道我理解错了没有。反正如果目标进程有父进程的话,用这个办法难免有些影响,实际运用的时候要考虑一下。

4、代码大多从“Playing with ptrace, Part II http://www.linuxjournal.com/node/6210/print”这篇文章里面复制过来,可以去看看原文关于ptrace的用法说名吧。只是我把他本来打印“hello world”的汇编代码改为调用两个系统调用的了。

   调用Linux系统调用通过int $80的80号中断来进行,调用时,其中eax存放系统中断号码,ebx ,ecx等等依次为传给系统调用的参数。系统调用返回时eax为返回值。可以参考一下“Professional+Assembly+Language.pdf” 一书关于在汇编中使用文件系统调用来操作文件的例子。

   其实,好像说新的cpu可以通过sysenter指令来进入系统调用的,那个性能要比int 80要好些。大家可以试试吧。我对汇编不是很熟悉就不试了。我在virtuabox + ubuntu 10.04上面测试int $80还是可以正常工作的,可能现在系统对两种办法都还支持吧。

代码如下:

----------test.c---------------------------------------------

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/ptrace.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <asm/ptrace.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] = '\0';

}

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;

    i = 0;

    j = len / long_size;

    laddr = str;

    while(i < j) {

        memcpy(data.chars, laddr, long_size);

        ptrace(PTRACE_POKEDATA, child,

               addr + i * 4, data.val);

        ++i;

        laddr += long_size;

    }

    j = len % long_size;

    if(j != 0) {

        memcpy(data.chars, laddr, j);

        ptrace(PTRACE_POKEDATA, child,

               addr + i * 4, data.val);

    }

}

int main(int argc, char *argv[])

{

//   int log;

//   log = open("/tmp/widebright.txt",O_CREAT|O_RDWR|O_TRUNC, S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP| S_IROTH|S_IWOTH );

//printf ("result =%d\n",log);

//exit(0);

// if (log != -1){

//       int result =dup2(log,1); //重定向标准输出

       //if (result == -1)

       // printf ("dup2 return failed\n");

       //printf ("result =%d\n", write (log, "failed\n", 5));

// }

   //printf("ddddd,hahahha\n");

  

// close (log);

/*

__asm__ (

"jmp forward\n\t"

"backward:\n\t"

         "popl   %esi #get path string address \n\t"

         "movl   $5, %eax #sys_open number arch/x86/kernel/syscall_table_32.S\n\t"

         "movl   %esi, %ebx\n\t"

         "movl   $0x242, %ecx\n\t"

         "movl   $0x1b6, %edx #all has read and write permissions\n\t"

         "int    $0x80\n\t"

         "test   %eax,%eax\n\t"

         "js end\n\t"

         "mov    %eax , %ebx # parm 1\n\t"

         "movl   $63, %eax #sys_dup2 number arch/x86/kernel/syscall_table_32.S\n\t"

         "movl   $1, %ecx     # parm 2\n\t "

         "int    $0x80\n\t"

"#jmp end\n\t"

"end:\n\t"

         "int3\n\t"

"forward:\n\t"

         "call   backward\n\t"

         ".string \"/tmp/widebright.txt\"\n\t"

"#end:\n\t"

);

(gdb) x/66xb backward-2

0x8048c10 <main+53>: 0xeb 0x27 0x5e 0xb8 0x05 0x00 0x00 0x00

0x8048c18 <main+61>: 0x89 0xf3 0xb9 0x42 0x02 0x00 0x00 0xba

0x8048c20 <main+69>: 0xb6 0x01 0x00 0x00 0xcd 0x80 0x85 0xc0

0x8048c28 <main+77>: 0x78 0x0e 0x89 0xc3 0xb8 0x3f 0x00 0x00

0x8048c30 <main+85>: 0x00 0xb9 0x01 0x00 0x00 0x00 0xcd 0x80

0x8048c38 <end>: 0xcc 0xe8 0xd4 0xff 0xff 0xff 0x2f 0x74

0x8048c40 <forward+7>: 0x6d 0x70 0x2f 0x77 0x69 0x64 0x65 0x62

0x8048c48 <forward+15>: 0x72 0x69 0x67 0x68 0x74 0x2e 0x74 0x78

0x8048c50 <forward+23>: 0x74 0x00

*/

//printf("ddddd,hahahha\n");

// return 0;

    pid_t traced_process;

    struct pt_regs regs, newregs;

    long ins;

    const int len = 66;

    char insertcode[] =

{0xeb, 0x27, 0x5e, 0xb8, 0x05, 0x00, 0x00, 0x00,

0x89, 0xf3, 0xb9, 0x42, 0x02, 0x00, 0x00, 0xba,

0xb6, 0x01, 0x00, 0x00, 0xcd, 0x80, 0x85, 0xc0,

0x78, 0x0e, 0x89, 0xc3, 0xb8, 0x3f, 0x00, 0x00,

0x00, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd, 0x80,

0xcc, 0xe8, 0xd4, 0xff, 0xff, 0xff, 0x2f, 0x74,

0x6d, 0x70, 0x2f, 0x77, 0x69, 0x64, 0x65, 0x62,

0x72, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x74, 0x78,

0x74, 0x00};

    char backup[len];

    if(argc != 2) {

        printf("Usage: %s <pid to be traced>\n",

               argv[0], argv[1]);

        exit(1);

    }

    traced_process = atoi(argv[1]);

    ptrace(PTRACE_ATTACH, traced_process,

           NULL, NULL);

    wait(NULL); //等待attach成功。目标进程被断下

    ptrace(PTRACE_GETREGS, traced_process,

           NULL, &regs); //获取目标进程当前的寄存器状态

    getdata(traced_process, regs.eip, backup, len);

    putdata(traced_process, regs.eip,

            insertcode, len); //注入我们的指令到当前运行的位置。

    ptrace(PTRACE_SETREGS, traced_process,

           NULL, &regs);

    ptrace(PTRACE_CONT, traced_process,

           NULL, NULL); //继续运行

    wait(NULL); //等待我们汇编代码里面的int3 调试断点。

    printf("The process stopped, Putting back "

           "the original instructions\n");

    ptrace(PTRACE_GETREGS, traced_process,

           NULL, &newregs);

   // printf("\n%ld-%ld\n",regs.eip,newregs.eip);

   // sleep(10);

    putdata(traced_process, regs.eip, backup, len); //还原原本的代码

    ptrace(PTRACE_SETREGS, traced_process,

           NULL, &regs);

    printf("Letting it continue with "

           "original flow\n");

    ptrace(PTRACE_DETACH, traced_process,

           NULL, NULL);

    return 0;

}

-------------写一个简单的测试例子 test2.c--------------------

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

int main(void)

{

   int i = 0;

   while (i < 20000000)

   {                   

      printf("current number is %d\n",i);

      i++;

      sleep(5);        

   }

}

------------------------------------------

测试一下。

gcc test2.c -o test.exe

桌面$ ./test.exe

current number is 0

current number is 1

current number is 2

current number is 3

current number is 4

current number is 5

current number is 6

current number is 7

current number is 8

current number is 9

current number is 10

current number is 11

current number is 12

current number is 13

current number is 14

^C

-----------

桌面$ ps -ef |grep test.exe

1000      4609 3554 0 10:51 pts/0    00:00:00 ./test.exe

1000      4667 4295 0 10:52 pts/1    00:00:00 grep --color=auto test.exe

桌面$ ./a.out 4609

The process stopped, Putting back the original instructions

Letting it continue with original flow

桌面$ cat /tmp/widebright.txt

current number is 15

桌面$ cat /tmp/widebright.txt

current number is 15

current number is 16

桌面$ cat /tmp/widebright.txt

current number is 15

current number is 16

可以看到test。exe的标准输出确实被我们重定向到这个/tmp/widebright.txt文件里面去了。

  评论这张
 
阅读(629)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017