25

我一直在尝试了解如何在 Mac OS X 上读取其他进程的内存,但我运气不佳。我在网上看到了很多使用ptracewith等的示例,但是它在 BSD [ ]PEEKDATA上没有该选项。man ptrace

int pid = fork();
if (pid > 0) {
    // mess around with child-process's memory
}

如何在 Mac OS X 上读取和写入另一个进程的内存?

4

8 回答 8

16

使用task_for_pid()或其他方法获取目标进程的任务端口。此后,您可以使用vm_read()vm_write()等直接操作进程的地址空间。

于 2008-09-15T13:48:35.297 回答
12

Matasano Chargen 前段时间发表了一篇关于将一些调试代码移植到 OS X 的好帖子,其中包括学习如何在另一个进程中读取和写入内存(除其他外)。

它必须工作,否则 GDB 不会

事实证明,苹果以其无限的智慧,已经将ptrace(). OS X 手册页列出了以下请求代码:

  • PT_ATTACH— 选择要调试的进程
  • PT_DENY_ATTACH— 因此进程可以阻止自己被调试
    [...]

没有提到读取或写入内存或寄存器。如果手册页没有在错误代码部分中也提到PT_GETREGS, PT_SETREGS,PT_GETFPREGS和,那将是令人沮丧的。PT_SETFPREGS所以,我检查了ptrace.h. 在那里我发现:

  • PT_READ_I——阅读指导词
  • PT_READ_D— 读取数据字
  • PT_READ_U— 如果您的年龄足以记住 U 区是什么,则可以读取 U 区数据
    [...]

有一个问题解决了。我可以为断点读写内存。但是我仍然无法访问寄存器,我需要能够弄乱 EIP。

于 2008-08-14T04:46:37.850 回答
9

我知道这个线程已有 100 年历史,但对于从搜索引擎来到这里的人来说:

xnumem完全符合您的要求,操作和读取进程间内存。

// Create new xnu_proc instance
xnu_proc *Process = new xnu_proc();

// Attach to pid (or process name)
Process->Attach(getpid());

// Manipulate memory
int i = 1337, i2 = 0;
i2 = process->memory().Read<int>((uintptr_t)&i);

// Detach from process
Process->Detach();
于 2014-07-27T20:12:47.623 回答
6

如果您希望能够在进程之间共享内存块,您应该查看 shm_open(2) 和 mmap(2)。在一个进程中分配一块内存并将路径(用于 shm_open)传递给另一个进程非常容易,然后两者都可以一起发疯。正如 Chris Hanson 所提到的,这比在另一个进程的地址空间中闲逛要安全得多。当然,如果你不能控制这两个过程,这对你没有多大好处。

(请注意, shm_open 的最大路径长度似乎是 26 字节,尽管这似乎没有在任何地方记录。)

// Create shared memory block
void* sharedMemory = NULL;
size_t shmemSize = 123456;
const char* shmName = "mySharedMemPath";        
int shFD = shm_open(shmName, (O_CREAT | O_EXCL | O_RDWR), 0600);
if (shFD >= 0) {
    if (ftruncate(shFD, shmemSize) == 0) {
        sharedMemory = mmap(NULL, shmemSize, (PROT_READ | PROT_WRITE), MAP_SHARED, shFD, 0);
        if (sharedMemory != MAP_FAILED) {
            // Initialize shared memory if needed
            // Send 'shmemSize' & 'shmemSize' to other process(es)
        } else handle error
    } else handle error
    close(shFD);        // Note: sharedMemory still valid until munmap() called
} else handle error

...
Do stuff with shared memory
...

// Tear down shared memory
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize);
if (shFD >= 0) shm_unlink(shmName);





// Get the shared memory block from another process
void* sharedMemory = NULL;
size_t shmemSize = 123456;              // Or fetched via some other form of IPC
const char* shmName = "mySharedMemPath";// Or fetched via some other form of IPC
int shFD = shm_open(shmName, (O_RDONLY), 0600); // Can be R/W if you want
if (shFD >= 0) {
    data = mmap(NULL, shmemSize, PROT_READ, MAP_SHARED, shFD, 0);
    if (data != MAP_FAILED) {
        // Check shared memory for validity
    } else handle error
    close(shFD);        // Note: sharedMemory still valid until munmap() called
} else handle error


...
Do stuff with shared memory
...

// Tear down shared memory
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize);
// Only the creator should shm_unlink()
于 2008-09-15T16:08:25.320 回答
2

您想使用共享内存方法进行进程间通信。有关其他公共方法的摘要,请参见此处

我很快就在这本书中找到了你需要的东西,它包含了当今所有 UNIX 通用的所有 API(比我想象的要多得多)。你应该在未来买它。这本书是一组(数百)印刷手册页,很少安装在现代机器上。每个手册页都详细介绍了一个 C 函数。

我很快就找到了shmat() shmctl()shmdt()shmget()。我没有广泛搜索,也许还有更多。

它看起来有点过时了,但是:是的,现代 UNIX 操作系统的基本用户空间 API 可以追溯到 80 年代。

更新:书中描述的大多数功能都是 POSIX C 头文件的一部分,您不需要安装任何东西。很少有例外,例如原始库“curses”。

于 2013-09-30T23:19:02.240 回答
2

我肯定找到了您需要的简短实现(只有一个源文件(main.c))。它是专门为 XNU 设计的。

它在谷歌搜索的前十名中,关键字«dump process memory os x»

源代码在这里

但从虚拟地址空间点de vue的严格角度来看,您应该对这个问题更感兴趣:OS X:生成核心转储而不关闭进程?(也看这个

当您查看 gcore 源代码时,执行此操作非常复杂,因为您需要处理胎面及其状态......

在大多数 Linux 发行版上,gcore 程序现在是 GDB 包的一部分。我认为 OSX 版本是使用 xcode/开发工具安装的。

更新: wxHexEditor 是一个可以编辑设备的编辑器。它还可以像编辑常规文件一样编辑进程内存。它适用于所有 UNIX 机器。

于 2013-10-07T23:45:37.623 回答
1

在其背后操纵进程的内存是一件坏事,并且充满危险。这就是为什么 Mac OS X(像任何 Unix 系统一样)具有受保护的内存,并使进程彼此隔离的原因。

当然可以:在显式合作的进程之间有共享内存的设施。也有方法来操作其他进程的地址空间,只要这样做的进程具有这样做的明确权利(如安全框架所授予的那样)。但这对于编写调试工具的人来说是可用的。对于 Mac OS X 上的绝大多数开发来说,这不应该是正常的——甚至是罕见的——发生。

于 2008-08-14T09:19:08.283 回答
1

一般来说,我建议您使用常规 open() 打开临时文件。一旦它在两个进程中都打开,您就可以从文件系统中 unlink() 它,并且您的设置与使用 shm_open 时的设置非常相似。该过程与 Scott Marcy 为 shm_open 指定的过程极为相似。

这种方法的缺点是,如果执行 unlink() 的进程崩溃,您最终会得到一个未使用的文件,并且没有进程负责清理它。这个缺点与 shm_open 相同,因为如果没有任何 shm_unlinks 给定名称,则该名称保留在共享内存空间中,可供未来进程使用 shm_opened。

于 2010-01-19T16:36:48.617 回答