首页 > 系统相关 >进程注入-ptrace实现代码注入

进程注入-ptrace实现代码注入

时间:2024-07-25 13:40:58浏览次数:11  
标签:include int 代码 long PTRACE 注入 NULL ptrace

ptrace简介

ptrace是一个系统调用,使用过Linux系统多多少少会接触方便我们查看执行的程序的系统调用的strace命令或者编程时使用gdb进行程序调试。他们幕后原理工作其实就是ptrace完成的。
我们通过man ptrace命令可以查看ptrace的使用说明。
ptrace系统调从名字上看是用于进程跟踪的,它提供了父进程可以观察和控制其子进程执行的能力,并允许父进程检查和替换子进程的内核镜像(包括寄存器)的值。其基本原理是: 当使用了ptrace跟踪后,所有发送给被跟踪的子进程的信号(除了SIGKILL),都会被转发给父进程,而子进程则会被阻塞,这时子进程的状态就会被系统标注为TASK_TRACED。而父进程收到信号后,就可以对停止下来的子进程进行检查和修改,然后让子进程继续运行。

ptrace函数的定义

#include <sys/ptrace.h>
long ptrace(int request, int pid, int addr, int data);

函数描述:

request参数决定了系统调用的功能:
PTRACE_TRACEME:0
本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。
PTRACE_PEEKTEXT, PTRACE_PEEKDATA:1
从内存地址中读取一个字节,内存地址由addr给出。
PTRACE_PEEKUSR:3
从USER区域中读取一个字节,偏移量为addr。
PTRACE_POKETEXT:4, PTRACE_POKEDATA:5
往内存地址中写入一个字节。内存地址由addr给出。
PTRACE_POKEUSER:6
往USER区域中写入一个字节。偏移量为addr。
PTRACE_SYSCALL:24, PTRACE_CONT:7
重新运行。
PTRACE_KILL:8
杀掉子进程,使它退出。
PTRACE_SINGLESTEP:9
设置单步执行标志
PTRACE_ATTACH:16
跟踪指定pid 进程。
PTRACE_DETACH:17
结束跟踪

Intel386特有:

PTRACE_GETREGS
读取寄存器
PTRACE_SETREGS
设置寄存器
PTRACE_GETFPREGS
读取浮点寄存器
PTRACE_SETFPREGS
设置浮点寄存器
返回值
成功返回0,出错返回-1;

注意:init这类初始化文件不可以使用patrace

初次尝试

//gcc flag.c
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <unistd.h>


int main()
{   pid_t child;
    long orig_eax;
    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("/bin/ls", "ls", NULL);
    }
    else {
        wait(NULL);
        orig_rax = ptrace(PTRACE_PEEKUSER,
                          child, 8 * ORIG_RAX,
                          NULL);
        printf("The child made a "
               "system call %ld\n", orig_rax);
        ptrace(PTRACE_CONT, child, NULL, NULL);
    }
    return 0;
}

image.png
image.png
程序首先fork一个子进程,然后暂停子进程等待追踪,然后会返回0给父进程,就会进入else,wait等待内核通知,收到通知后,父进程就接管了子进程,然后PTRACE_PEEKUSR读取rax寄存器的内容存在orig_rax,打印rax,然后重启子进程执行ls。

注入测试

测试文件

#include<unistd.h>
#include<stdio.h>

int main()
{ 
   int i;
   printf("pid=%d\n",getpid());
    for(i = 0;i < 10; ++i) {
        printf("My counter: %d \n", i);
        sleep(2);
    }
    return 0;
}

注入文件

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <asm/ptrace-abi.h>
#include <string.h>
#include <stdio.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;

    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);
    }
}
long freespaceaddr(pid_t pid)
{
    FILE *fp;
    char filename[30];
    char line[85];
    long addr;
    char str[20];
    sprintf(filename, "/proc/%d/maps", pid);
    fp = fopen(filename, "r");
    if(fp == NULL)
        exit(1);
    while(fgets(line, 85, fp) != NULL) {
        sscanf(line, "%lx-%*lx %*s %*s %s", &addr, 
               str, str, str, str);
        if(strcmp(str, "00:00") == 0)
            break;
    }
    fclose(fp);
    return addr;
}
int main(int argc, char *argv[])
{ 
pid_t traced_process;
    struct user_regs_struct regs, newregs;
    long ins;
    int len = 132;
    char insertcode[] =
        "\xeb\x15\x5e\xb8\x04\x00"
        "\x00\x00\xbb\x02\x00\x00\x00\x89\xf1\xba"
        "\x0c\x00\x00\x00\xcd\x80\xcc\xe8\xe6\xff"
        "\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f"
        "\x72\x6c\x64\x0a\x00";
    char backup[len];
    if(argc != 2) {
        printf("Usage: %s <pid to be traced> ", 
               argv[0], argv[1]);
        exit(1);
    }
    traced_process = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, traced_process, 
           NULL, NULL);
    wait(NULL);
    ptrace(PTRACE_GETREGS, traced_process, 
           NULL, &regs);
    getdata(traced_process, regs.rip, backup, len);
    putdata(traced_process, regs.rip, 
            insertcode, len);
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    ptrace(PTRACE_CONT, traced_process, 
           NULL, NULL);
    wait(NULL);
    printf("The process stopped, Putting back "
           "the original instructions ");
    putdata(traced_process, regs.rip, backup, len);
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    printf("Letting it continue with "
           "original flow ");
    ptrace(PTRACE_DETACH, traced_process,
           NULL, NULL);
    return 0;
}
~/Desktop/IOT/GDB$ ./test
pid=31166
My counter: 0 
My counter: 1 
My counter: 2 
My counter: 3 
My counter: 4 
Hello World
My counter: 5 
My counter: 6 
My counter: 7 
My counter: 8 
My counter: 9
~/Desktop/IOT/GDB$ ./shell 3604
The process stopped, Putting back the original instructions Letting it continue with original flow

标签:include,int,代码,long,PTRACE,注入,NULL,ptrace
From: https://www.cnblogs.com/blonet/p/18322826

相关文章

  • 翻转字符串里的单词(双指针去重思路+代码实现)
    题目①双指针思路整体思路:去重+反转数组填充类问题都可以使用双指针方式!原理如同:双指针移除元素去重其实是一种删除操作,1.双指针去重fast判断slow指向待填充位置额外再使用一个变量:isblock(判断之前是否出现过空格)连续空格的话只保留一个空格,达到去重效果遇......
  • 力扣:三数之和(左右双指针思路+动画演示+代码实现)
    题目①双指针思路(双指针匹配方式,还不涉及去重)1.需要的变量个数(三个变量,双指针作为其中两个)left、right已经两个变量,表示两个数。题目求三数之和,只需要另外一个变量i即可!所以一共是nums[i]、nums[left]、nums[right]。存储满足条件的这三个值2.双指针工作原理......
  • 从源代码安装 python3.5 后如何修复 virtualenv 的 python pip 分段错误(核心转储)响应
    背景嗨,我的主要目标是为许多使用旧版本Python的项目创建一个virtualenv,这些项目与系统版本(3.10.x)是分开的。我是使用PopOS22.04并进行所有更新。由于此错误,我什至无法使用pip。我也阅读了周围的内容,但我读到的所有解决方案要么输出日志文件,要么......
  • 代码随想录算法训练营第 23 天 |LeetCode 39. 组合总和 LeetCode 40.组合总和II LeetC
    代码随想录算法训练营Day23代码随想录算法训练营第23天|LeetCode39.组合总和LeetCode40.组合总和IILeetCode131.分割回文串目录代码随想录算法训练营前言LeetCode39.组合总和LeetCode40.组合总和IILeetCode131.分割回文串一、基础1、回溯可以看成N叉树2、去......
  • 代码随想录算法训练营第 22 天 |LeetCode77. 组合 LeetCode 216.组合总和III LeetCode
    代码随想录算法训练营Day22代码随想录算法训练营第22天|LeetCode77.组合LeetCode216.组合总和IIILeetCode17.电话号码的字母组合目录代码随想录算法训练营前言LeetCode77.组合LeetCode216.组合总和IIILeetCode17.电话号码的字母组合一、基础1、回溯可以解......
  • MySQL配置开发文章:学习路线、使用案例及代码示例
    引言MySQL是一个广泛使用的开源关系型数据库管理系统,由于其性能高、成本低、可靠性强,成为了许多开发者的首选工具,本文将介绍MySQL的基本配置、学习路线、使用案例及代码示例,帮助你更好地掌握MySQL的使用MySQL配置开发教程学习路线基础知识:了解关系型数据库的基本概念,熟......
  • 我的 Python 代码和 Cycle Time 小部件之间的平均周期时间不同
    我过去遇到过如何在周期时间小部件中计算平均周期时间的一些问题,因此我决定使用Python进行分析,看看是否找到任何方法来计算平均周期时间并获得相同的结果周期时间小部件中显示的值。我的问题是我无法达到周期时间小部件中显示的相同的平均周期时间值。你们能帮我解决这......
  • 抖音直播弹幕数据逆向:websocket和JS注入
    ......
  • 代码随想录算法训练营第二十二天|回溯算法part01
    第77题.组合在单个集合1-n中,寻找所有个数为k的组合。和所有递归一样,都有三部曲。确定参数与返回值确定终止条件单层逻辑首先,回溯算法的返回值一般是void,参数依照题目要求而增加,在这一题中,参数有n,k还有startIndex。终止条件是path的size等于k,将path存放在result中。......
  • ccfcsp 201803.2 碰撞的小球 100分代码
    本题是一道小模拟规模小难度在碰撞检测在写模拟题时的思路应该是先找到应该储存的信息是哪些,抽象出来,应该模拟的方法是哪些。类似oop。includeusingnamespacestd;constintL=1000;structball{intp;chard=1;//只可能为1或-1,表示方向}b[L+1];intmain(){int......