我一直在尝试理解如何在Mac OS X上读取其他进程的内存,但是我没有太多的运气。我在网上看到很多示例使用ptrace
和PEEKDATA
等选项,但是在BSD上没有这个选项
[man ptrace
]。
int pid = fork();
if (pid > 0) {
// mess around with child-process's memory
}
在Mac OS X上如何读写另一个进程的内存?
我一直在尝试理解如何在Mac OS X上读取其他进程的内存,但是我没有太多的运气。我在网上看到很多示例使用ptrace
和PEEKDATA
等选项,但是在BSD上没有这个选项
[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()
等直接操作进程的地址空间。
vm_remap
,它允许您将外部进程的内存映射到自己的虚拟机中。 - Sergey L.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区域数据
[...]这解决了一个问题。我可以读写内存以设置中断点。 但是我仍然无法访问寄存器,而我需要能够操作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();
// 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()
sysctl -A
并搜索“kern.sysv.shmmax”来查看此设置。 - fixermarkstatic int
,它可能会被分配到同一内存位置,或以某种方式被定位。我有点想象一些查看游戏状态的游戏机器人就是这样运作的。我不确定这是否可行。 - Jeremy在进程背后操纵其内存是一件危险的事情,充满了风险。这就是为什么Mac OS X(像任何Unix系统一样)具有受保护的内存,并使进程彼此隔离。
当然可以做到:有共享内存的设施,可以在明确合作的进程之间进行共享。还有一些方法可以操作其他进程的地址空间,只要执行此操作的进程具有明确的权限(由安全框架授予)。但这是供编写调试工具的人使用的。对于在Mac OS X上进行的绝大多数开发来说,这不应该是正常的甚至是罕见的事件。