Linux:将被调试进程内存映射到调试器内存空间
实现方法
核心思路
/proc/<pid>/mem确实不支持mmap操作,因为procfs是虚拟文件系统,无法提供内存映射所需的物理页面对应关系。替代方案是:先创建本地匿名内存映射,再通过ptrace()将被调试进程的目标内存区域数据同步到这个映射区,后续直接读写本地映射即可,按需同步回被调试进程。
具体步骤
解析
/proc/<pid>/maps获取目标区域信息
读取该文件提取目标内存块的关键参数:起始虚拟地址、结束地址、权限。比如一条典型的映射条目:55f8d7a00000-55f8d7a22000 r--p 00000000 103:02 168933 /usr/bin/bash计算区域长度:
length = 结束地址 - 起始地址,记录起始地址target_addr。创建匹配权限的匿名映射
用mmap()创建与目标区域权限、大小一致的本地匿名映射:void *local_map = mmap(NULL, length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (local_map == MAP_FAILED) { perror("mmap failed"); exit(EXIT_FAILURE); }权限需和目标区域对应,比如目标是
rw-p就用PROT_READ | PROT_WRITE。通过
ptrace()同步远程内存到本地
用PTRACE_READV批量读取比逐个PTRACE_PEEKDATA效率更高。先构造iovec结构体分别指向本地映射和远程目标地址:struct iovec local_iov = {.iov_base = local_map, .iov_len = length}; struct iovec remote_iov = {.iov_base = (void *)target_addr, .iov_len = length}; // 确保被调试进程处于停止状态(比如已通过PTRACE_ATTACH附加) if (ptrace(PTRACE_READV, pid, &remote_iov, &local_iov) == -1) { perror("ptrace READV failed"); exit(EXIT_FAILURE); }直接读写本地映射区
现在可以像操作普通内存一样读写local_map,无需再调用系统访问被调试进程内存。(可选)同步本地修改回被调试进程
如果需要将修改内容写回,用PTRACE_WRITEV反向操作:if (ptrace(PTRACE_WRITEV, pid, &local_iov, &remote_iov) == -1) { perror("ptrace WRITEV failed"); exit(EXIT_FAILURE); }
注意事项
- 操作前需确保拥有足够权限(root或同UID),且被调试进程处于可ptrace的状态。
- 若目标内存区域动态变化(如被换出、权限变更),需重新执行同步步骤。
- 操作完成后可通过
PTRACE_DETACH解除对被调试进程的附加。
内容的提问来源于stack exchange,提问作者tuxifan
相关产品推荐
相关产品推荐

