使用dd转储映射的缓冲区



进入/proc/PID/maps,我可以看到一些缓冲区映射到内核模块的内存:

44a00000-44b00000 rwxs 00000000 00:01 XXXX /dev/my_module

我知道它是逻辑地址,我想用dd转储这个内存?

dd需要获取物理内存地址,如何计算这个缓冲区的物理地址来转储它?

有多种方法可以获得与Linux上运行的进程相关的内存信息。

首先,让我们确定要从中获取信息的运行实例的进程ID。在这个测试中,我在google.com上运行ping。

unknown@unknown-pi4:~$  sudo ps aux | grep ping
unkno+    1402  0.0  0.1 311860  6376 ?        Ssl  15:31   0:01 /usr/libexec/gsd-housekeeping
unknon+    3716  0.0  0.0   9952  2108 pts/0    T    18:11   0:00 ping www.google.com
unknow+    4152  0.1  0.0   9952  2108 pts/0    S+   20:07   0:00 ping www.google.com
unknow+    4176  0.0  0.0   8604   824 pts/1    S+   20:12   0:00 grep --color=auto ping

其次,使用/proc/$pid/maps查找有关进程的更多信息/proc/$pid/maps提供了一个虚拟地址映射列表以及附加信息,例如映射文件的对应文件

# https://man7.org/linux/man-pages/man5/proc.5.html
sudo head -1 /proc/3716/maps
aaaab61cf000-aaaab61df000 r-xp 00000000 b3:02 3748                       /usr/bin/ping

第三,使用/proc/$pid/pagemap查看内存/proc/$pid/pagemap提供了关于每个映射页面的附加信息,包括物理地址,但前提是它存在

# https://man7.org/linux/man-pages/man5/proc.5.html
# https://linux.die.net/man/1/xxd
sudo cat /proc/3716/pagemap | xxd | less
00000220: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000230: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000240: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000250: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000260: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000270: 0000 0000 0000 0000 0000 0000 0000 0000  ................

最后我们要使用dd

  • dd-转换并复制文件
  • https://man7.org/linux/man-pages/man1/dd.1.html

命令分解:

  • sudo=请求使用dd的权限
  • if=从FILE而不是stdin读取FILE
  • skip=N输入开始时跳过N个ibs大小的块
  • bs=BYTES一次读取和写入最多BYTES字节(默认值:512(;覆盖ibs和obs
  • count=N只复制N个输入块
  • od-以八进制和其他格式转储文件
  • -t、 --format=TYPE选择输出格式
  • x[SIZE]十六进制,SIZE字节/整数
  • 命名字符,忽略高阶位
unknown@unknown-pi4:/tmp$ sudo dd if=/proc/3716/mem skip=$((0xaaaab61cf000))  bs=1 count=128 | od -t x1a
dd: /proc/3716/mem: cannot skip to specified offset
0000000  7f  45  4c  46  02  01  01  00  00  00  00  00  00  00  00  00
del   E   L   F stx soh soh nul nul nul nul nul nul nul nul nul
0000020  03  00  b7  00  01  00  00  00  e0  32  00  00  00  00  00  00
etx nul   7 nul soh nul nul nul   `   2 nul nul nul nul nul nul
0000040  40  00  00  00  00  00  00  00  18  04  01  00  00  00  00  00
@ nul nul nul nul nul nul nul can eot soh nul nul nul nul nul
0000060  00  00  00  00  40  00  38  00  09  00  40  00  1a  00  19  00
nul nul nul nul   @ nul   8 nul  ht nul   @ nul sub nul  em nul
0000100  06  00  00  00  04  00  00  00  40  00  00  00  00  00  00  00
ack nul nul nul eot nul nul nul   @ nul nul nul nul nul nul nul
0000120  40  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
@ nul nul nul nul nul nul nul   @ nul nul nul nul nul nul nul
0000140  f8  01  00  00  00  00  00  00  f8  01  00  00  00  00  00  00
x soh nul nul nul nul nul nul   x soh nul nul nul nul nul nul
0000160  08  00  00  00  00  00  00  00  03  00  00  00  04  00  00  00
128+0 records in
128+0 records out
bs nul nul nul nul nul nul nul etx nul nul nul eot nul nul nul
128 bytes copied, 0.0019137 s, 66.9 kB/s
0000200

这是另一个dd命令,它将允许您查看PID内存中的字符串

unknown@unknown-pi4:~$ sudo grep heap /proc/3716/maps
aaaad44ed000-aaaad450e000 rw-p 00000000 00:00 0                          [heap]
# note where I place the mapping addresses in this command.
unknown@unknown-pi4:~$ sudo dd if=/proc/3716/mem bs=1 skip=$((0xaaaad44ed000)) count=$((0xaaaad450e000-0xaaaad44ed000)) status=none | strings | less

GDB-GNU项目调试器

还有其他方法可以查看正在运行的进程的内存。一种方法是使用像gdb这样的调试器。调试器知道进程使用的结构,并且可以跟踪指针和其他项。

您可以通过以下方式将流程转储到文件中:

# http://www.yolinux.com/TUTORIALS/GDB-Commands.html
unknown@unknown-pi4:~$ sudo gdb --pid=3716
(gdb) gcore
(gdb) deatch 
# to exit control z

该文件将存储为core.3716,可以使用cat读取。


您也可以使用pmap来获取有关流程的信息。

  • pmap-报告进程的内存映射
  • https://man7.org/linux/man-pages/man1/pmap.1.html
unknown@unknown-pi4:/tmp$ pmap -XX 1402 | grep ping
1402:   /usr/libexec/gsd-housekeeping
Address Perm   Offset Device  Inode   Size KernelPageSize MMUPageSize  Rss  Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible              VmFlags Mapping
aaaabe75b000 r-xp 00000000  b3:02  31059     40              4           4   20   20            0            0            20             0         20         0        0             0              0             0              0               0    0       0      0           0    rd ex mr mw me dw gsd-housekeeping
aaaabe775000 r--p 0000a000  b3:02  31059      4              4           4    4    4            0            0             0             4          4         4        0             0              0             0              0               0    0       0      0           0    rd mr mw me dw ac gsd-housekeeping
aaaabe776000 rw-p 0000b000  b3:02  31059      4              4           4    4    4            0            0             0             4          4         4        0             0              0             0              0               0    0       0      0           0 rd wr mr mw me dw ac gsd-housekeeping

在我的Ubuntu系统上,我不得不暂时禁用一个限制来运行几个需要ptrace的命令。

文件名:

/etc/sysctl.d/10-ptrace.conf

更改此行:

kernel.yama.ptrace_scope = 1

到此:

kernel.yama.ptrace_scope = 0


您也可以使用脚本转储内存。

touch dump_process_memory

chmod +x dump_process_memory.sh

#!/bin/bash
grep rw-p /proc/$1/maps 
| sed -n 's/^([0-9a-f]*)-([0-9a-f]*) .*$/1 2/p' 
| while read start stop; do 
gdb --batch --pid $1 -ex 
"dump memory $1-$start-$stop.dump 0x$start 0x$stop"; 
done

sudo ./dump_process_memory.sh PID


还有各种开源工具可以用于内存取证

  • AVML(获取Linux的易失性内存(:https://github.com/microsoft/avml

  • LiME~Linux内存提取器:https://github.com/504ensicsLabs/LiME

  • 波动性:https://github.com/volatilityfoundation/volatility

----------------------------------------
My system information
----------------------------------------
Platform:     Ubuntu
OS Version:   20.10 (Groovy Gorilla)
----------------------------------------

可以通过/proc/PID/mem执行此操作;示例:

$ sudo  head -1 /proc/1/maps
564c14022000-564c14054000 r--p 00000000 fd:00 8786642 /usr/lib/systemd/systemd
$ sudo dd if=/proc/1/mem skip=$((0x564c14022000))  bs=1 count=128 | od -t x1a
dd: /proc/1/mem: cannot skip to specified offset
0000000  7f  45  4c  46  02  01  01  00  00  00  00  00  00  00  00  00
del   E   L   F stx soh soh nul nul nul nul nul nul nul nul nul
0000020  03  00  3e  00  01  00  00  00  50  da  03  00  00  00  00  00
etx nul   > nul soh nul nul nul   P   Z etx nul nul nul nul nul
0000040  40  00  00  00  00  00  00  00  80  b1  18  00  00  00  00  00
@ nul nul nul nul nul nul nul nul   1 can nul nul nul nul nul
0000060  00  00  00  00  40  00  38  00  0d  00  40  00  1e  00  1d  00
nul nul nul nul   @ nul   8 nul  cr nul   @ nul  rs nul  gs nul
0000100  06  00  00  00  04  00  00  00  40  00  00  00  00  00  00  00
ack nul nul nul eot nul nul nul   @ nul nul nul nul nul nul nul
0000120  40  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
@ nul nul nul nul nul nul nul   @ nul nul nul nul nul nul nul
0000140  d8  02  00  00  00  00  00  00  d8  02  00  00  00  00  00  00
X stx nul nul nul nul nul nul   X stx nul nul nul nul nul nul
0000160  08  00  00  00  00  00  00  00  03  00  00  00  04  00  00  00
128+0 records in
128+0 records out
bs nul nul nul nul nul nul nul etx nul nul nul eot nul nul nul
128 bytes copied, 0.000257009 s, 498 kB/s
0000200

这应该适用于任何映射,但必须具有CAP_PTRACE权限,因此我使用了sudo。shell(至少bash(将通过$(( .. ))将十六进制转换为十进制(算术表达式很乐意处理十六进制数字(。当dd给出错误消息时。。。CCD_ 16表明搜索实际上成功了。

请注意,这不一定是一种非常有效的读取设备内存的方式。我将此作为";技术演示";这样的回答。在我看来;技术上正确";方法是自己编写一个应用程序到mmap()设备。

最新更新