使用 dd 转储映射缓冲区
dump mapped buffer with dd
进入/proc/PID/maps
我可以看到一些缓冲区映射到内核模块的内存:
44a00000-44b00000 rwxs 00000000 00:01 XXXX /dev/my_module
我知道它是逻辑地址,我想用 dd
?
转储这段内存
dd
需要获取物理内存地址,如何计算这个缓冲区的物理地址来转储它?
可以通过/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
给出了一条错误消息...... strace
表明搜索实际上成功了。
请注意,这不一定是一种非常有效的读取设备内存的方法。我将其发布为“技术演示”类的答案。在我看来,“技术上正确”的方法是自己为 mmap()
设备编写一个应用程序。
有多种方法可以获取与 Linux 上的 运行ning 进程关联的内存信息。
首先,让我们确定要从中获取信息的 运行ning 实例的 进程 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 从 FILE 而不是 stdin 读取
- skip=N 在输入开始时跳过 N 个 ibs 大小的块
- bs=BYTES 一次最多读写BYTES字节(默认:512);
覆盖 ibs 和 obs
- count=N只复制N个输入块
- od - 以八进制和其他格式转储文件
- -t, --format=TYPE select 输出格式或格式
- 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 项目调试器
还有其他方法可以查看 运行ning 进程的内存。一种方法是使用像 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//maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/ /p' \
| while read start stop; do \
gdb --batch --pid -ex \
"dump memory -$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
-
----------------------------------------
My system information
----------------------------------------
Platform: Ubuntu
OS Version: 20.10 (Groovy Gorilla)
----------------------------------------
进入/proc/PID/maps
我可以看到一些缓冲区映射到内核模块的内存:
44a00000-44b00000 rwxs 00000000 00:01 XXXX /dev/my_module
我知道它是逻辑地址,我想用 dd
?
dd
需要获取物理内存地址,如何计算这个缓冲区的物理地址来转储它?
可以通过/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
给出了一条错误消息...... strace
表明搜索实际上成功了。
请注意,这不一定是一种非常有效的读取设备内存的方法。我将其发布为“技术演示”类的答案。在我看来,“技术上正确”的方法是自己为 mmap()
设备编写一个应用程序。
有多种方法可以获取与 Linux 上的 运行ning 进程关联的内存信息。
首先,让我们确定要从中获取信息的 运行ning 实例的 进程 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 从 FILE 而不是 stdin 读取
- skip=N 在输入开始时跳过 N 个 ibs 大小的块
- bs=BYTES 一次最多读写BYTES字节(默认:512); 覆盖 ibs 和 obs
- count=N只复制N个输入块
- od - 以八进制和其他格式转储文件
- -t, --format=TYPE select 输出格式或格式
- 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 项目调试器
还有其他方法可以查看 运行ning 进程的内存。一种方法是使用像 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//maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/ /p' \
| while read start stop; do \
gdb --batch --pid -ex \
"dump memory -$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
----------------------------------------
My system information
----------------------------------------
Platform: Ubuntu
OS Version: 20.10 (Groovy Gorilla)
----------------------------------------