标题: *nix环境用户态memdump的几种方案 创建: 2018-11-27 12:08 更新: 2023-07-27 09:37 链接: https://scz.617.cn/unix/201811271208.txt 在*nix环境用户态对任意进程进行memdump,普适方案是: cat /proc/[pid]/maps pmap -px gcore gdb dump memory info auxv info files info proc stat info sharedlibrary info proc mappings 从程序员角度看,有这么几种方案: -------------------------------------------------------------------------- a) PTRACE_ATTACH waitpid PTRACE_PEEKTEXT/PTRACE_PEEKDATA write( fd_out ) PTRACE_DETACH 这可能是最古老的方案,效率最差,但兼容性最好。 waitpid确保目标进程STOP。在PTRACE_DETACH之前不需要显式PTRACE_CONT, PTRACE_DETACH之后目标进程会自动CONT。 -------------------------------------------------------------------------- b) PTRACE_ATTACH waitpid open( /proc/[pid]/mem ) lseek read write( fd_out ) close PTRACE_DETACH 为了打开/proc/[pid]/mem,需要PTRACE_ATTACH,仅仅"kill -SIGSTOP"是不够的。 lseek需要处理"32-bits程序访问文件0x80000000及以上偏移"的问题。 /proc/[pid]/mem只支持read,不支持mmap,后者会返回ENODEV。 -------------------------------------------------------------------------- c) PTRACE_ATTACH waitpid open( /proc/[pid]/mem ) pread write( fd_out ) close PTRACE_DETACH pread代替了lseek+read。在多线程编程中建议使用pread/pwrite,它们不会改变 read/write用到的文件I/O偏移。 -------------------------------------------------------------------------- d) process_vm_readv write( fd_out ) 自从Linux 3.2 (2012.1)及glibc 2.15 (2012.3)始,可以使用上述API,此时不需要 事先PTRACE_ATTACH,也不要求目标进程STOP。有点类似Windows上的 ReadProcessMemory/WriteProcessMemory。 这个办法需要注意内核版本是否适用。 -------------------------------------------------------------------------- 不管用哪种办法,都只需要gcc,不需要复杂的SDK之流。Android就当它是Linux,当 你看到某个Android上的memdump.c需要NDK才能编译,纯属扯淡。 参看proc(5) -------------------------------------------------------------------------- /proc/[pid]/mem This file can be used to access the pages of a process's memory through open(2), read(2), and lseek(2). Permission to access this file is governed by a ptrace access mode PTRACE_MODE_ATTACH_FSCREDS check; see ptrace(2). /proc/[pid]/maps address perms offset dev inode pathname A file containing the currently mapped memory regions and their access permissions. See mmap(2) for some further information about memory mappings. Permission to access this file is governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see ptrace(2). The address field is the address space in the process that the mapping occupies. The perms field is a set of permissions: r = read w = write x = execute s = shared p = private (copy on write) The offset field is the offset into the file/whatever; dev is the device (major:minor); inode is the inode on that device. 0 indicates that no inode is associated with the memory region, as would be the case with BSS (uninitialized data). The pathname field will usually be the file that is backing the mapping. For ELF files, you can easily coordinate with the offset field by looking at the Offset field in the ELF program headers (readelf -l). There are additional helpful pseudo-paths: [stack] The initial process's (also known as the main thread's) stack. [stack:] (since Linux 3.4) A thread's stack (where the is a thread ID). It corresponds to the /proc/[pid]/task/[tid]/ path. [vdso] The virtual dynamically linked shared object. See vdso(7). [heap] The process's heap. If the pathname field is blank, this is an anonymous mapping as obtained via mmap(2). There is no easy way to coordinate this back to a process's source, short of running it through gdb(1), strace(1), or similar. -------------------------------------------------------------------------- 参看 How do I read from /proc/$pid/mem under Linux - [2011-01-22] https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux 这篇于2019、2020年有更新。mem文件偏移完全对应进程空间地址,可以对照maps文 件进行mem文件读取。从kernel 3.3开始,不再需要PTRACE_ATTACH即可读取mem,于 是dd、xxd等工具可直接转储、查看目标进程空间。 ProcDump for Linux https://github.com/Sysinternals/ProcDump-for-Linux