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

Mac OS下读取Python进程内存触发Segmentation Fault问题求助

解决Mach VM API操作Python进程内存触发段错误的问题

问题根源

CPython的内存模型和普通C程序差异极大:

  • Python的str是封装后的PyUnicodeObject结构体,你打印的id()地址是结构体本身的指针,而非实际字符数据的起始地址,直接操作这个地址会破坏Python的内部管理结构。
  • Python有自己的内存池、引用计数机制,部分内存页有严格的权限保护,随意修改会触发内存错误。
  • 普通C程序的字符串是直接的栈/堆字符数组,而Python字符串的实际数据存储在结构体的特定字段或偏移位置,且受版本影响。

解决步骤

  • 准确定位字符数据的实际地址
    不要直接用Python输出的id(s)作为读写地址。需要根据对应CPython版本的PyUnicodeObject结构体定义,计算实际字符数据的偏移:

    • 对于3.9+的紧凑型Unicode字符串,实际UTF-8数据通常存在结构体的utf8字段中,或紧跟结构体末尾(需查阅对应版本的CPython源码确认偏移量)。
    • 例如,你可以先通过vm_read读取PyUnicodeObject的前几个字段,验证字符串长度、类型标识,再定位数据区域。
  • 正确处理内存权限
    Python进程的内存页可能是只读权限,操作前需临时调整权限,操作后恢复:

    1. 用vm_protect获取目标内存页的原权限。
    2. 将权限修改为VM_PROT_READ | VM_PROT_WRITE。
    3. 完成读写后,恢复原权限,避免破坏Python的内存安全机制。
  • 规避Python内部管理区域
    只针对字符串的实际字符数据区域操作,绝对不要修改PyUnicodeObject的管理字段(如引用计数、长度、类型指针),也不要触碰Python的内存池(arena)区域,这些操作会直接导致段错误。

  • 确保操作的稳定性
    操作前用task_suspend暂停Python进程,防止操作过程中Python触发GC或内存重分配导致地址失效;操作完成后用task_resume恢复进程。
    操作前先用vm_read验证目标地址的可读性,确认地址有效再执行写入。

示例伪代码

#include <mach/mach.h>
#include <stdio.h>
#include <string.h>

// 需根据目标CPython版本定义PyUnicodeObject的关键字段偏移
#define PY_UNICODE_UTF8_OFFSET 0x30 // 示例偏移,需实际核对对应版本

int main() {
    task_t target_task;
    mach_vm_address_t py_obj_addr = 0x100700000; // Python输出的id(s)地址
    mach_vm_address_t str_data_addr = py_obj_addr + PY_UNICODE_UTF8_OFFSET;
    char new_content[] = "modified_string";
    vm_prot_t old_prot, old_max_prot;

    // 假设已通过pid获取到target_task
    // 先保存原权限并调整为可读写
    vm_protect(target_task, str_data_addr, strlen(new_content), FALSE,
               VM_PROT_READ | VM_PROT_WRITE, &old_prot, &old_max_prot);
    
    // 写入新内容
    vm_write(target_task, str_data_addr, (vm_offset_t)new_content, strlen(new_content));
    
    // 恢复原权限
    vm_protect(target_task, str_data_addr, strlen(new_content), FALSE,
               old_prot, &old_prot, &old_max_prot);

    return 0;
}

关键注意事项

  • 不同CPython版本的PyUnicodeObject结构差异很大,必须针对目标版本查阅源码(如Include/cpython/unicodeobject.h)确认字段偏移。
  • 写入的内容长度不能超过原字符串的已分配长度,否则会覆盖相邻内存区域,触发段错误。
  • Bit-Slicer的核心逻辑就是自动解析Python的运行时结构、处理内存权限和进程暂停,你可以参考这类工具的实现思路来完善自己的代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:30:44