Tools · Forensics tools · 09 / 25
Volatility 3: loaded modules and private executable memory
windows.dlllist and windows.ldrmodules describe modules a process loaded. windows.malfind points at private executable pages. Each hit is a region to account for, and security tools produce hits too.
A module list is what the loader recorded
windows.dlllist prints the modules a process loaded through the normal loader lists: the path, the base address, and a size. You use it when you need to know whether a specific library was in the process you already identified. A payroll case often cares less about every DLL in explorer.exe and more about whether pid 4812’s powershell.exe is the stock binary from the disk hash and which modules it had loaded. Compare a path to Autopsy. A module path that is not on disk anymore, or that lives in a Temp directory, is a lead. A path under System32 that matches a known hash is the ordinary case.
windows.ldrmodules compares the three loader lists Windows keeps. A module present in one list and missing from another is an inconsistency in those lists. You report the path and which lists contain it. Security products and some debuggers alter loader state on machines you are allowed to examine, so an inconsistency is a queue, and the publisher and the path decide how fast you move. A Temp path with a broken list goes in the report. A signed driver you were told the company deploys can be noted and set aside.
Private executable pages are a place to look
windows.malfind looks for memory regions that are privately allocated, executable, and not backed by a mapped file the way a normal module is. The output names a pid, an address, a protection, and a short preview of bytes. A hit means “this region does not look like a normal mapped DLL.” It is the start of a review. Processes that compile or unpack at runtime, and several kinds of security software, can allocate executable memory on a healthy host. The preview is there so you can see whether the region starts with a recognizable file header or looks like data. You do not need to act on the bytes beyond recording them and, when the procedure says so, handing a dump to a reviewer.
If you dump a region, hash the dump, record the pid and the address, and store it as a derivative of the memory image. The image remains the evidence. A dump is for a second look under the lab rules, often with YARA for a string you already have from the case, such as the workbook name. Pasting a page of raw bytes into the report helps almost no one. The address, the protection, the pid, and whether the workbook string appears are the sentences.
- Pid and process name, tied back to pslist or psscan.
- Address and protection as the plugin printed them.
- Whether the region is file-backed or private.
- Whether a case string appears, and the hash of any dump you made.
Handles tell you what the process had open
windows.handles, filtered to the pid you care about, lists objects the process had open: files, keys, mutants, other processes. A file handle to \Temp\p4.xlsx is a direct tie between that process object and the path on disk, stronger than a command-line string because the kernel had an open object. A handle can close before acquisition, so absence is the usual situation for an exited process. Presence is the lucky case. Record the object name and the pid.
A handle on another process is a different kind of row. Read the target process name and the access the table shows, and remember that administrative tools and endpoint agents open processes as their job. The source image and the target image decide whether the row belongs in the finding. An unknown Temp binary with a handle on lsass.exe is urgent on a host you are examining. explorer.exe with ordinary handles is the desktop. The plugin does not rank them. You do, in writing, with the names visible.
Keep the review inside the image
Everything in this lesson is a description of pages and objects already in NL-FIN-14.raw. You are not asked to reproduce a technique that would create private executable memory, and the report does not need that procedure. It needs the region, the owner, and what you compared it to. If a region is not explained by a file on disk or by software Northline says they run, it stays tagged “unexplained executable region” with the address. That tag is allowed to be the end of your part of the work when a malware specialist has the dump.
Save plugin output beside the other Volatility text. Name the files with the plugin and the pid so windows-malfind-4812.txt does not get mixed with a later run. If there are no hits, save the empty result too. A missing file looks like a plugin you forgot.
Worked case: stock powershell, no extra region, one file string
windows.dlllist for pid 4812 shows the System32 path for powershell.exe and the usual runtime libraries. That path matches the NSRL-hashed binary on disk. windows.malfind produces no region for pid 4812. You record the negative. windows.handles for that pid is sparse because the process had exited; it does not show an open file. The command line from the earlier lesson remains the link to the workbook paths.
You add one sentence to the memory note: the exited powershell object looks like the stock binary, malfind did not flag a private executable region for it, and the open-file handle did not survive. The unexplained piece is still the remote TIME_WAIT row, which you already wrote up under netscan. You do not invent an injection to fill a quiet malfind.
Diagram
Three memory results and the note each one earns
What you write
- Module path
dlllist names a file. Compare that path and hash to the disk. A System32 path with a known hash is the stock binary.
- List mismatch
ldrmodules shows a path missing from one loader list. Record which lists. The path and the publisher decide the priority.
- Private page
malfind names an address and a protection. Identify the process. A dump is hashed and stored as a derivative, with the case string search you were asked to run.
Check yourself
1. windows.malfind prints one private executable region inside a process Northline’s software inventory says is their endpoint agent, and the path is the agent’s install directory. What is the careful next step?