You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS下用Python读取外部程序内存地址值时崩溃,求解决方案

在MacOS上用Python读取其他进程内存的问题解决

原代码的直接错误

你写的代码里,x是字符串类型的地址,但ctypes.cast需要的是整数类型的内存地址,直接传字符串会导致类型错误,这是程序崩溃的原因之一。就算把x转成整数(比如int(x, 16)),程序还是会崩溃——因为MacOS的进程隔离机制不允许直接访问其他进程的内存地址。

MacOS的核心限制

MacOS采用严格的进程隔离:

  • 每个进程拥有独立的虚拟地址空间,你拿到的其他进程的内存地址,在当前Python进程的地址空间里是无效的,直接访问会触发段错误(程序崩溃)。
  • 系统默认开启ASLR(地址空间布局随机化),每次程序启动后,内存地址都会随机变化,静态的地址很快会失效。

正确的实现方式

要读取其他进程的内存,必须调用MacOS的内核级API(task_for_pid和vm_read),且需要root权限。以下是可行的代码示例:

import ctypes
import ctypes.util

# 加载系统库
libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
libmach = ctypes.CDLL(ctypes.util.find_library('mach'), use_errno=True)

# 定义Mach内核相关类型
mach_port_t = ctypes.c_uint32
vm_address_t = ctypes.c_uint64
vm_size_t = ctypes.c_uint64
kern_return_t = ctypes.c_int

# 声明系统函数的参数和返回值类型
libmach.task_for_pid.argtypes = [mach_port_t, ctypes.c_int, ctypes.POINTER(mach_port_t)]
libmach.task_for_pid.restype = kern_return_t

libmach.vm_read.argtypes = [mach_port_t, vm_address_t, vm_size_t, ctypes.POINTER(vm_address_t), ctypes.POINTER(vm_size_t)]
libmach.vm_read.restype = kern_return_t

libmach.vm_deallocate.argtypes = [mach_port_t, vm_address_t, vm_size_t]
libmach.vm_deallocate.restype = kern_return_t

def read_process_memory(pid, address, size):
    task = mach_port_t()
    # 获取目标进程的task端口(需要root权限)
    ret = libmach.task_for_pid(mach_port_t(0), pid, ctypes.byref(task))
    if ret != 0:
        raise OSError(f"获取进程端口失败,错误码: {ret}")
    
    data_ptr = vm_address_t()
    data_size = vm_size_t()
    # 读取指定地址的内存
    ret = libmach.vm_read(task, vm_address_t(address), vm_size_t(size), ctypes.byref(data_ptr), ctypes.byref(data_size))
    if ret != 0:
        raise OSError(f"读取内存失败,错误码: {ret}")
    
    # 将内存数据转为Python字节串
    data = ctypes.string_at(data_ptr, data_size)
    
    # 释放内核分配的内存缓冲区
    libmach.vm_deallocate(task, data_ptr, data_size)
    
    return data

# 使用示例:替换为你的目标进程PID和内存地址
try:
    target_pid = 1234  # 目标进程的PID,可通过ps命令获取
    target_address = 0x7FA09AAE85A0  # 要读取的内存地址(整数形式)
    read_size = 16  # 要读取的字节数
    memory_content = read_process_memory(target_pid, target_address, read_size)
    print(f"读取到的内存数据(十六进制): {memory_content.hex()}")
except OSError as e:
    print(f"操作失败: {e}")

注意事项

  1. 必须以root权限运行:执行命令时加上sudo,比如sudo python3 your_script.py,否则task_for_pid会权限不足。
  2. SIP限制:如果系统开启了系统完整性保护(SIP),无法读取系统进程(如Finder、Safari)的内存,需要临时关闭SIP才能操作。
  3. 地址有效性:确保目标地址是目标进程当前有效的虚拟地址,ASLR会导致地址随机变化,通常需要通过逆向工具找到基地址+偏移来计算有效地址。
  4. 内存大小:读取的内存大小不能超出目标地址的有效范围,否则vm_read会失败。

内容的提问来源于stack exchange,提问作者octopuswindow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:30:55