Repository navigation
A hardening release. Output can no longer be redirected or mixed up through the output directory, and an interrupted run no longer leaves a broken symbol file in Volatility's cache. IOC lists keep look-alike hosts instead of dropping them. A monthly workflow now runs the latest Volatility 3 on real Linux, Windows 10 and macOS images. It is a major release because the output directory must now be new or empty.
Changed
- Breaking: the output directory must be new or empty, the default
volatility_outputincluded: a second plainvol-analyzerun in the same directory stops with "Output directory is not empty". Pass a new-odirectory per dump. Why: see the first two Security entries.
Security
- The output directory is entered once and then written through relative paths. Every write used to resolve the path again, so someone who can write to a parent directory (a shared case folder, or the current directory of a
sudorun) could swap in a directory with planted symlinks mid-run: it received the hashdump, andstrings/all.txtcould overwrite any file the analyst can write. - An existing output directory must be empty, as with bulk_extractor. Entries planted earlier (symlinks, world-readable files) were written through, and a second run into the same directory mixed two dumps' results: the text report named the new dump while
analysis_summary.jsonkept the old one's hashes. Scripts that reuse an output directory must pass a new one. strings/domains_lowconf.txt: names that match a noise filter (minified JS, file names, all-numeric, all-caps or mixed-case TLDs, ELF section names) are kept there instead of being dropped, so a host registered to look like noise (evil.app,navigator.top,4444.top,q.ai,Evil-C2.Top) is never lost. Only names that cannot be registered (no IANA TLD, closed brand TLDs) are dropped. 28,277 entries on Windows 10, 1,058 on Windows 7, 8,029 on Debian 7, 5,121 on macOS 10.9.- Control characters (C0, DEL, and C1 as UTF-8) in any argument (dump, output,
--symbolsand--isf-urlpaths, option values,VOL3_CMD) are refused, also when a symlinked directory brings them into a resolved path: a file name with newlines forged lines (MD5, plugin status) in the text report, and escape sequences reached the terminal. Unknown options are shown shell-quoted. - A relative dump path is made absolute before
volsees it:volreadhttp://host/mem.raw(a local directory namedhttp:) as a URL and fetched it, so the recorded hashes and the analysis covered different data. -othrough a symlink to a system directory (/etc), or to a directory below one that did not exist yet (/tmp/../etc/new/dir), got past the blocklist; the nearest existing parent is resolved to its physical path now (macOS/private/etcincluded), and the directory is checked again once entered...after a directory that does not exist yet (-o new/../../etc/x) is refused, as it cannot be resolved beforemkdir.- A backslash in the output path (
-o 'case\001') silently emptieddomains.txt(awk-vdecodes escapes) and could redirect a temporary file outside the output directory. - CI checkouts no longer keep the
GITHUB_TOKENin.git/config(persist-credentials: false).
Added
- Monthly "Real dumps" workflow (
make real-testlocally,make ci-realfor every CI step): runsvol-analyzewith the latest Volatility 3 release on public Linux (Debian), Windows 10 and macOS 10.9 images, all pinned by SHA-256, with OS auto-detection, as in the Quick Start, and fails when the OS is misdetected, a plugin fails (outside a short list of known Volatility 3 bugs), the reports miss the symbols used, or the IOC lists lose a known host. The fake-vol tests cannot catch upstream plugin or CLI changes; this does. make check-tldsfails when IANA's TLD list has changed since the lastmake update-tlds; it runs in the monthly workflow.strings/reverse_dns.txt: reverse-DNS identifiers (com.apple.audio,org.example.app) are split out ofdomains.txtinstead of being dropped. On a macOS 10.9 image they were 36% of all domain hits (com.applealone 43,596): 537 names move out, leaving 20,136 domains.SECURITY.mdwith private vulnerability reporting, and a bug report form.make hooksrunsmake cibefore everygit push(versioned.githooks/pre-push).- Release tags are SSH-signed, starting with v4.0.0.
- The text and JSON reports name the symbol table Volatility actually used ("Symbols Used" /
execution.symbols_used): the ISF file or URL on Linux/macOS, the kernel PDB name and GUID on Windows. It is read from the first plugin's debug log (vol.log). "ISF URL: none" could hide a remote ISF that Volatility had cached on an earlier--isf-urlrun and kept using. strings/domains.txtmatches all-caps hosts with three or more labels and a 2–3 letter TLD (LOGIN.LIVE.COM). Names are counted lower-cased, soGitHub.comandgithub.comadd up.strings/ipv4.txton macOS dumps reads netstat'saddress.portform (10.0.0.5.443→10.0.0.5).
Fixed
- OS auto-detection stopped a slow probe with SIGTERM, which kills
volwithout running its cleanup: a probe cut short whilevoldownloaded the Windows kernel PDB could leave a broken symbol file behind for every later run. Probes are now stopped with SIGINT (and killed 10 s later if that is ignored). The script times the probes itself, sotimeout/gtimeoutis no longer needed (uutilstimeout, the default on Ubuntu 26.04, does not deliver-s INT);VOL_DETECT_TIMEOUT=0means no limit. Likewise, Ctrl-C or SIGTERM tovol-analyzestops runningvolprocesses with SIGINT (after 2 s, which a Ctrl-C in the terminal needs to reach them first), and with SIGTERM only if they are still running 5 s after that. analysis_summary.jsonwas not valid UTF-8 for a file name in another encoding (caf\xe9.raw); such a path is written shell-quoted ($'caf\351.raw').stringsoutput is folded into lines of at most 8 KiB: one printable run of gigabytes in the image madegrepandsedhold all of it in memory. An interrupted run stopsstringstoo, and astringsfailure partway through is reported.-owith a directory name starting with-failed inmkdir.- Ctrl-C did not stop a shell loop over several dumps (
for f in *.raw; do vol-analyze "$f" -o "$f.out"; done):vol-analyzeexited with status 130, which tells the calling shell the interrupt was handled; it now ends by SIGINT. - A name followed by an underscore, alone or before a number (
c2.evil.top_,c2.evil.top_443), was lost fromdomains.txt. - Bash completion of
--isf-urloffered nothing once the URL contained:(https:), because readline splits words at colons. strings/domains.txtnoise on real dumps (Windows 10, Windows 7 CTF image, Debian 7). Moved todomains_lowconf.txt: minified JavaScript (this.id,t.name; one-letter names stay domains on .com/.net/.org/.me:x.org,t.me), Windows prefetch names (CMD.EXE-CD245F9E.pf), .NET names (System.IO), ELF section and GNU tar header names by exact name (note.gnu.build,data.rel.ro,gnu.linkonce.td,rela.got,text.hot,gnu.sparse.map). Dropped: closed brand TLDs that clash with code names (e.target,Date.now,microsoft.windows,wscript.shell). URL escapes no longer glue onto names (2Fwww.w3.org,%252Fdouble encoding included). Rules keyed on a first label (JS globals such asself,window) only apply to two-label names, so a subdomain an attacker picks (self.c2-panel.top) stays indomains.txt. 81,370 → 78,781 entries on Windows 10, 810 → 761 on Windows 7, 9,327 → 9,147 on Debian 7 (reverse-DNS identifiers now go toreverse_dns.txt: 190, 0 and 30).strings/ipv4.txtkept 0.x.x.x addresses, which are version strings: 784 → 511 entries on Debian 7, 2,531 → 2,503 on Windows 10, 269 → 266 on Windows 7.