【问题标题】:How to read and change value from memory in Linux?如何在 Linux 中读取和更改内存中的值?
【发布时间】:2023-03-30 18:50:01
【问题描述】:

main.c中的代码

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

int main() {
    int c_variable = 0; // the target

    for(int x = 0; x < 100; x++) {
        c_variable += 5; // increase by 5 to change the value of the int
        printf("%i\n", c_variable); // print current value
        sleep(8); // sleep so I have time to scan memory
    }

    return 0;

}

我想要实现的是读取整数c_variable,然后在另一个 .c 程序中对其进行修改。我在 linux 上,所以我做了ps -A | grep main 并得到了正在运行的程序的 PID。然后我做了sudo scanmem PID 并输入了c_variable 的当前值几次。我只剩下三个内存地址,执行命令set 500 更改了程序打印的值,有效地将内存地址的值更改为 500 而不是 35 或程序当前的任何值。然后我执行了以下代码

#include <stdio.h>

int main() {
    const long unsigned addr = 0x772d85fa1008; // one of the three addresses from scanmem
    printf("%lu\n", addr);

    return 0;
}

但我得到了一些随机的长串数字,而不是当前数字。我读过的关于如何在 linux 上读写内存的教程和答案不必使用long unsigned,而是可以使用 char* 或只使用 int* 。我的内存地址似乎有点长,我以前没有看到内存地址那么久。无论如何,如何读写整数c_variable的内存地址?

编辑:scanmem 的输出看起来像这样

info: we currently have 3 matches.
3> list
[ 0] 7771ff64b090,  6 +        1e090, stack, 20, [I64 I32 I16 I8 ]
[ 1] 7771ff64b5d8,  6 +        1e5d8, stack, 20, [I64 I32 I16 I8 ]
[ 2] 7771ff64b698,  6 +        1e698, stack, 20, [I32 I16 I8 ]
3> set 50
info: setting *0x7771ff64b090 to 0x32...
info: setting *0x7771ff64b5d8 to 0x32...
info: setting *0x7771ff64b698 to 0x32...

输出

...
150
155
160
165
170
175
55
60
65
...

【问题讨论】:

  • 您打印的是实际地址号码,而不是地址上的号码。
  • 随机数字串是否与 0x772d85fa1008 或其十进制表示 131037404991496 相同?
  • 您知道当前大多数操作系统中两个正在运行的程序的地址空间是相互独立的吗?同一个地址在不同的程序中可以保存不同的值。
  • @Yunnosch 你能给我推荐一个学习资源吗?
  • 一个有效的问题,但我不得不让你失望。我不知道有什么值得推荐的资源。

标签: c linux pointers memory


【解决方案1】:

在 Linux 下运行的进程一般都有自己的虚拟化内存空间。如果要访问其他进程的内存空间,Linux API中已经做了安排,见shmctl, shmget, shmat, shmdt。

【讨论】:

    【解决方案2】:

    您正在打印实际的地址编号,但以十进制表示,而不是地址中的内容。

    const int *addr = (int *) 0x772d85fa1008;
    printf("%d\n", *addr);
    

    您必须将addr 声明为指针类型。更具体地说,是一个 指向整数的指针。它的值 (0x772d85fa1008) 保存整数的地址

    然后,在printf 调用中,您取消引用它以获取存储在地址处的实际整数。

    尽管在实践中我不能保证这是否会起作用,因为现代操作系统中的内存并不像你想象的那么简单。但我没有足够的知识来评估这一点。

    【讨论】:

    • 我收到一个错误:cannot initialize a variable of type const int * with an rvalue of type long,因为地址太长了。是不是太长了?我看到的教程都用int了,但是这个地址太长了吧?
    • 在赋值前尝试将地址常量转换为指针。查看我的编辑。
    • @boool3max 会导致Segmentation fault (core dumped) 并在 sudo 中运行程序会导致找到所有三个地址的Segmentation fault。在帖子中查看我的编辑。
    • 嗯,这就是你的答案。进程之间的内存不是那么简单
    猜你喜欢
    • 2012-11-28
    • 1970-01-01
    • 2014-11-09
    • 2016-03-20
    • 2018-05-25
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    相关资源
    最近更新 更多