volatilityfoundation / volatility3

Volatility 3.0 development
http://volatilityfoundation.org/
Other
2.72k stars 461 forks source link

Linux Page Cache and IDR #1233

Closed gcmoreira closed 3 months ago

gcmoreira commented 3 months ago

This PR includes abstractions for RadixTree, XArray, Page Cache and IDR to ensure support with both older and the newest kernel versions. The RadixTree and XArray enable the implementation of other subsystems like the Page Cache and IDR.

This is the final iteration of other PRs which are part of this feature.

Besides the Page Cache plugins, we added two more plugins to this PR to be able to test the whole code with different kernel versions.

Inode Page Cache

linux.pagecache.Files plugin

This plugin can list all inodes, filter by type and find filenames. Basically, it shows superblock, dentry and inode info. It also supports the Timeliner plugin.

For instance, to list all inodes:

$ ./vol.py -f ./ubuntu-4.9.0-19-32bit.core linux.pagecache.Files 
Volatility 3 Framework 2.7.1
Progress:  100.00               Stacking attempts finished                  
SuperblockAddr  MountPoint      Device  InodeNum        InodeAddr       FileType        InodePages      CachedPages     FileMode        AccessTime      ModificationTime        ChangeTime      FilePath

0xf7094800      /       0:1     1       0xf4801e60      DIR     0       0       drwxr-xr-x      2024-07-29 13:44:58.916000 UTC  2024-07-29 13:44:58.916000 UTC  2024-07-29 13:44:58.916000 UTC  /
0xf7094800      /       0:1     7626    0xf4b2a5c0      DIR     0       0       drwx------      2022-06-30 18:26:10.000000 UTC  2022-06-30 18:26:10.000000 UTC  2024-07-29 13:44:58.228996 UTC  /root
0xf7154800      /sys    0:16    1       0xf4b492e0      DIR     0       0       dr-xr-xr-x      2024-07-29 13:44:58.500000 UTC  2024-07-29 13:44:58.500000 UTC  2024-07-29 13:44:58.500000 UTC  /sys
...

Filtering by file type. For instance, list the top Regular files with more pages in cache:

$ ./vol.py -f ./ubuntu-4.9.0-19-32bit.core linux.pagecache.Files --type REG | sort -k8 -n -r | head -10
0xf6845800      /run    0:18    9964    0xf6fd30b0      REG     647     647     -rw-r-----      2024-07-29 13:45:01.348000 UTC  2024-07-29 13:45:02.044000 UTC  2024-07-29 13:45:02.044000 UTC  /run/log/journal/791e6a5cbadf47da9808b2fdd26a7bf0/system.journal
0xf6f7b800      /       254:3   5506492 0xf46d5780      REG     549     474     -rwxr-xr-x      2024-07-29 13:00:30.392000 UTC  2020-06-20 17:33:46.000000 UTC  2024-01-07 10:46:57.080673 UTC  /usr/bin/perl
0xf6f7b800      /       254:3   2359824 0xf4536a08      REG     517     440     -rw-r--r--      2024-07-29 13:00:29.524000 UTC  2022-06-29 12:41:17.000000 UTC  2024-01-07 10:56:29.475108 UTC  /lib/systemd/libsystemd-shared-232.so
...

Find a specific file name:

$ ./vol.py -f ./ubuntu-4.9.0-19-32bit.core linux.pagecache.Files  --find /etc/shadow
Volatility 3 Framework 2.7.1
Progress:  100.00               Stacking attempts finished                  
SuperblockAddr  MountPoint      Device  InodeNum        InodeAddr       FileType        InodePages      CachedPages     FileMode        AccessTime      ModificationTime        ChangeTime      FilePath

0xf6f7b800      /       254:3   7078755 0xf46c83f8      REG     1       1       -rw-r-----      2024-07-29 13:00:30.552000 UTC  2024-01-07 11:19:42.597348 UTC  2024-01-07 11:19:42.597348 UTC  /etc/shadow

linux.pagecache.InodePages plugin

This plugin requires either an inode address (--inode) or a filename (--find) to search for the inode, and optionally, you can use (--dump) to dump the inode's page cache contents which is the primary and greatest goal of this effort.

Example 1, via inode address:

$ ./vol.py -f ./ubuntu-4.9.0-19-32bit.core linux.pagecache.InodePages --inode 0xf6fd30b0 --dump system.journal
Volatility 3 Framework 2.7.1
PageVAddr       PagePAddr       MappingAddr     Index   DumpSafe        Flags

0xf5e9be90      0x7bf84000      0xf6fd31a8      0       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
0xf5e9beb4      0x7bf85000      0xf6fd31a8      1       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
0xf5e9bed8      0x7bf86000      0xf6fd31a8      2       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
...
0xf5e8f944      0x7ba09000      0xf6fd31a8      646     True    dirty,lru,savepinned,swapbacked

Same inode but finding it via its filename:

$ ./vol.py -f ./ubuntu-4.9.0-19-32bit.core linux.pagecache.InodePages --find /run/log/journal/791e6a5cbadf47da9808b2fdd26a7bf0/system.journal --dump system.journal
Volatility 3 Framework 2.7.1
PageVAddr       PagePAddr       MappingAddr     Index   DumpSafe        Flags

0xf5e9be90      0x7bf84000      0xf6fd31a8      0       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
0xf5e9beb4      0x7bf85000      0xf6fd31a8      1       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
0xf5e9bed8      0x7bf86000      0xf6fd31a8      2       True    active,dirty,lru,referenced,savepinned,swapbacked,uptodate
...
0xf5e8f944      0x7ba09000      0xf6fd31a8      646     True    dirty,lru,savepinned,swapbacked

Checking the results:

$ file system.journal 
system.journal: Journal file, Mon Jul 29 13:44:59 2024, online, compressed lz4, header size 0xf0, entries 0x23f

$ journalctl --file=system.journal --list-boots
IDX BOOT ID                          FIRST ENTRY                  LAST ENTRY                  
  0 4f2a7426dab64f4dafa29343d13c1483 Mon 2024-07-29 23:44:59 AEST Mon 2024-07-29 23:45:01 AEST

$ journalctl --file=system.journal 
Jul 29 23:44:59 debian9.localdomain kernel: Linux version 4.9.0-19-686 (debian-kernel@lists.debian.org) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) ) #1 SMP Debian 4.9.320-2 (2022-06-30)
Jul 29 23:44:59 debian9.localdomain kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
Jul 29 23:44:59 debian9.localdomain kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
Jul 29 23:44:59 debian9.localdomain kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
...

Example 2:

$ ./vol.py ./ubuntu-4.9.0-19-686.core linux.pagecache.Files --find /etc/passwd
Volatility 3 Framework 2.7.1        
SuperblockAddr  MountPoint      Device  InodeNum        InodeAddr       FileType        InodePages      CachedPages     FileMode        AccessTime      ModificationTime        ChangeTime      FilePath

0xf6f7b800      /       254:3   7078938 0xf45116c0      REG     1       1       -rw-r--r--      2024-07-29 13:00:30.368000 UTC  2024-01-07 11:07:28.924695 UTC  2024-01-07 11:07:28.924695 UTC  /etc/passwd

Dump the inode:

$ ./vol.py -f ./ubuntu-4.9.0-19-686.core linux.pagecache.InodePages --find /etc/passwd --dump passwd
Volatility 3 Framework 2.7.1
PageVAddr       PagePAddr       MappingAddr     Index   DumpSafe        Flags

0xf5e87b68      0x7b68a000      0xf45117b8      0       True    active,lru,mappedtodisk,referenced,uptodate

Check the file:

$ cat passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologi
...

IDR

linux.ebpf.EBPF

A basic plugin to enumerate eBPF programs using the prog IDR. Tip for devs: Other contributions using the maps, links, etc. IDRs and even extending this plugin are welcome ;)

Test the plugin on a Cilium installation.

$ ./vol.py -f ./ram-5.8.0-53-ubuntu20.04-64bit.lime_cilium linux.ebpf.EBPF 
Volatility 3 Framework 2.8.0
Progress:  100.00               Stacking attempts finished                 
Address Name    Tag     Type

0xc9000002f000  -       3b185187f1855c4c        BPF_PROG_TYPE_XDP
0xc90000031000  BEGIN   f4b3d30cab782162        BPF_PROG_TYPE_KPROBE
0xc90000067000  sys_enter_execv e4476dee689a817e        BPF_PROG_TYPE_TRACEPOINT
0xc90000063000  -       3b185187f1855c4c        BPF_PROG_TYPE_XDP
0xc900005d5000  xdp_prog_simple 3b185187f1855c4c        BPF_PROG_TYPE_XDP
0xc90000141000  -       59904229c5a1f55d        BPF_PROG_TYPE_SCHED_CLS
0xc90000559000  -       6deef7357e7b4530        BPF_PROG_TYPE_CGROUP_SKB
0xc90000409000  -       6deef7357e7b4530        BPF_PROG_TYPE_CGROUP_SKB
0xc9000079d000  -       6deef7357e7b4530        BPF_PROG_TYPE_CGROUP_SKB
0xc9000079b000  -       6deef7357e7b4530        BPF_PROG_TYPE_CGROUP_SKB
...

linux.pidhashtable.PIDHashTable

This is based on the vol2 plugin, removing ancient kernel support, curating code and enhancing comments, while using the new IDR abstraction included also in this effort.

$ ./vol.py -f ./ram-5.8.0-53-ubuntu20.04-64bit.lime_cilium linux.pidhashtable.PIDHashTable --decorate-comm 
Volatility 3 Framework 2.8.0
Progress:  100.00               Stacking attempts finished                 
OFFSET  PID     TID     PPID    COMM

0x8881396117c0  1       1       0       systemd
0x888139615f00  2       2       0       [kthreadd]
0x888139614740  3       3       2       [rcu_gp]
0x888139610000  4       4       2       [rcu_par_gp]
0x8881396317c0  6       6       2       [kworker/0:0H]
0x888139630000  9       9       2       [mm_percpu_wq]
0x888139632f80  10      10      2       [ksoftirqd/0]
0x8881396397c0  11      11      2       [rcu_sched]
...
gcmoreira commented 3 months ago

Hey @ikelos, not sure why this cannot merge those changes. It looks pretty simple to me. Anyway, I'm not allowed to resolve those conflicts, it seems I will need your help here. Thanks

ikelos commented 3 months ago

Hey @ikelos, not sure why this cannot merge those changes. It looks pretty simple to me. Anyway, I'm not allowed to resolve those conflicts, it seems I will need your help here. Thanks

Yeah, that was a bit weird, they weren't really conflict from what I could see, but I guess some of the recent merges touched the files in those places. Anyway, should be all resolved, lemme know if there's an issue...

gcmoreira commented 3 months ago

@ikelos I changed the state to draft. It's almost ready but I want to add some testcases for completeness.

In the meantime, if you can please have a look at the LinuxUtilities version. I bumped the minor number when I added the ex choose_kernel_tree() helper, but, I later moved it to the IDStorage class. However, I made a code improvement, which could also be considered a patch, since the functionality itself hasn't changed. Not sure the exact criteria we should take into account for this. If we need to update the version again, the pidhashtable plugin requirements also needs to be adjusted.

ikelos commented 3 months ago

No problem moving this to draft. If the change you've made doesn't add to the LinuxUtilities interface (or remove/change it in any way) but just alters how it does the stuff it does (without changing the results) then it can just be bumped on the PATCH version rather than the MINOR version. Depends on the patch, but should be ok (otherwise we tend to leave the old functionality around with a deprecation warning, because bumping a MAJOR version on LinuxUtilities will be... painful. 5:P

gcmoreira commented 3 months ago

Hey @ikelos, IMO it's ready to merge. Again, my apologies. I know it's quite extensive chuck of code. I tried to break it down in some PRs, but I know I could have done it even better. I'll work on improving this for the next PR. On a positive note, I'm pretty sure our DFIR users will find these features very useful. Cheers

gcmoreira commented 3 months ago

@ikelos if you are happy with the last changes, it should be ready to go

gcmoreira commented 3 months ago

@ikelos I believe everything is done on my end. Please take a look when you have time. Cheers

ikelos commented 3 months ago

Yep, looks good, going to merge now, thanks for your patience getting it all sorted! 5:)

gcmoreira commented 3 months ago

Yep, looks good, going to merge now, thanks for your patience getting it all sorted! 5:)

Thank you, and again... very sorry for the long PR, I will submit smaller PRs next time. Very happy that Volatility3 now includes these features