阅读其他进程 OS X 中的内存?

发布于 2024-07-04 04:53:05 字数 423 浏览 7 评论 0原文

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

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

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

I've been trying to understand how to read the memory of other processes on Mac OS X, but I'm not having much luck. I've seen many examples online using ptrace with PEEKDATA and such, however it doesn't have that option on BSD [man ptrace].

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

How is it possible to read from and write to the memory of another process on Mac OS X?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

我偏爱纯白色 2024-07-11 04:53:05

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

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

In general, I would recommend that you use regular open() to open a temporary file. Once it's open in both processes, you can unlink() it from the filesystem and you'll be set up much like you would be if you'd used shm_open. The procedure is extremely similar to the one specified by Scott Marcy for shm_open.

The disadvantage to this approach is that if the process that will be doing the unlink() crashes, you end up with an unused file and no process has the responsibility of cleaning it up. This disadvantage is shared with shm_open, because if nothing shm_unlinks a given name, the name remains in the shared memory space, available to be shm_opened by future processes.

呢古 2024-07-11 04:53:05

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

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

Manipulating a process's memory behind its back is a Bad Thing and is fraught with peril. That's why Mac OS X (like any Unix system) has protected memory, and keeps processes isolated from one another.

Of course it can be done: There are facilities for shared memory between processes that explicitly cooperate. There are also ways to manipulate other processes' address spaces as long as the process doing so has explicit right to do so (as granted by the security framework). But that's there for people who are writing debugging tools to use. It's not something that should be a normal — or even rare — occurrence for the vast majority of development on Mac OS X.

遗忘曾经 2024-07-11 04:53:05

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

Use task_for_pid() or other methods to obtain the target process’s task port. Thereafter, you can directly manipulate the process’s address space using vm_read(), vm_write(), and others.

余生再见 2024-07-11 04:53:05

我知道这个帖子已经有 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();

I know this thread is 100 years old, but for people coming here from a search engine:

xnumem does exactly what you are looking for, manipulate and read inter-process memory.

// 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();
悲欢浪云 2024-07-11 04:53:05

Matasano Chargen 不久前发表了一篇关于将一些调试代码移植到 OS X 的好文章,其中包括学习如何在另一个进程中读写内存(除其他外)。

它必须工作,否则 GDB 不会

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

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

没有提及读取或写入内存或寄存器。 如果手册页没有在其中提到 PT_GETREGSPT_SETREGSPT_GETFPREGSPT_SETFPREGS,那将会令人沮丧。错误代码部分。 因此,我检查了 ptrace.h。 在那里我发现:

  • PT_READ_I — 读取指令字
  • PT_READ_D — 读取数据字
  • PT_READ_U — 如果您足够大,还记得 U 区是什么,则读取 U 区数据
    [...]

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

Matasano Chargen had a good post a while back on porting some debugging code to OS X, which included learning how to read and write memory in another process (among other things).

It has to work, otherwise GDB wouldn't:

It turns out Apple, in their infinite wisdom, had gutted ptrace(). The OS X man page lists the following request codes:

  • PT_ATTACH — to pick a process to debug
  • PT_DENY_ATTACH — so processes can stop themselves from being debugged
    [...]

No mention of reading or writing memory or registers. Which would have been discouraging if the man page had not also mentioned PT_GETREGS, PT_SETREGS, PT_GETFPREGS, and PT_SETFPREGS in the error codes section. So, I checked ptrace.h. There I found:

  • PT_READ_I — to read instruction words
  • PT_READ_D — to read data words
  • PT_READ_U — to read U area data if you’re old enough to remember what the U area is
    [...]

There’s one problem solved. I can read and write memory for breakpoints. But I still can’t get access to registers, and I need to be able to mess with EIP.

无声无音无过去 2024-07-11 04:53:05

如果您希望能够在进程之间共享内存块,则应该查看 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()

It you're looking to be able to share chunks of memory between processes, you should check out shm_open(2) and mmap(2). It's pretty easy to allocate a chunk of memory in one process and pass the path (for shm_open) to another and both can then go crazy together. This is a lot safer than poking around in another process's address space as Chris Hanson mentions. Of course, if you don't have control over both processes, this won't do you much good.

(Be aware that the max path length for shm_open appears to be 26 bytes, although this doesn't seem to be documented anywhere.)

// 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()
莫相离 2024-07-11 04:53:05

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

它位于 Google 搜索前十名的结果中,关键字为 « dump process memory os x »

源代码为

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

当你查看gcore源代码时,它是相当复杂的这样做是因为您需要处理线程及其状态...

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

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

I have definitely found a short implementation of what you need (only one source file (main.c)).
It is specially designed for XNU.

It is in the top ten result of Google search with the following keywords « dump process memory os x »

The source code is here

but from a strict point of virtual address space point de vue, you should be more interested with this question: OS X: Generate core dump without bringing down the process? (look also this)

When you look at gcore source code, it is quite complex to do this since you need to deal with treads and their state...

On most Linux distributions, the gcore program is now part of the GDB package. I think the OSX version is installed with xcode/the development tools.

UPDATE: wxHexEditor is an editor which can edit devices. IT CAN also edit process memory the same way it does for regular files. It work on all UNIX machines.

阿楠 2024-07-11 04:53:05

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

我没花很长时间就在这个 本书,其中包含当今所有 UNIX 通用的所有 API(比我想象的要多得多)。 将来你应该买它。 本书是一套(数百个)印刷版手册页,很少安装在现代机器上。
每个手册页都详细介绍了一个 C 函数。

没过多久我就找到了 shmat() shmctl(); 其中的 shmdt()shmget() 。 我没有广泛搜索,也许还有更多。

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

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

You want to do Inter-Process-Communication with the shared memory method. For a summary of other commons method, see here

It didn't take me long to find what you need in this book which contains all the APIs which are common to all UNIXes today (which many more than I thought). You should buy it in the future. This book is a set of (several hundred) printed man pages which are rarely installed on modern machines.
Each man page details a C function.

It didn't take me long to find shmat() shmctl(); shmdt() and shmget() in it. I didn't search extensively, maybe there's more.

It looked a bit outdated, but: YES, the base user-space API of modern UNIX OS back to the old 80's.

Update: most functions described in the book are part of the POSIX C headers, you don't need to install anything. There are few exceptions, like with "curses", the original library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文