Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux: add sanity check in find_aslr #1070

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

vobst
Copy link

@vobst vobst commented Dec 20, 2023

Describe the bug
We encountered a situation where Volatility would wrongly assume that a memory image had a virtual ASLR of zero because the first matching init_task was in a fragment of the .data section of the kernel ELF file in the page cache, instead of the one in the running kernel's .data section. The kernel ELF file was opened prior to acquisition and thus fragments of it were scattered in physical memory.

The kernel ELF file's .data section contains the init_task's task_struct with values for the files, thread_pid, fs, ... members initialized to the non-randomized addresses that are also found in the system map.

$ objcopy --dump-section .data=/tmp/linux.data bpfvol3-roboxes-centos9s-vmlinux_extracted-8b0ac.elf
$ readelf --symbols bpfvol3-roboxes-centos9s-vmlinux_extracted-8b0ac.elf | rg init_files
189146: ffffffff83084800   704 OBJECT  GLOBAL DEFAULT   28 init_files
$ rg 'init_files' bpfvol3-roboxes-centos9s-vmlinux_extracted-8b0ac.map
171871:ffffffff83084800 D init_files
$ xxd /tmp/linux.data | rg swapper -C 30 | rg 0048
0001b650: 20d2 0883 ffff ffff 0048 0883 ffff ffff   ........H......

Volatility currently picks the first valid-looking init_task it finds in the image and thus if such a fragment of the data section precedes the real init_task a virtual ASLR of zero is determined by the following code:

            aslr_shift = (
                init_task.files.cast("long unsigned int")
                - module.get_symbol("init_files").address
            )

To identify such "phony" matches I'd propose two heuristics:

  1. "match is phony" <=> .active_mm == init_mm where the address of init_mm is taken from the system map/json symbols. This works because kernel threads, i.e. tasks with .mm=NULL, "steal" the active_mm of the previous task when they are scheduled to run on a CPU. Thus, as long as some CPU on the system has been idle at least once the active_mm of the real init_task will be unequal to init_mm, even on systems that really had no ASLR. (Theoretically it would be possible to construct an edge case where this is wrong, but it is incredibly unlikely ^^)
  2. There are multiple doubly-linked lists in the init_task's task_struct that are statically initialized to be empty. Thus, a possible heuristic based on this would be: "match is phony" <=> .tasks.next == .tasks.prev, which should never be the case for the real init_task.

I personally prefer the latter option due to its simplicity (just tell me if you think so too and I'll happily remove the other one from the PR).

Context
Volatility Version: a4b927f

To Reproduce
In case you are interested I uploaded some dump+symbol that exhibits this behavior. Download

Process listing plugins will show no output (empty task list), other plugins like kmsg will list dereference invalid pointers and crash.

@vobst vobst force-pushed the add-sanity-check-find_aslr-linux branch from 662f023 to 844254d Compare December 20, 2023 17:47
@ikelos ikelos requested a review from atcuno December 20, 2023 19:30
@vobst vobst force-pushed the add-sanity-check-find_aslr-linux branch from 844254d to 8440184 Compare December 20, 2023 20:51
@vobst vobst changed the title Add sanity check in find_aslr for Linux Linux: add sanity check in find_aslr Dec 20, 2023
@ikelos
Copy link
Member

ikelos commented Feb 1, 2024

@atcuno could you give this a look over please, it's very short but I just can't tell if the technique it's using is valid or if there'll be corner cases that might go wrong...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants