Into /proc/PID/maps
I can see memory that some buffer mapped to kernel module:
44a00000-44b00000 rwxs 00000000 00:01 XXXX /dev/my_module
I know that it's logical address , and I want to dump this memory with dd
?
dd
need to get physical memory address , how can I calculate the physical address of this buffer to dump it?
There are multiple ways to obtain the memory information associated with a running process on Linux.
First, let's determine the process IDs of the running instance that we want to obtain information from. In this test I'm running a ping at google.com.
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
Second, use /proc/$pid/maps to find out more information about a process. /proc/$pid/maps provides a list of mappings of virtual addresses together with additional information, such as the corresponding file for mapped files.
# 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
Third, use /proc/$pid/pagemap to look at the memory. /proc/$pid/pagemap provides additional information about each mapped page, including the physical address, but only if it exists..
# 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 ................
Finally we want to use dd
Breakdown of the command:
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
Here is another dd command that will allow you to see the strings within the PID memory.
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 Project debugger
There are other ways to look at the memory of a running process. One way is to use a debugger like gdb. A debugger knows the structures used by a process and can follow pointers and other items.
You can dump your process to a file this way:
# http://www.yolinux.com/TUTORIALS/GDB-Commands.html
unknown@unknown-pi4:~$ sudo gdb --pid=3716
(gdb) gcore
(gdb) deatch
# to exit control z
The file will be stored as core.3716, which can be read with cat.
You can also use pmap to obtain information about a process.
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
On my Ubuntu system I had to temporarily disable a restriction to run a couple of commands that required ptrace.
filename:
/etc/sysctl.d/10-ptrace.conf
change this line:
kernel.yama.ptrace_scope = 1
to this:
kernel.yama.ptrace_scope = 0
You can also dump the memory with a script.
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
There are also various open source tools that you can use for memory forensics.
AVML (Acquire Volatile Memory for Linux): https://github.com/microsoft/avml
LiME ~ Linux Memory Extractor: https://github.com/504ensicsLabs/LiME
Volatility: https://github.com/volatilityfoundation/volatility
----------------------------------------
My system information
----------------------------------------
Platform: Ubuntu
OS Version: 20.10 (Groovy Gorilla)
----------------------------------------
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With