使用vm_read读取其他进程内存时触发MACH_SEND_INVALID_DEST错误
解决macOS进程内存读取时的MACH_SEND_INVALID_DEST错误
嘿,我一眼就看到你代码里的核心问题了——task_for_pid的用法完全错了,这直接导致了MACH_SEND_INVALID_DEST错误。咱们一步步把问题拆明白,再把代码修好:
问题出在哪?
先看task_for_pid的函数签名:
kern_return_t task_for_pid(mach_port_t target_task, pid_t pid, mach_port_t *task_port);
它的返回值是操作的状态码(比如KERN_SUCCESS表示成功),而目标进程的task端口是通过第三个指针参数输出的。但你把返回值直接赋值给了task变量,这就导致task存的根本不是有效的进程端口,后续调用vm_read自然会因为"目标无效"报错。
另外还有几个小细节需要调整:
vm_read的参数顺序写错了,读取大小和输出内存指针的位置搞反了- 读完内存后没释放
vm_read分配的缓冲区,会造成内存泄漏 - macOS的权限限制:普通用户调用
task_for_pid需要特殊权限,不然也会失败
修复后的完整代码
#include <stdio.h> #include <sys/types.h> #include <mach/mach.h> #include <mach/mach_vm.h> int main() { pid_t pid; printf("PID: "); scanf("%d", &pid); vm_address_t address; printf("Address (hex): "); scanf("%lx", &address); // 正确获取目标进程的task端口 mach_port_t target_task; kern_return_t ret = task_for_pid(mach_task_self(), pid, &target_task); if (ret != KERN_SUCCESS) { fprintf(stderr, "Failed to get task for PID %d, error: 0x%x\n", pid, ret); return 1; } vm_offset_t read_buffer; mach_msg_type_number_t read_size = sizeof(int); ret = vm_read(target_task, address, read_size, &read_buffer, &read_size); if (ret != KERN_SUCCESS) { fprintf(stderr, "Failed to read memory, error: 0x%x\n", ret); mach_port_deallocate(mach_task_self(), target_task); // 先释放task端口再退出 return 1; } // 把读取到的内存转成int类型输出 int *value = (int *)read_buffer; printf("Read value: %d\n", *value); // 清理资源:释放vm_read分配的内存和task端口 vm_deallocate(mach_task_self(), read_buffer, read_size); mach_port_deallocate(mach_task_self(), target_task); return 0; }
运行时的注意事项
- 权限问题:macOS的SIP(系统完整性保护)会限制普通用户调用
task_for_pid,你有两个解决办法:- 直接用
sudo运行编译后的程序,比如sudo ./memory_reader - 给二进制文件添加权限:先创建一个
entitlements.plist文件,内容如下:
然后执行签名命令:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.task.forge</key> <true/> </dict> </plist>sudo codesign --entitlements entitlements.plist -s - ./memory_reader
- 直接用
- 地址有效性:确保你输入的内存地址是目标进程中真实存在且可读的,不然会返回
KERN_INVALID_ADDRESS之类的错误。
内容的提问来源于stack exchange,提问作者lego man
相关产品推荐
相关产品推荐

