使用process_vm_readv从另一个进程修改整数值 [英] Modifying integer value from another process using process_vm_readv

查看:1967
本文介绍了使用process_vm_readv从另一个进程修改整数值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Ubuntu Linux编写两个程序.我正在尝试从另一个进程更改整数的值.我的第一个过程(A)是一个永久循环并在屏幕上显示该值的简单程序.该程序可以按预期工作,并且只需在屏幕上显示值-1430532899(0xAABBCCDD).

I am using Ubuntu Linux to write two programs. I am attempting to change the value of an integer from another process. My first process (A) is a simple program that loops forever and displays the value to the screen. This program works as intended and simply displays the value -1430532899 (0xAABBCCDD) to the screen.

#include <stdio.h>

int main()
{
    //The needle that I am looking for to change from another process
    int x = 0xAABBCCDD;

    //Loop forever printing out the value of x
    int counter = 0;
    while(1==1)
    {
        while(counter<100000000)
        {
            counter++;
        }
        counter = 0;
        printf("%d",x);
        fflush(stdout);
    }

    return 0;
}

在另一个终端中,我使用ps -e命令列出进程,并记下进程(A)的进程ID.接下来作为root用户使用(sudo),我运行下一个程序(B),然后输入从进程(A)中记下的进程ID.

In a separate terminal, I use the ps -e command to list the processes and note the process id for process (A). Next as root use (sudo) I run this next program (B) and enter in the process ID that I noted from process (A).

程序基本上从后向搜索(DD CC BB AA)的针头找到针头,并记下地址.然后,它尝试将十六进制值(0xEEEEEEEE)写入同一位置,但是当errno设置为14时,我得到一个错误的地址错误.奇怪的是,稍后在地址空间中,我能够将值成功写入地址(0x601000),但是指针(0xAABBCCDD)位于0x6005DF的地址我无法在其中写入. (但可以读得很清楚,因为那是我找到针的地方)

The program basically searches for the needle which is in memory backwards (DD CC BB AA) find the needle, and takes note of the address. It then goes and tries to write the hex value (0xEEEEEEEE) to that same location, but I get a bad address error when errno is set to 14. The strange thing is a little later in the address space, I am able to write the values successfully to the address (0x601000) but the address where the needle(0xAABBCCDD) is at 0x6005DF I cannot write there. (But can read obviously because that is where I found the needle)

#include <stdio.h>
#include <iostream>
#include <sys/uio.h>
#include <string>
#include <errno.h>
#include <vector>

using namespace std;

char getHex(char value);
string printHex(unsigned char* buffer, int length);
int getProcessId();

int main()
{
    //Get the process ID of the process we want to read and write
    int pid = getProcessId();

    //Lists of addresses where we find our needle 0xAABBCCDD and the addresses where we simply cannot read
    vector<long> needleAddresses;
    vector<long> unableToReadAddresses;

    unsigned char buf1[1000];  //buffer used to store memory values read from other process

    //Number of bytes read, also is -1 if an error has occurred
    ssize_t nread;

    //Structures used in the process_vm_readv system call
    struct iovec local[1];
    struct iovec remote[1];
    local[0].iov_base = buf1;
    local[0].iov_len = 1000;
    remote[0].iov_base = (void * ) 0x00000;     //start at address 0 and work up
    remote[0].iov_len = 1000;

    for(int i=0;i<10000;i++)
    {
        nread = process_vm_readv(pid, local, 1, remote, 1 ,0);

        if(nread == -1)
        {
            //errno is 14 then the problem is "bad address" 
            if(errno == 14)
                unableToReadAddresses.push_back((long)remote[0].iov_base);
        }
        else
        {
            cout<<printHex(buf1,local[0].iov_len);

            for(int j=0;j<1000-3;j++)
            {

                if(buf1[j] == 0xDD && buf1[j+1] == 0xCC && buf1[j+2] == 0xBB && buf1[j+3] == 0xAA)
                {       
                    needleAddresses.push_back((long)(remote[0].iov_base+j));
                }
            }

        }
        remote[0].iov_base += 1000;
    }



    cout<<"Addresses found at...";
    for(int i=0;i<needleAddresses.size();i++)
    {
        cout<<needleAddresses[i]<<endl;
    }

    //How many bytes written
    int nwrite = 0;

    struct iovec local2[1];
    struct iovec remote2[1];

    unsigned char data[] = {0xEE,0xEE,0xEE,0xEE};

    local2[0].iov_base = data;
    local2[0].iov_len = 4;
    remote2[0].iov_base = (void*)0x601000;
    remote2[0].iov_len = 4;

    for(int i=0;i<needleAddresses.size();i++)
    {
        cout<<"Attempting to write "<<printHex(data,4)<<" to address "<<needleAddresses[i]<<endl;
        remote2[0].iov_base = (void*)needleAddresses[i];

        nwrite = process_vm_writev(pid,local2,1,remote2,1,0);

        if(nwrite == -1)
        {
            cout<<"Error writing to "<<needleAddresses[i]<<endl;
        }
        else 
        {
            cout<<"Successfully wrote data";
        }
    }


    //For some reason THIS will work
    remote2[0].iov_base = (void*)0x601000;  
    nwrite = process_vm_writev(pid,local2,1,remote2,1,0);

    cout<<"Wrote "<<nwrite<<" Bytes to the address "<<0x601000 <<" "<<errno;

    return 0;
}

string printHex(unsigned char* buffer, int length)
{
    string retval;
    char temp;

    for(int i=0;i<length;i++)
    {

        temp = buffer[i];
        temp = temp>>4;
        temp = temp & 0x0F;
        retval += getHex(temp);

        temp = buffer[i];
        temp = temp & 0x0F;
        retval += getHex(temp);

        retval += ' ';
    }

    return retval;
}

char getHex(char value)
{
    if(value < 10)
    {
        return value+'0';
    }   
    else
    {
        value = value - 10;
        return value+'A';
    }
}

int getProcessId()
{
    int data = 0;
    printf("Please enter the process id...");
    scanf("%d",&data);
    return data;
}

最重要的是,我无法修改其他过程中重复的打印整数.

Bottom line is that I cannot modify the repeating printed integer from another process.

推荐答案

我至少可以看到这些问题.

I can see at least these problems.

  1. 没有人可以保证进程的可写存储器中任何地方都有0xAABBCCDD.编译器可以完全优化它,也可以将其放入寄存器中.确保变量将被放置在主存储器中的一种方法是声明它volatile.

volatile int x = 0xAABBCCDDEE;

  • 没有人保证进程的只读内存中的某个地方没有没有 0xAABBCCDD.相反,可以肯定的是,实际上那里存在这样一种价值.程序还可以在其他地方获取它以初始化变量?初始化可能会转换为类似于此的汇编指令

  • No one guarantees there's no 0xAABBCCDD somewhere in the read-only memory of the process. On the contrary, one could be quite certain there is in fact such a value there. Where else could the program possibly obtain it to initialise the variable? The initialisation probably translates to an assembly instruction similar to this

    mov eax, 0xAABBCCDD
    

    毫无疑问,

    包含与0xAABBCCDD匹配的位模式.地址0x6005DF可能位于.text节中.它极不可能出现在堆栈中,因为堆栈地址通常接近地址空间的顶部.

    which, unsurprisingly, contains a bit pattern that matches 0xAABBCCDD. The address 0x6005DF could well be in the .text section. It is extremely unlikely it is on the stack, because stack addresses are typically close to the top of the address space.

    64位进程的地址空间很大.没有希望在合理的时间内遍历所有内容.需要以某种方式限制地址范围.

    The address space of a 64-bit process is huge. There is no hope to traverse it all in a reasonable amount of time. One needs to limit the range of addresses somehow.

    这篇关于使用process_vm_readv从另一个进程修改整数值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆