我一直在尝试了解如何在 Mac OS X 上读取其他进程的内存,但我运气不佳。我在网上看到了很多使用ptrace
with等的示例,但是它在 BSD [ ]PEEKDATA
上没有该选项。man ptrace
int pid = fork();
if (pid > 0) {
// mess around with child-process's memory
}
如何在 Mac OS X 上读取和写入另一个进程的内存?
我一直在尝试了解如何在 Mac OS X 上读取其他进程的内存,但我运气不佳。我在网上看到了很多使用ptrace
with等的示例,但是它在 BSD [ ]PEEKDATA
上没有该选项。man ptrace
int pid = fork();
if (pid > 0) {
// mess around with child-process's memory
}
如何在 Mac OS X 上读取和写入另一个进程的内存?
使用task_for_pid()
或其他方法获取目标进程的任务端口。此后,您可以使用vm_read()
、vm_write()
等直接操作进程的地址空间。
Matasano Chargen 前段时间发表了一篇关于将一些调试代码移植到 OS X 的好帖子,其中包括学习如何在另一个进程中读取和写入内存(除其他外)。
事实证明,苹果以其无限的智慧,已经将
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。
我知道这个线程已有 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();
如果您希望能够在进程之间共享内存块,您应该查看 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()
您想使用共享内存方法进行进程间通信。有关其他公共方法的摘要,请参见此处
我很快就在这本书中找到了你需要的东西,它包含了当今所有 UNIX 通用的所有 API(比我想象的要多得多)。你应该在未来买它。这本书是一组(数百)印刷手册页,很少安装在现代机器上。每个手册页都详细介绍了一个 C 函数。
我很快就找到了shmat() shmctl();shmdt()和shmget()。我没有广泛搜索,也许还有更多。
它看起来有点过时了,但是:是的,现代 UNIX 操作系统的基本用户空间 API 可以追溯到 80 年代。
更新:书中描述的大多数功能都是 POSIX C 头文件的一部分,您不需要安装任何东西。很少有例外,例如原始库“curses”。
我肯定找到了您需要的简短实现(只有一个源文件(main.c))。它是专门为 XNU 设计的。
它在谷歌搜索的前十名中,关键字«dump process memory os x»
源代码在这里
但从虚拟地址空间点de vue的严格角度来看,您应该对这个问题更感兴趣:OS X:生成核心转储而不关闭进程?(也看这个)
当您查看 gcore 源代码时,执行此操作非常复杂,因为您需要处理胎面及其状态......
在大多数 Linux 发行版上,gcore 程序现在是 GDB 包的一部分。我认为 OSX 版本是使用 xcode/开发工具安装的。
更新: wxHexEditor 是一个可以编辑设备的编辑器。它还可以像编辑常规文件一样编辑进程内存。它适用于所有 UNIX 机器。
在其背后操纵进程的内存是一件坏事,并且充满危险。这就是为什么 Mac OS X(像任何 Unix 系统一样)具有受保护的内存,并使进程彼此隔离的原因。
当然可以:在显式合作的进程之间有共享内存的设施。也有方法来操作其他进程的地址空间,只要这样做的进程具有这样做的明确权利(如安全框架所授予的那样)。但这对于编写调试工具的人来说是可用的。对于 Mac OS X 上的绝大多数开发来说,这不应该是正常的——甚至是罕见的——发生。
一般来说,我建议您使用常规 open() 打开临时文件。一旦它在两个进程中都打开,您就可以从文件系统中 unlink() 它,并且您的设置与使用 shm_open 时的设置非常相似。该过程与 Scott Marcy 为 shm_open 指定的过程极为相似。
这种方法的缺点是,如果执行 unlink() 的进程崩溃,您最终会得到一个未使用的文件,并且没有进程负责清理它。这个缺点与 shm_open 相同,因为如果没有任何 shm_unlinks 给定名称,则该名称保留在共享内存空间中,可供未来进程使用 shm_opened。