c++ - 如果你知道地址,你能访问另一个程序的堆栈/堆吗?

标签 c++ pointers memory segmentation-fault ram

只是一个杂项问题。
我有一个 C++ 程序:

#include <stdio.h>

int main() 
{
    while (1) {
        int value1 = 1;
        printf("%p\n", (void *)&value1);
        void* address = (void *)&value1;
        int value2 = *(int*)address;
        printf("%d\n",value2);
    }
    return 0;
}
它的作用是获取 value1 的地址,将其存储在 address 中,然后获取 address 中的变量并将其存储在 value2 中。
这工作得很好,但是,我想从另一个 C++ 程序访问变量。我试过这个(这个文件中有两种方法):
#include<iostream>
#include <cstdint>

int main() {
    std::cout << "before seg fault" << std::flush;
    uintptr_t p = <address>;
    int value = *reinterpret_cast<int *>(p);
    int value2 = *(int*)<address>;
    std::cout << "after seg fault"<< std::flush;
    std::cout << value;
    return 0;
}
这会在尝试访问该值时导致段错误,这可能是因为操作系统不希望我访问该值,或者因为它在此实例中不存在。
无论这看起来多么不切实际和愚蠢,有没有办法克服这个问题?或者是不可能的?作为旁注,为什么应该/为什么我不应该这样做?
编辑:我已经批准了 Chris 的回答,因为当你在 linux 上使用 root 运行它时它工作得很好。要求同样适用于 Mac 和 Windows 的东西会不会太过分了?我曾尝试在 Mac 系统上运行 poke 程序,但它给出了错误:无法访问 pid 26112::No such file or directory,由行调用:fprintf(stderr, "usage: %s pid address value\n", av[0]);

最佳答案

每个进程都有自己的地址空间,程序中的地址引用该地址空间,与任何其他地址空间中的地址无关。因此,当您将显式值放入这样的指针并使用它时,您将获得此进程中该地址的任何内容(这可能是无效的,因此您会收到 SEGFAULT 或类似错误),而不是访问其他进程.
在大多数操作系统上,有一些方法可以访问另一个进程的地址空间,但需要获得许可。例如,在 Linux 上,这个 poke程序可以修改另一个进程的地址空间:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int ac, char **av) {
    char    name[64];
    int     fd;
    if (ac != 4) {
        fprintf(stderr, "usage: %s pid address value\n", av[0]);
        exit(1); }
    sprintf(name, "/proc/%.10s/mem", av[1]);
    if ((fd = open(name, O_WRONLY)) < 0) {
        fprintf(stderr, "Can't access pid %s", av[1]);
        perror(":");
        exit(1); }
    lseek(fd, strtol(av[2], 0, 0), SEEK_SET);
    if (write(fd, av[3], strlen(av[3]) + 1) < 0)
        perror("write");
    return 0;
}
如果你然后运行这个程序:
#include <stdio.h>
#include <unistd.h>

int main() {
    char data[16] = "test";
    while (1) {
        printf("pid = %d, &data = %p, data = %s\n", getpid(), &data, data);
        sleep(2);
    }
}
它将打印如下所示的行:
pid = 6376, &data = 0x7ffe255f3190, data = test
pid = 6376, &data = 0x7ffe255f3190, data = test
如果你运行 ./poke 6376 0x7ffe255f3190 Hello在另一个窗口/终端中,它将更改为
pid = 6376, &data = 0x7ffe255f3190, data = Hello
pid = 6376, &data = 0x7ffe255f3190, data = Hello

关于c++ - 如果你知道地址,你能访问另一个程序的堆栈/堆吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68866194/

相关文章:

c++ - 如何使用 C++ 分发 lua 文件

c++ - 第一次异常 (ntdll.dll)

java - 更改java中LinkedList中元素的值

c - 在 C 中使用 scanf 进行解析

c - 你如何在 C 中将 void 指针转换为 char 指针

c++ - 将一个数组的内容复制到另一个数组会导致内存泄漏吗

c++ - Perfmon 中的 CPU 百分比

c++ - Visual Studio 2015 上的日志

java - 碎片化内存是什么样子的?

java - 如何预测递归方法的最大调用深度?