如果您知道地址,您可以访问另一个程序的堆栈/堆吗?

Gam*_*ent 5 c++ memory ram pointers segmentation-fault

只是一个杂项问题。我有一个 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;
}
Run Code Online (Sandbox Code Playgroud)

它的作用是获取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;
}
Run Code Online (Sandbox Code Playgroud)

这会在尝试访问该值时导致分段错误,这可能是因为操作系统不希望我访问该值或者因为该实例中不存在该值。

无论这看起来多么不切实际和愚蠢,有没有办法克服这个问题?或者说这是不可能的?顺便说一句,我为什么应该/为什么不应该这样做?

编辑:我已经批准了克里斯的答案,因为当你在 Linux 上使用 root 运行它时它工作得很好。要求同时适用于 Mac 和 Windows 的东西会不会太过分了?我尝试在Mac系统上运行poke程序,但出现错误:无法访问pid 26112::没有这样的文件或目录,由行调用: fprintf(stderr, "usage: %s pid address value\n", av[0]);

Chr*_*odd 7

每个进程都有自己的地址空间,程序中的地址引用该地址空间,独立于任何其他地址空间中的地址。因此,当您将显式值放入这样的指针并使用它时,您将获得此进程中该地址处的任何内容(这可能是无效的,因此您会收到 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您随后运行该程序:

#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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它将打印类似于以下内容的行:

pid = 6376, &data = 0x7ffe255f3190, data = test
pid = 6376, &data = 0x7ffe255f3190, data = test
Run Code Online (Sandbox Code Playgroud)

如果您./poke 6376 0x7ffe255f3190 Hello在另一个窗口/终端中运行,它将更改为

pid = 6376, &data = 0x7ffe255f3190, data = Hello
pid = 6376, &data = 0x7ffe255f3190, data = Hello
Run Code Online (Sandbox Code Playgroud)