Skip to content

[2024] AArch64 support - #1088

Draft
Abyss-W4tcher wants to merge 91 commits into
volatilityfoundation:developfrom
Abyss-W4tcher:aarch64-support
Draft

Abyss-W4tcher wants to merge 91 commits into
volatilityfoundation:developfrom
Abyss-W4tcher:aarch64-support

Conversation

@Abyss-W4tcher

@Abyss-W4tcher Abyss-W4tcher commented Jan 20, 2024 •

Copy link
Copy Markdown
Contributor

Hi 👋,

This PR provides AArch64 integration to the Volatility3 framework, as well as a design rework in the current linux stacker.

Implementation follows ARM official documentation, and includes essential APIs for higher level code (plugins etc.).

You can follow the roadmap here :


My ressources :


Testing :

  • RaspberryPi (virtual) : Linux version 6.1.21
  • Android AVD (virtual) : Linux version 3.18.94
  • RaspberryPi (physical) : Linux version 6.1.0-rpi8-rpi-v8
  • Google Pixel 6A (physical) : Linux version 5.10.157-android13-4-00003-g830b023b88f3-dirty
  • Jetson lime (physical) : Linux version 4.9.201-tegra
  • NXP LX2160 (physical) : Linux version 6.1.36

Thanks to everyone who took the time to test this PR on their devices !


Unstable plugins :

  • linux.bash :
    • sections have no size on Android related samples.
    • 12/04/24 update : Android does not ship with bash by default, as it's not GNU/Linux running on the system . Either we need a dedicated plugin (.ash_history ?), or a check to tell users why the plugin isn't working.
  • linux.lsof :
    • dentry members can be NULL, and this behaviour isn't handled (more informations in the dedicated Slack thread)

Please note that this is still experimental, testing is still going on. If you want to try this PR out, here are the steps :

  • Merge/checkout the PR into your local Volatility3 copy (git checkout aarch64-support)
  • Make a memory capture of your AArch64 device (see attached ressources)
  • Create the ISF against the vmlinux file with dwarf2json
  • Set the following on top of the plugins you plan to use :
requirements.ModuleRequirement(
      name="kernel",
      description="Linux kernel",
      architectures=["Intel32", "Intel64", "AArch64"],
)

If you have any real-life samples to provide, or if you encounter any error, feel free to comment below !

Comment thread volatility3/framework/automagic/linux.py Fixed
Comment thread volatility3/framework/automagic/linux.py Fixed
Comment thread volatility3/framework/automagic/linux.py Fixed
Comment thread volatility3/framework/automagic/linux.py Fixed

@ikelos ikelos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for this, it looks awesome! I haven't been through it all, I've most concentrated on the arm layer at the moment (and I haven't made my way through all of that). The comments pointing to the location of useful documentation is massively useful and very much appreciated! 5:D There's a few little bits that can be cleaned up but on the whole it looks perfectly in line with the rest of volatility, so good work! It'll take me a while to find time to go through more of it, and check the various references to fully get what's going on.

I'm trying to figure out the split between mapping and _mapping, it looks like _mapping returns every chunk, and mapping coalesces them together is that about right? I think that's probably for the best, but it feels like it makes for bulky code somehow. Really excited to see where this codes (and find some Windows-on-arm samples to try it against too!). 5:D

Comment thread volatility3/framework/automagic/linux.py Outdated
)
self._base_layer = self.config["memory_layer"]
# self._swap_layers = [] # TODO
self._page_map_offset = self.config["page_map_offset"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two pages maps as part of AArch64, aren't there? Which one should people provide here? Might be better to use the terminology used by the architecture here, rather than reusing values used elsewhere...

@Abyss-W4tcher Abyss-W4tcher Jan 21, 2024 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Linux Stacker, we are instantiating the kernel Layer. We pass the kernel DTB (Translation Table Base 1 Base Address) to the AArch64 layer. There is in fact a unique page map for the whole kernel, stored in ARM register TTBR1, and a page map for the user land stored in TTBR0. TTBR0 is not constant, and changes on every process context switch. What this means, is that TTBR0 is changed to the value of the current process DTB (which happens continuously).

For me, there are only two possible callers to this layer :

  • LinuxStacker (kernel, only once)
  • "Processes"

People should not have to instantiate the kernel layer twice, but only user space layers (programs) ? In another comment I detailed how I implemented a check to facilitate this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so... it looks like we've got the page_map_offet (for non kernel spaces) and then a separate option requirement that contains the register pointing to the kernel layer's page table structure? That's reasonably elegant, and I guess for the kernel space you could use the same value for both the page_table and the TTBR1. Still trying to think through the ramifications, but so far it seems ok.

I'm wondering why you picked page_map_offset for the config option, rather than TTBR0 or something for clarity? If it's something that's expected in other places in the code, then I might want to review those places, because I don't think layer are allowed to depend on requirements of a generic layer (and if we want to have that value exposed in all layers, which doesn't make sense because not every layer has a page table) then it should be done with an interface that exposes a read-only property and have that applied to both intel and arm.

I understand we're treating them as two different layers, but I can't tell whether conceptually that makes sense. On the one hand, both registers can change indepdendently of each other (in theory). On the other hand, a process label object may well want to read data from the kernel layer, presumably?

Comment thread volatility3/framework/layers/arm.py Outdated
# self._swap_layers = [] # TODO
self._page_map_offset = self.config["page_map_offset"]
self._tcr_el1_tnsz = self.config["tcr_el1_tnsz"]
self._page_size = self.config["page_size"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this part of the architecture, or is it dynamic, or is it something pre-defined?

@Abyss-W4tcher Abyss-W4tcher Jan 21, 2024 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • _page_map_offset is the DTB (either kernel or specific to a process). For the kernel, it can be calculated thanks to the existing Intel implementation. For the process, I don't know exactly where, but it is stored in the task_struct directly if I'm not mistaken.
  • _tcr_el1_tnsz : The size offset of the memory region addressed by TTBR1_EL1. The region size is 2(64-T1SZ) bytes -> See page 7081 of the doc. It is defined in the kernel config, but we cannot predict it (it is calculated in LinuxStacker).
  • _page_size : Page size (4, 16 or 64 KB), also defined in the kernel config, but we cannot predict it (it is calculated in LinuxStacker).

Comment thread volatility3/framework/layers/arm.py Outdated
self._tcr_el1_tnsz = self.config["tcr_el1_tnsz"]
self._page_size = self.config["page_size"]

# Context : TTB0 (user) or TTB1 (kernel)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this layer will only cope with one of user or kernel? That might be complex to handle in the future?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This layer needs to be instantiated one time for the kernel, and as many times as there are processes. End users should not have to instantiate the kernel layer twice, and instantiating a process layer is basically the same as the Intel logic (I think mostly of malfind, which I used to validate the processes layers translations).

Comment thread volatility3/framework/layers/arm.py Outdated
Comment thread volatility3/framework/layers/arm.py Outdated
Comment thread volatility3/framework/layers/arm.py Outdated
Comment thread volatility3/framework/layers/arm.py Outdated
),
requirements.IntRequirement(name="page_map_offset", optional=False),
requirements.IntRequirement(name="page_map_offset_kernel", optional=False),
requirements.IntRequirement(name="tcr_el1_tnsz", optional=False),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually provide a description field with requirements, which might be quite handy here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, I will take a look !

Comment thread volatility3/framework/layers/arm.py Outdated
Comment thread volatility3/framework/layers/arm.py Outdated
@Abyss-W4tcher

Copy link
Copy Markdown
Contributor Author

Hi @ikelos, thanks for your quick replies !

I will check every of your comment right now, as I have some spare time. Regarding your general concern regarding mapping, it is more or less the exact Intel implementation from https://github.com/volatilityfoundation/volatility3/blob/develop/volatility3/framework/layers/intel.py#L271. It worked well out of the box for this layer :).

@ikelos

ikelos commented Jan 21, 2024

Copy link
Copy Markdown
Member

Hehehe, yeah, I figured it might be. That's not too sweet the intel layer isn't overly complicated but it's fine for now. If you find any ways of simplifying it we can back port then to intel too... 5;D

@Abyss-W4tcher

Abyss-W4tcher commented Jan 22, 2024 •

Copy link
Copy Markdown
Contributor Author

Here is what a typical layer instantiation debug looks like :

Kernel layer instantiated by LinuxStacker and a higher stacker :

DEBUG    volatility3.framework.automagic.linux: Linux ASLR shift values determined: physical -ffffffbfc7e00000 virtual 172a600000
DEBUG    volatility3.framework.layers.arm: Base layer : Elf64Layer
DEBUG    volatility3.framework.layers.arm: Virtual address space : kernel
DEBUG    volatility3.framework.layers.arm: Virtual addresses space range : ('0xffffffc000000000', '0xffffffffffffffff')
DEBUG    volatility3.framework.layers.arm: Page size : 4
DEBUG    volatility3.framework.layers.arm: T1SZ : 25
DEBUG    volatility3.framework.layers.arm: Page map offset : 0x41963000
DEBUG    volatility3.framework.layers.arm: Translation mappings : [(38, 30), (29, 21), (20, 12)]
DEBUG    volatility3.framework.automagic.linux: Kernel DTB was found at: 0x41963000
DEBUG    volatility3.framework.automagic.linux: AArch64 image found
DEBUG    volatility3.framework.layers.arm: Base layer : memory_layer
DEBUG    volatility3.framework.layers.arm: Virtual address space : kernel
DEBUG    volatility3.framework.layers.arm: Virtual addresses space range : ('0xffffffc000000000', '0xffffffffffffffff')
DEBUG    volatility3.framework.layers.arm: Page size : 4
DEBUG    volatility3.framework.layers.arm: T1SZ : 25
DEBUG    volatility3.framework.layers.arm: Page map offset : 0x41963000
DEBUG    volatility3.framework.layers.arm: Translation mappings : [(38, 30), (29, 21), (20, 12)]

Processes layers instantiated by malfind :

DEBUG    volatility3.framework.layers.arm: Base layer : memory_layer
DEBUG    volatility3.framework.layers.arm: Virtual address space : user
DEBUG    volatility3.framework.layers.arm: Virtual addresses space range : ('0x0', '0x3fffffffff')
DEBUG    volatility3.framework.layers.arm: Page size : 4
DEBUG    volatility3.framework.layers.arm: T0SZ : 25
DEBUG    volatility3.framework.layers.arm: Page map offset : 0x47266000
DEBUG    volatility3.framework.layers.arm: Translation mappings : [(38, 30), (29, 21), (20, 12)]

DEBUG    volatility3.framework.layers.arm: Base layer : memory_layer
DEBUG    volatility3.framework.layers.arm: Virtual address space : user
DEBUG    volatility3.framework.layers.arm: Virtual addresses space range : ('0x0', '0x3fffffffff')
DEBUG    volatility3.framework.layers.arm: Page size : 4
DEBUG    volatility3.framework.layers.arm: T0SZ : 25
DEBUG    volatility3.framework.layers.arm: Page map offset : 0x47928000
DEBUG    volatility3.framework.layers.arm: Translation mappings : [(38, 30), (29, 21), (20, 12)]

Check out memory samples here [7 days] :

Comment thread volatility3/framework/layers/arm.py Outdated
join = interfaces.configuration.path_join

# Never stack on top of an intel layer
# Never stack on top of a linux layer

@Abyss-W4tcher Abyss-W4tcher Jan 30, 2024 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To improve this, why not add an explicit layer property, like _is_top_layer inside volatility3/framework/layers/intel.py#Intel and volatility3/framework/layers/arm.py#AArch64 and check with following :

        if getattr(layer, "_is_top_layer") and layer._is_top_layer:
            return None

If we keep the current implementation, we have to change the Linux, Windows and Mac stacker for each new architecture layer.

@ikelos ikelos Jan 30, 2024 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the reason is virtualization, it's possible to have an arm layer inside an intel layer (and it's certainly possible to have an intel layer on top an intel layer). You're right, it's not really a scalable solution (hence the FIXME right beneath this line), but it's also not a trivial attribute...

@Abyss-W4tcher Abyss-W4tcher Jan 30, 2024 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which stacker is supposed to do this (LinuxStacker, WindowsIntelStacker and MacIntelStacker blocks it), for example if a VM managed by qemu-system-aarch64 on an Intel host was running when the memory was dumped ?

Will a "VM (qemu) layer" be available from the globals context.layers variable too :

  • FileLayer
    • LimeLayer
      • IntelLayer
        • Memory Layer
        • QemuLayer (not sure about this one)
          • IntelLayer
            • Memory Layer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is anything automatic in core that would do that, but it would be nice to have.

There has been this issue from a while ago that talks about that kind of thing.
#464

@Abyss-W4tcher Abyss-W4tcher Jan 30, 2024 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing it out :) So in the current state, as it is not implemented, we will continue to strictly refuse stacking on top of Linux and AArch64. Adding an explicit flag on those two might be a temporary and more scalable solution ?

I leave this as a side note, for a potentiel reader in the future interested in AArch64 hypervisor execution mode (and what it might imply, if treating a layer from the hypervisor point of view) : https://developer.arm.com/documentation/102412/0103/Privilege-and-Exception-levels/Exception-levels

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have a vmscan plugin, and in the future will likely generate a config file that will allow virtual machine guests to have volatility plugins run on them. This likely either by Intel on Intel, or IntelVM (doesn't exist yet) on Intel. The point is, it is a capability we'd like to leave open for the future, so planning for it now is useful.

Comment thread volatility3/framework/automagic/linux.py Fixed
Comment thread volatility3/framework/automagic/linux.py Fixed
)
layer.config["kernel_virtual_offset"] = aslr_shift
linux_arch_stackers = [LinuxIntelSubStacker, LinuxAArch64SubStacker]
for linux_arch_stacker in linux_arch_stackers:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the stacking is operated blindly. However, we could also rely on symbols to determine the architecture to stack on.

I identified idmap_pg_dir to be arm64 exclusive, and present since the first 3.7 release. Relying on a symbol, avoids "forced exception rounds", which shouts about missing symbols when an AArch64 image is first passed to the Intel stacker.

Panchajanya1999 added a commit to DRDONavkiran/volatility3 that referenced this pull request Feb 22, 2025
Based on [1].

[1]: volatilityfoundation/volatility3#1088 (comment)

Signed-off-by: Panchajanya1999 <kernel@panchajanya.dev>
(cherry picked from commit da9df8c)
Signed-off-by: Panchajanya1999 <kernel@panchajanya.dev>
(cherry picked from commit 4b285df)
@Panchajanya1999

Panchajanya1999 commented Apr 1, 2025 •

Copy link
Copy Markdown

Hi,

i am trying to get volatility3 working for arm64 android and till now I got it partially working on a physical Google Pixel 6A and LAVA Agni 2.

From the list of unstable plugins, till now I have got lsof and elfs working properly. I tried rewriting netstat but still no luck.

Here is my repo, feel free to look into it!
https://github.com/Panchajanya1999/volatility3-arm64

Thank You! Will update this thread if i find something interesting to share.

[ oh btw, i used LiME to get proper ramdumps from these two devices ]

here are sample files to have a look
lsof.txt
elfs.txt

dadokkio added a commit to LDO-CERT/orochi that referenced this pull request Aug 8, 2025
* local files, nginx
* empty clamav with -
* api test code
* vt/maxmind error, update notebook
* test https, uv
* test dev build
* update changelog
* test build
* multiple version
* python3.12 - go1.22 - ws updates
* #1030 update - #947 method 1
* update libs
* upgrade tree view
* fix download dump error
* keep pip for volatility for shared install path
* plugin add fix
* improve plugin install, regipy plugins
* do things manually
* fix admin upload plugins
* #1068
* #1074
* fix 2 py files in same plugin
* hivelist with fire_and_forget, runtimeerror
* Add experimental support for ARM64
Waiting the merge of volatilityfoundation/volatility3#1088
* add arm64 to all linux plugins
* #1073 - wip
* improve create and unzip ui lock
* fix for linux pslist dump with arm64 and update vol3 commit
* update __init__
* integrity error
* description if available
* update libs, fix small issue
* #1073 wip
* 2fa, update libs, yara-x
* rule filter fix
* extra settings
* #1082
* add bodyfile support for timeliner
* plot bodyfile chart
* use go image to build dwarf2json
* fix: command variables are now in defaults.py
* update js, python libs
* fix datatables filter on bookmarks
* add DEFAULT_FROM_EMAIL settings
* add EMAIL_TIMEOUT settings
* fix port settings
* email required at signup
* https support in external env
* #1102
* WIP: no elastic + varie
* keep elastic for migration
* fixes, elk migration
* fix import value key
* offcanvas left sidebar
* speedup value import
* dask status
* #1071
* use browser history
* fix diff_view path
* fix new menu, update libs
* #1073
* check deps on new
* #1073 + new uv setup
* Update dependabot.yml to pyproject in new
* some minor fix
* replace jscolor with coloris [wip] + bootstrap toast
* rules sync fix
* move some auth variables from config to env
* small fixes
* loading in symbols upload
* port update rendering fix in our custom one
* #1309 #1310
* partial fix for coloris.js
* proxy dask status
* fixes: #1341 - #1308
* fix merge
---------
Co-authored-by: Davide Arcuri <davide.arcuri@leonardo.com>
Co-authored-by: garanews <puntogtg@tiscali.it>
dadokkio added a commit to LDO-CERT/orochi that referenced this pull request Aug 8, 2025
* local files, nginx

* empty clamav with -

* api test code

* api test code

* vt/maxmind error, update notebook

* test https, uv

* test dev build

* update changelog

* test build

* test dev build

* test dev build

* test dev build

* test dev build

* multiple version

* test dev build

* python3.12 - go1.22 - ws updates

* python3.12 - go1.22 - ws updates

* #1030 update - #947 method 1

* update libs

* upgrade tree view

* fix download dump error

* keep pip for volatility for shared install path

* plugin add fix

* plugin add fix

* improve plugin install, regipy plugins

* do things manually

* do things manually

* fix admin upload plugins

* #1068

* #1068

* update changelog

* #1074

* #1074

* fix 2 py files in same plugin

* #1074

* hivelist with fire_and_forget, runtimeerror

* hivelist with fire_and_forget, runtimeerror

* Add experimental support for ARM64

Waiting the merge of volatilityfoundation/volatility3#1088

* add arm64 to all linux plugins

* #1073 - wip

* improve create and unzip ui lock

* fix for linux pslist dump with arm64 and update vol3 commit

* update __init__

* integrity error

* description if available

* update libs, fix small issue

* update libs, fix small issue

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* 2fa, update libs, yara-x

* rule filter fix

* extra settings

* #1082

* #1082

* add bodyfile support for timeliner

* plot bodyfile chart

* plot bodyfile chart

* use go image to build dwarf2json

* fix: command variables are now in defaults.py

* update js, python libs

* fix datatables filter on bookmarks

* add DEFAULT_FROM_EMAIL settings

* add EMAIL_TIMEOUT settings

* fix port settings

* email required at signup

* https support in external env

* https support in external env

* #1102

* WIP: no elastic + varie

* keep elastic for migration

* fixes, elk migration

* fix import value key

* offcanvas left sidebar

* speedup value import

* dask status

* #1071

* use browser history

* fix diff_view path

* fix new menu, update libs

* #1073

* #1073

* #1073

* #1073

* #1073

* check deps on new

* #1073

* #1073

* #1073 + new uv setup

* #1073 + new uv setup

* Update dependabot.yml to pyproject in new

* #1073 + new uv setup

* some minor fix

* replace jscolor with coloris [wip] + bootstrap toast

* rules sync fix

* move some auth variables from config to env

* small fixes

* loading in symbols upload

* port update rendering fix in our custom one

* #1309 #1310

* partial fix for coloris.js

* proxy dask status

* fixes: #1341 - #1308

* fix merge

* maxmind to_ditc instead of raw

* deepsource suggest

---------

Co-authored-by: Davide Arcuri <davide.arcuri@leonardo.com>
Co-authored-by: garanews <puntogtg@tiscali.it>
dadokkio added a commit to LDO-CERT/orochi that referenced this pull request Sep 3, 2025
* local files, nginx

* empty clamav with -

* api test code

* api test code

* vt/maxmind error, update notebook

* test https, uv

* test dev build

* update changelog

* test build

* test dev build

* test dev build

* test dev build

* test dev build

* multiple version

* test dev build

* python3.12 - go1.22 - ws updates

* python3.12 - go1.22 - ws updates

* #1030 update - #947 method 1

* update libs

* upgrade tree view

* fix download dump error

* keep pip for volatility for shared install path

* plugin add fix

* plugin add fix

* improve plugin install, regipy plugins

* do things manually

* do things manually

* fix admin upload plugins

* #1068

* #1068

* update changelog

* #1074

* #1074

* fix 2 py files in same plugin

* #1074

* hivelist with fire_and_forget, runtimeerror

* hivelist with fire_and_forget, runtimeerror

* Add experimental support for ARM64

Waiting the merge of volatilityfoundation/volatility3#1088

* add arm64 to all linux plugins

* #1073 - wip

* improve create and unzip ui lock

* fix for linux pslist dump with arm64 and update vol3 commit

* update __init__

* integrity error

* description if available

* update libs, fix small issue

* update libs, fix small issue

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* 2fa, update libs, yara-x

* rule filter fix

* extra settings

* #1082

* #1082

* add bodyfile support for timeliner

* plot bodyfile chart

* plot bodyfile chart

* use go image to build dwarf2json

* fix: command variables are now in defaults.py

* update js, python libs

* fix datatables filter on bookmarks

* add DEFAULT_FROM_EMAIL settings

* add EMAIL_TIMEOUT settings

* fix port settings

* email required at signup

* https support in external env

* https support in external env

* #1102

* WIP: no elastic + varie

* keep elastic for migration

* fixes, elk migration

* fix import value key

* offcanvas left sidebar

* speedup value import

* dask status

* #1071

* use browser history

* fix diff_view path

* fix new menu, update libs

* #1073

* #1073

* #1073

* #1073

* #1073

* check deps on new

* #1073

* #1073

* #1073 + new uv setup

* #1073 + new uv setup

* Update dependabot.yml to pyproject in new

* #1073 + new uv setup

* some minor fix

* replace jscolor with coloris [wip] + bootstrap toast

* rules sync fix

* move some auth variables from config to env

* small fixes

* loading in symbols upload

* port update rendering fix in our custom one

* #1309 #1310

* partial fix for coloris.js

* proxy dask status

* fixes: #1341 - #1308

* fix merge

* maxmind to_ditc instead of raw

* deepsource suggest

* #1359 misp export restore

* fixarm (#1363)

Co-authored-by: garanews <puntogtg@tiscali.it>

* 2.4.1

* fix vt uuid

---------

Co-authored-by: Davide Arcuri <davide.arcuri@leonardo.com>
Co-authored-by: garanews <puntogtg@tiscali.it>

@ikelos ikelos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, finally found time to go through this. It's actually in a really good place, and I'm sorry I couldn't find the time before to go through it all. As it is, I've only really gone through the arm layer, and not any of the automagic/linux.py changes yet. I couldn't find any kind of generic arm stacker, which I see is because we're using info from the linux layer to figure out the various values for ARM registers, much like we do with intel. I'll review that another time (and actually, I'd almost like to the get the arm layer in without the stacker first, just so it's available, and so everything doesn't sit waiting on the stacker. That would also allow people to share around config files to load up arm layers even though automagic can't do it directly yet...

I will try and get to the linux stacker stuff soon, hopefully in a couple of weeks, but no promises (sadly). This stuff seems to take me a long time these days...

description="Kernel unique identifier, including compiler name and version, kernel version, compile time.",
),
requirements.IntRequirement(
name=AArch64RegMap.TCR_EL1.__name__,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamically named options are risky, because a change to that class could cause an API change to this class (because the input options would change name). I'd much prefer these to take string names or in a worst case scenario, look them up in constants.

return cls._table_lookup(value, lookup_table, reverse_lookup)


def set_reg_bits(value: int, reg_field: Enum, reg_value: int = 0) -> int:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this seems to relate only to AArch64RegFieldValues, could this be made a method of it (a staticmethod or classmethod would be fine), rather than floating off on it's own?

)
self._base_layer = self.config["memory_layer"]
# self._swap_layers = [] # TODO
self._page_map_offset = self.config["page_map_offset"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so... it looks like we've got the page_map_offet (for non kernel spaces) and then a separate option requirement that contains the register pointing to the kernel layer's page table structure? That's reasonably elegant, and I guess for the kernel space you could use the same value for both the page_table and the TTBR1. Still trying to think through the ramifications, but so far it seems ok.

I'm wondering why you picked page_map_offset for the config option, rather than TTBR0 or something for clarity? If it's something that's expected in other places in the code, then I might want to review those places, because I don't think layer are allowed to depend on requirements of a generic layer (and if we want to have that value exposed in all layers, which doesn't make sense because not every layer has a page table) then it should be done with an interface that exposes a read-only property and have that applied to both intel and arm.

I understand we're treating them as two different layers, but I can't tell whether conceptually that makes sense. On the one hand, both registers can change indepdendently of each other (in theory). On the other hand, a process label object may well want to read data from the kernel layer, presumably?

# [1], see D8.3, page 5852
return (
49 if ttb_granule in [4, 16] and is_52bits else 47,
ttb_lookup_indexes[-1][1],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get this is trying to get the tail of the list, but it could do with a comment just to say that's what's going on. This also doesn't match the signature type, which says ttb_lookup_indexes is supposed to be int whereas _determine_ttb_lookup_indexes which is passed into it, returns List[Tuple[int]]? Could we type it properly and add Napolean style docstrings throughout the whole class to give a description for what each argument is please?

ttb_selector = self._mask(virtual_offset, 55, 55)

# Check if requested address belongs to the virtual memory space context
if ttb_selector != self._virtual_addr_space:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this basically says "if we're in the process space and ask for a kernel address, fail immediately". I get the simplification, but I feel as though that's quite limiting? Given we're supposed to know where the kernel layer table (TTBR1 reg value) is supposed to be, could we just swap that in for table_address and translate it correctly here? Throwing an error feels like it will make every consumer have to code in support for a double lookup. I'm not sure the volatility use needs to know the difference (although there should be a convenience function on the layer to allow users to figure out which table an address is part of).

if isinstance(excp, exceptions.PagedInvalidAddressException):
mask = (1 << excp.invalid_bits) - 1
else:
mask = (1 << self.page_shift) - 1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more expensive than just accessing _page_size_in_bits.

def _get_valid_table(self, base_address: int) -> Optional[bytes]:
"""Extracts the translation table, validates it and returns it if it's valid."""
table = self._context.layers.read(
self._base_layer, base_address, self.page_size

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds two function calls to what would otherwise just be a variable lookup. Please use self._page_size.


masked_trees = {}
for mm_cls_name, mm_cls in inspect.getmembers(AArch64RegMap, inspect.isclass):
if issubclass(mm_cls, Enum) and mm_cls_name in registers_values.keys():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want an else clause with a vollog saying why it got there instead of doing what was expected.

"""Canonicalizes an address by performing an appropiate sign extension on the higher addresses"""
if self._bits_per_register <= self._ttb_bitsize:
return addr & self.address_mask
elif addr < (1 << self._ttb_bitsize - 1):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have this elif? This isn't getting the canonical prefix it might otherwise expect? Does arm even have address canonicalization? There have been arm reference comments everywhere else, but I can't see one here?

def _mask(
value: int, high_bit: int, low_bit: int, shift: Optional[int] = None
) -> int:
"""Returns the bits of a value between highbit and lowbit inclusive."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this is identical to intel. Fiven there's only two, it's probably worth keeping them in their own classes, but we might want to figure out what shared location we would move them to, if we were going to?

dadokkio added a commit to LDO-CERT/orochi that referenced this pull request Jul 28, 2026
* local files, nginx

* empty clamav with -

* api test code

* api test code

* vt/maxmind error, update notebook

* test https, uv

* test dev build

* update changelog

* test build

* test dev build

* test dev build

* test dev build

* test dev build

* multiple version

* test dev build

* python3.12 - go1.22 - ws updates

* python3.12 - go1.22 - ws updates

* #1030 update - #947 method 1

* update libs

* upgrade tree view

* fix download dump error

* keep pip for volatility for shared install path

* plugin add fix

* plugin add fix

* improve plugin install, regipy plugins

* do things manually

* do things manually

* fix admin upload plugins

* #1068

* #1068

* update changelog

* #1074

* #1074

* fix 2 py files in same plugin

* #1074

* hivelist with fire_and_forget, runtimeerror

* hivelist with fire_and_forget, runtimeerror

* Add experimental support for ARM64

Waiting the merge of volatilityfoundation/volatility3#1088

* add arm64 to all linux plugins

* #1073 - wip

* improve create and unzip ui lock

* fix for linux pslist dump with arm64 and update vol3 commit

* update __init__

* integrity error

* description if available

* update libs, fix small issue

* update libs, fix small issue

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* #1073 wip

* 2fa, update libs, yara-x

* rule filter fix

* extra settings

* #1082

* #1082

* add bodyfile support for timeliner

* plot bodyfile chart

* plot bodyfile chart

* use go image to build dwarf2json

* fix: command variables are now in defaults.py

* update js, python libs

* fix datatables filter on bookmarks

* add DEFAULT_FROM_EMAIL settings

* add EMAIL_TIMEOUT settings

* fix port settings

* email required at signup

* https support in external env

* https support in external env

* #1102

* WIP: no elastic + varie

* keep elastic for migration

* fixes, elk migration

* fix import value key

* offcanvas left sidebar

* speedup value import

* dask status

* #1071

* use browser history

* fix diff_view path

* fix new menu, update libs

* #1073

* #1073

* #1073

* #1073

* #1073

* check deps on new

* #1073

* #1073

* #1073 + new uv setup

* #1073 + new uv setup

* Update dependabot.yml to pyproject in new

* #1073 + new uv setup

* some minor fix

* replace jscolor with coloris [wip] + bootstrap toast

* rules sync fix

* move some auth variables from config to env

* small fixes

* loading in symbols upload

* port update rendering fix in our custom one

* #1309 #1310

* partial fix for coloris.js

* proxy dask status

* fixes: #1341 - #1308

* fix merge

* maxmind to_ditc instead of raw

* deepsource suggest

* #1359 misp export restore

* fixarm (#1363)

Co-authored-by: garanews <puntogtg@tiscali.it>

* 2.4.1

* fix vt uuid

* 2.4.2 wip

* new style

* fix bodyfile

---------

Co-authored-by: Davide Arcuri <davide.arcuri@leonardo.com>
Co-authored-by: garanews <puntogtg@tiscali.it>
@cpuu

cpuu commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Hi @Abyss-W4tcher, thanks for your work on AArch64 support! I noticed that this PR has been open for over two years and is still awaiting merge. I’d like to share my test results for commit 5ee05ce in the hope that they can help move things forward.

I tested this commit on a Raspberry Pi 4 running Ubuntu 24.04.5 LTS with kernel 6.8.0-1064-raspi and 4 KB pages, using a memory dump acquired with AVML 0.21.0 and a matching ISF. I added AArch64 to the plugins’ architecture requirements as instructed.

Of the 30 Linux plugins available in that revision, 15 successfully returned results, 7 returned empty results, and 7 encountered errors. I plan to investigate further to distinguish AArch64-specific issues from limitations in the Linux plugin implementations or kernel compatibility. Cross-checking against Intel Linux samples should help with that. The remaining plugin, check_idt, is specific to Intel’s interrupt descriptor table and does not apply to AArch64.

With the growing number of IoT devices and the diversity of embedded ARM Linux systems, I’d really like to see memory forensics support extend to these devices, and I hope to contribute by testing a wider range of configurations. I’m also working with the AVML project to help validate AArch64 memory acquisition. I’d be happy to share the commands and relevant logs if useful.

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.

8 participants