Feature: new renderer support Mermaid π§ββοΈ (for tree relationship).#737
Conversation
Mermaid (for tree relationship).
|
This looks like it'll be really awesome, but I'm afraid the renderer is hard coded with column names to produce the relationships ( I'd suggest giving each node a random identifier and then the first node that's one level higher before it, is it's parent (so each time there's a step down, pop the node on the end of a parent list, and use the end of the list as the parent, and each step up pop it off the list). That will make the renderer much more generic and work with any tree-based plugin, rather than just those that output Another option would be to make this a very handy additional tool to run over existing output methods (such as JSON, JSONL or similar) if you'd prefer? |
@ikelos That's right, I think you gave me a good guide about the part I was worried about. If so, we will change this PR to Draft PR because we still need more work and we are not ready for the review. If the prepared code is completed according to the feedback soon and it is enough to receive a review, I will request it again. I hope it will be a good feature that many people will use. |
@ikelos Could you give me a little more detail about the this comment, I'll try it the way you first suggested it, but if it's a good suggestion to improve further, I'll be happy to accept it. |
Sure, I just meant you could write it as a separate tool which takes in the existing output from volatility3 and then produces the mermaid output from that, so something like:
If you really wanted you could write a separate program (or a volshell snippet) which could do the same thing. I think that make it a renderer makes more sense, but if it was tricky to make it generic then this would be another option. 5:) |
@ikelos Ah I understand, but I also think the best way is to implement it as a renderer. Thank you for the detailed explanation. π |
Mermaid (for tree relationship).Mermaid π§ββοΈ (for tree relationship).
Address review feedback that the renderer was tightly coupled to plugins
exposing PID/PPID columns: the previous implementation looked up "PID"
and "PPID" by name to build parent->child edges and raised a generic
exception otherwise, which prevented any non-pstree tree plugin from
being rendered as Mermaid.
The relationship is already encoded in the TreeGrid -- every TreeNode
carries its path_depth -- so the new render() walks the rows in
traversal order and tracks ancestry with a parent stack:
* descending one or more levels pushes the previously-emitted node
once per level (so a level skip still produces sane pops);
* ascending pops the corresponding number of levels;
* the stack top is always the parent of the next emitted node, or
empty for a root-level node.
Each node is given a stable per-render identifier (n1, n2, ...) instead
of being keyed by a column value such as PID, since PIDs are not unique
across a TreeGrid and may contain characters that are unsafe in Mermaid
node IDs.
A small label-escaping helper replaces the previous ad-hoc string
replacement of parentheses, and embedded newlines in cell renderings
are folded to <br> so each row stays a single Mermaid node.
The unused tree_indent_column placeholder (flagged by code scanning)
is dropped as part of the rewrite.
Bring the new MermaidRenderer in line with the repository's ruff formatting rules (introduced in the develop merge that this branch just absorbed): double-quoted strings, trailing comma after the last mapping entry, four-space hanging indent for the visitor signature, and an additional blank line between top-level classes.
|
Hi @ikelos β coming back to this one after rather a long term. Could you please review this PR when you have time? The renderer is now plugin-agnostic: instead of looking up |
ikelos
left a comment
There was a problem hiding this comment.
Thanks for taking the time to rework this, it looks much more flexible and applicable to all outputs! 5:D Just one minor point, and it's not a show stopper, but it feels like next_id could be a generator (specifically the itertools.count generator). Otherwise this looks good!
Per review feedback, the small next_id() closure that combined a 'nonlocal node_counter' assignment with an f-string formatter is more naturally expressed as itertools.count. The counter generator yields the integer sequence starting at 1 and the call site formats it as 'n<index>' on the spot, so the behaviour is unchanged: per-render, strictly-increasing, plugin-agnostic Mermaid node identifiers.
|
Looks good, thanks! I'll merge this once the tests have completed. 5:) |
Description
Hello, everyone in the community! π
Through
dot-based rendering inVolatility, we were able to conduct an effective analysis by visualizing the relationship between processes and the composition ofVADin the form of trees.Volatility 3now helps us visualize tree-like information through Depth, but there are limitations.I thought a lot about whether to migrate
dotfirst.Dot is still a good visualization tool and helps many developers and analysts.
However, I would like to propose a new instrument called
mermaid.Mermaid, (Repository) is a good tool for dynamically rendering charts or graphs based on markdowns.When we sometimes had to share dots with the outside world using
dots, we needed to share files, take screenshots, or have a separate viewer.However,
mermaidhas the advantage of being able to share and write graphs neatly inSVGform easily in markdown or web. (Github also officially supports this and is included as an example in this PR.)Of course, if you want to use Mermaid more precisely, you need to change the rendering structure. (Unlike before, we don't seem to have the means to configure rendering on each plugin.) But I think it can get better gradually.
I submitted a PR for the basic
Mermaidrendering code. This is sufficient to indicate tree relationships such asPIDandPPID, and feedback from other analysts was also available.Command
> python3 vol.py -f 32.vmem -r mermaid windows.pstreeResult
Terminal Text
Embedded
graph TD 0 --> 4[PID:4<br>PPID:0<br>ImageFileName:System<br>OffsetV:0x86359280<br>Threads:106<br>Handles:-<br>SessionId:N/A<br>Wow64:False<br>CreateTime:2022-04-26 04:57:11.000000 <br>ExitTime:N/A<br>] 4 --> 304[PID:304<br>PPID:4<br>ImageFileName:smss.exe<br>OffsetV:0x8c82f040<br>Threads:4<br>Handles:-<br>SessionId:N/A<br>Wow64:False<br>CreateTime:2022-04-26 04:57:11.000000 <br>ExitTime:N/A<br>] 4 --> 92[PID:92<br>PPID:4<br>ImageFileName:Registry<br>OffsetV:0x87e28640<br>Threads:4<br>Handles:-<br>SessionId:N/A<br>Wow64:False<br>CreateTime:2022-04-26 04:57:06.000000 <br>ExitTime:N/A<br>] 4 --> 1564[PID:1564<br>PPID:4<br>ImageFileName:MemCompression<br>OffsetV:0x863b35c0<br>Threads:18<br>Handles:-<br>SessionId:N/A<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 384 --> 404[PID:404<br>PPID:384<br>ImageFileName:csrss.exe<br>OffsetV:0x9244c0c0<br>Threads:14<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 384 --> 480[PID:480<br>PPID:384<br>ImageFileName:wininit.exe<br>OffsetV:0x92530040<br>Threads:8<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 480 --> 616[PID:616<br>PPID:480<br>ImageFileName:services.exe<br>OffsetV:0x8cd14040<br>Threads:12<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 768[PID:768<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x92596680<br>Threads:25<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 768 --> 2976[PID:2976<br>PPID:768<br>ImageFileName:SearchApp.exe<br>OffsetV:0x9d18d600<br>Threads:29<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 768 --> 4544[PID:4544<br>PPID:768<br>ImageFileName:dllhost.exe<br>OffsetV:0x863d5040<br>Threads:8<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:20.000000 <br>ExitTime:N/A<br>] 768 --> 4072[PID:4072<br>PPID:768<br>ImageFileName:StartMenuExper<br>OffsetV:0x977b6040<br>Threads:35<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 768 --> 4200[PID:4200<br>PPID:768<br>ImageFileName:backgroundTask<br>OffsetV:0xa1c9e640<br>Threads:7<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:19.000000 <br>ExitTime:N/A<br>] 768 --> 4780[PID:4780<br>PPID:768<br>ImageFileName:mobsync.exe<br>OffsetV:0xa833a800<br>Threads:8<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:22.000000 <br>ExitTime:N/A<br>] 768 --> 5148[PID:5148<br>PPID:768<br>ImageFileName:RuntimeBroker.<br>OffsetV:0x965657c0<br>Threads:10<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:24.000000 <br>ExitTime:N/A<br>] 768 --> 3792[PID:3792<br>PPID:768<br>ImageFileName:SppExtComObj.E<br>OffsetV:0xa04db040<br>Threads:8<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:17.000000 <br>ExitTime:N/A<br>] 768 --> 4464[PID:4464<br>PPID:768<br>ImageFileName:dllhost.exe<br>OffsetV:0xa1ce0800<br>Threads:8<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:19.000000 <br>ExitTime:N/A<br>] 768 --> 1044[PID:1044<br>PPID:768<br>ImageFileName:WmiPrvSE.exe<br>OffsetV:0x9d01f600<br>Threads:11<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 768 --> 2132[PID:2132<br>PPID:768<br>ImageFileName:RuntimeBroker.<br>OffsetV:0x9d082680<br>Threads:21<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 768 --> 2460[PID:2460<br>PPID:768<br>ImageFileName:RuntimeBroker.<br>OffsetV:0x9d1df040<br>Threads:16<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 616 --> 2444[PID:2444<br>PPID:616<br>ImageFileName:sppsvc.exe<br>OffsetV:0x9bdae7c0<br>Threads:9<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 2060[PID:2060<br>PPID:616<br>ImageFileName:SearchIndexer.<br>OffsetV:0x9d18a040<br>Threads:22<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:18.000000 <br>ExitTime:N/A<br>] 2060 --> 4984[PID:4984<br>PPID:2060<br>ImageFileName:SearchFilterHo<br>OffsetV:0xa834c840<br>Threads:6<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:23.000000 <br>ExitTime:N/A<br>] 2060 --> 4916[PID:4916<br>PPID:2060<br>ImageFileName:SearchProtocol<br>OffsetV:0xa1d5f040<br>Threads:9<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:23.000000 <br>ExitTime:N/A<br>] 616 --> 1940[PID:1940<br>PPID:616<br>ImageFileName:spoolsv.exe<br>OffsetV:0x863fb880<br>Threads:13<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 3220[PID:3220<br>PPID:616<br>ImageFileName:NisSrv.exe<br>OffsetV:0xa043e840<br>Threads:9<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:15.000000 <br>ExitTime:N/A<br>] 616 --> 1436[PID:1436<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x977a87c0<br>Threads:17<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 1820[PID:1820<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x863d5840<br>Threads:21<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1444[PID:1444<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x89ba1580<br>Threads:25<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 2088[PID:2088<br>PPID:616<br>ImageFileName:MsMpEng.exe<br>OffsetV:0x8c24c040<br>Threads:29<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 1072[PID:1072<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x965d1680<br>Threads:65<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 1072 --> 336[PID:336<br>PPID:1072<br>ImageFileName:sihost.exe<br>OffsetV:0x97777880<br>Threads:21<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 1072 --> 1580[PID:1580<br>PPID:1072<br>ImageFileName:taskhostw.exe<br>OffsetV:0x977b67c0<br>Threads:12<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 1200[PID:1200<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x9761d880<br>Threads:21<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 1200 --> 2360[PID:2360<br>PPID:1200<br>ImageFileName:ctfmon.exe<br>OffsetV:0x9bdae040<br>Threads:12<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 1968[PID:1968<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x863de880<br>Threads:19<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 3120[PID:3120<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x9bd05480<br>Threads:10<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:15.000000 <br>ExitTime:N/A<br>] 616 --> 1472[PID:1472<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x8636f840<br>Threads:6<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1092[PID:1092<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x965d3440<br>Threads:21<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 3656[PID:3656<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x9777b040<br>Threads:9<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:16.000000 <br>ExitTime:N/A<br>] 616 --> 1108[PID:1108<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x965db040<br>Threads:22<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 2780[PID:2780<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x9daf9640<br>Threads:39<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:14.000000 <br>ExitTime:N/A<br>] 2780 --> 4708[PID:4708<br>PPID:2780<br>ImageFileName:rundll32.exe<br>OffsetV:0xa1d5c040<br>Threads:5<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:22.000000 <br>ExitTime:N/A<br>] 616 --> 352[PID:352<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x97777080<br>Threads:17<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:13.000000 <br>ExitTime:N/A<br>] 616 --> 3040[PID:3040<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x89bee040<br>Threads:13<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:15.000000 <br>ExitTime:N/A<br>] 616 --> 868[PID:868<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x9652a680<br>Threads:18<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1764[PID:1764<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x863cd040<br>Threads:14<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1644[PID:1644<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x863c1040<br>Threads:14<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1264[PID:1264<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x976336c0<br>Threads:31<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 616 --> 1784[PID:1784<br>PPID:616<br>ImageFileName:svchost.exe<br>OffsetV:0x863d0840<br>Threads:7<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 480 --> 752[PID:752<br>PPID:480<br>ImageFileName:fontdrvhost.ex<br>OffsetV:0x925997c0<br>Threads:8<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 480 --> 652[PID:652<br>PPID:480<br>ImageFileName:lsass.exe<br>OffsetV:0x92474040<br>Threads:14<br>Handles:-<br>SessionId:0<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 472 --> 496[PID:496<br>PPID:472<br>ImageFileName:csrss.exe<br>OffsetV:0x92533080<br>Threads:15<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 472 --> 576[PID:576<br>PPID:472<br>ImageFileName:winlogon.exe<br>OffsetV:0x9256c680<br>Threads:8<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 576 --> 760[PID:760<br>PPID:576<br>ImageFileName:fontdrvhost.ex<br>OffsetV:0x92599040<br>Threads:8<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 576 --> 956[PID:956<br>PPID:576<br>ImageFileName:dwm.exe<br>OffsetV:0x96565040<br>Threads:22<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:12.000000 <br>ExitTime:N/A<br>] 576 --> 2860[PID:2860<br>PPID:576<br>ImageFileName:userinit.exe<br>OffsetV:0x9db7b840<br>Threads:6<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:14.000000 <br>ExitTime:N/A<br>] 2860 --> 2892[PID:2892<br>PPID:2860<br>ImageFileName:explorer.exe<br>OffsetV:0x9db92080<br>Threads:71<br>Handles:-<br>SessionId:1<br>Wow64:False<br>CreateTime:2022-04-26 04:57:15.000000 <br>ExitTime:N/A<br>]Detail Screenshot
If you are interested in or have any comments on this PR, please feel free to leave a thread! π