diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5fdc83327..56d671102 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,13 +31,17 @@ jobs: gunzip linux-sample-1.bin.gz curl -sLO "https://downloads.volatilityfoundation.org/volatility3/images/win-xp-laptop-2005-06-25.img.gz" gunzip win-xp-laptop-2005-06-25.img.gz + curl -sLO "https://downloads.volatilityfoundation.org/volatility3/images/win-10_19041-2025_03.dmp.gz" + gunzip win-10_19041-2025_03.dmp.gz cd - - name: Download and Extract symbols run: | cd ./volatility3/symbols curl -sLO https://downloads.volatilityfoundation.org/volatility3/symbols/linux.zip + curl -sLO https://downloads.volatilityfoundation.org/volatility3/symbols/symbols_win-10_19041-2025_03.zip unzip linux.zip + unzip symbols_win-10_19041-2025_03.zip cd - - name: Testing... @@ -47,8 +51,8 @@ jobs: pytest ./test/plugins/linux/linux.py --volatility=volshell.py --image-dir=./test_images -k test_linux_volshell -v # Volatility - pytest ./test/plugins/windows/windows.py --volatility=vol.py --image-dir=./test_images -k "test_windows and not test_windows_volshell" -v - pytest ./test/plugins/linux/linux.py --volatility=vol.py --image-dir=./test_images -k "test_linux and not test_linux_volshell" -v + pytest ./test/plugins/windows/windows.py --volatility=vol.py --image=./test_images/win-10_19041-2025_03.dmp -k "test_windows and not test_windows_volshell" -v --durations=0 + pytest ./test/plugins/linux/linux.py --volatility=vol.py --image-dir=./test_images -k "test_linux and not test_linux_volshell" -v --durations=0 - name: Clean up post-test run: | diff --git a/test/__init__.py b/test/__init__.py index 2b59ef5ca..b2cfa3139 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,4 +1,8 @@ from enum import Enum +from pathlib import Path + +TESTS_ROOT_DIR = Path(__file__).parent +WINDOWS_TESTS_DATA_DIR = TESTS_ROOT_DIR / "plugins" / "windows" / "test_data" class Sample: @@ -9,6 +13,8 @@ class Sample: class WindowsSamples(Enum): WINDOWSXP_GENERIC = Sample("./test_images/win-xp-laptop-2005-06-25.img") """WindowsXP sample from early Volatility training.""" + WINDOWS10_GENERIC = Sample("./test_images/win-10_19041-2025_03.dmp") + """Windows10 CrashDump sample.""" class LinuxSamples(Enum): diff --git a/test/plugins/linux/linux.py b/test/plugins/linux/linux.py index 8ec485735..e39c1d15d 100644 --- a/test/plugins/linux/linux.py +++ b/test/plugins/linux/linux.py @@ -8,7 +8,7 @@ from test import test_volatility, LinuxSamples class TestLinuxVolshell: def test_linux_volshell(self, image, volatility, python): out = test_volatility.basic_volshell_test( - image, volatility, python, globalargs=("-l",) + image, volatility, python, volshellargs=("-l",) ) assert out.count(b" 100 diff --git a/test/plugins/windows/test_data/windows.driverirp.DriverIrp.json b/test/plugins/windows/test_data/windows.driverirp.DriverIrp.json new file mode 100644 index 000000000..f026e54a2 --- /dev/null +++ b/test/plugins/windows/test_data/windows.driverirp.DriverIrp.json @@ -0,0 +1,32 @@ +{ + "GENERIC": [ + "IRP_MJ_CREATE", + "IRP_MJ_CREATE_NAMED_PIPE", + "IRP_MJ_CLOSE", + "IRP_MJ_READ", + "IRP_MJ_WRITE", + "IRP_MJ_QUERY_INFORMATION", + "IRP_MJ_SET_INFORMATION", + "IRP_MJ_QUERY_EA", + "IRP_MJ_SET_EA", + "IRP_MJ_FLUSH_BUFFERS", + "IRP_MJ_QUERY_VOLUME_INFORMATION", + "IRP_MJ_SET_VOLUME_INFORMATION", + "IRP_MJ_DIRECTORY_CONTROL", + "IRP_MJ_FILE_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CONTROL", + "IRP_MJ_INTERNAL_DEVICE_CONTROL", + "IRP_MJ_SHUTDOWN", + "IRP_MJ_LOCK_CONTROL", + "IRP_MJ_CLEANUP", + "IRP_MJ_CREATE_MAILSLOT", + "IRP_MJ_QUERY_SECURITY", + "IRP_MJ_SET_SECURITY", + "IRP_MJ_POWER", + "IRP_MJ_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CHANGE", + "IRP_MJ_QUERY_QUOTA", + "IRP_MJ_SET_QUOTA", + "IRP_MJ_PNP" + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.info.Info.json b/test/plugins/windows/test_data/windows.info.Info.json new file mode 100644 index 000000000..ef350389f --- /dev/null +++ b/test/plugins/windows/test_data/windows.info.Info.json @@ -0,0 +1,96 @@ +{ + "WINDOWS10_GENERIC": [ + { + "Value": "0xf8043601f000", + "Variable": "Kernel Base" + }, + { + "Value": "0x6d4000", + "Variable": "DTB" + }, + { + "Value": "True", + "Variable": "Is64Bit" + }, + { + "Value": "False", + "Variable": "IsPAE" + }, + { + "Value": "0 WindowsIntel32e", + "Variable": "layer_name" + }, + { + "Value": "1 WindowsCrashDump64Layer", + "Variable": "memory_layer" + }, + { + "Value": "2 FileLayer", + "Variable": "base_layer" + }, + { + "Value": "0xf80436c1fb20", + "Variable": "KdDebuggerDataBlock" + }, + { + "Value": "19041.1.amd64fre.vb_release.1912", + "Variable": "NTBuildLab" + }, + { + "Value": "0", + "Variable": "CSDVersion" + }, + { + "Value": "0xf80436c2e420", + "Variable": "KdVersionBlock" + }, + { + "Value": "15.19041", + "Variable": "Major/Minor" + }, + { + "Value": "34404", + "Variable": "MachineType" + }, + { + "Value": "1", + "Variable": "KeNumberProcessors" + }, + { + "Value": "2025-03-06 17:59:20+00:00", + "Variable": "SystemTime" + }, + { + "Value": "C:\\Windows", + "Variable": "NtSystemRoot" + }, + { + "Value": "NtProductWinNt", + "Variable": "NtProductType" + }, + { + "Value": "10", + "Variable": "NtMajorVersion" + }, + { + "Value": "0", + "Variable": "NtMinorVersion" + }, + { + "Value": "10", + "Variable": "PE MajorOperatingSystemVersion" + }, + { + "Value": "0", + "Variable": "PE MinorOperatingSystemVersion" + }, + { + "Value": "34404", + "Variable": "PE Machine" + }, + { + "Value": "Tue Sep 26 06:53:33 2023", + "Variable": "PE TimeDateStamp" + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.pstree.PsTree.json b/test/plugins/windows/test_data/windows.pstree.PsTree.json new file mode 100644 index 000000000..139931730 --- /dev/null +++ b/test/plugins/windows/test_data/windows.pstree.PsTree.json @@ -0,0 +1,375 @@ +{ + "WINDOWS10_GENERIC": { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\winlogon.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:49:34+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "winlogon.exe", + "Offset(V)": 145201769754752, + "PID": 3616, + "PPID": 3568, + "Path": null, + "SessionId": 2, + "Threads": 3, + "Wow64": false, + "__children": [ + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\userinit.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:50:15+00:00", + "ExitTime": "2025-03-06T17:50:32+00:00", + "Handles": null, + "ImageFileName": "userinit.exe", + "Offset(V)": 145201786712256, + "PID": 4832, + "PPID": 3616, + "Path": null, + "SessionId": 2, + "Threads": 0, + "Wow64": false, + "__children": [ + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\explorer.exe", + "Cmd": "C:\\Windows\\Explorer.EXE", + "CreateTime": "2025-03-06T17:50:17+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "explorer.exe", + "Offset(V)": 145201787191488, + "PID": 4912, + "PPID": 4832, + "Path": "C:\\Windows\\Explorer.EXE", + "SessionId": 2, + "Threads": 57, + "Wow64": false, + "__children": [ + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\SecurityHealthSystray.exe", + "Cmd": "\"C:\\Windows\\System32\\SecurityHealthSystray.exe\" ", + "CreateTime": "2025-03-06T17:51:05+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "SecurityHealth", + "Offset(V)": 145201826054336, + "PID": 1860, + "PPID": 4912, + "Path": "C:\\Windows\\System32\\SecurityHealthSystray.exe", + "SessionId": 2, + "Threads": 2, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --no-startup-window --win-session-start", + "CreateTime": "2025-03-06T17:51:05+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201826906304, + "PID": 3952, + "PPID": 4912, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 61, + "Wow64": false, + "__children": [ + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=renderer --string-annotations --instant-process --pdf-upsell-enabled --video-capture-use-gpu-memory-buffer --lang=en-US --js-flags=--ms-user-locale= --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=21 --time-ticks-at-unix-epoch=-1741283277737123 --launch-time-ticks=556708795 --always-read-main-dll --field-trial-handle=3928,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=3996 /prefetch:1", + "CreateTime": "2025-03-06T17:57:14+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201787768960, + "PID": 5348, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 19, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=edge_xpay_wallet.mojom.EdgeXPayWalletService --lang=en-US --service-sandbox-type=utility --string-annotations --always-read-main-dll --field-trial-handle=6740,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=6732 /prefetch:8", + "CreateTime": "2025-03-06T17:57:52+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201832050880, + "PID": 3876, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 8, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=edge_search_indexer.mojom.SearchIndexerInterfaceBroker --lang=en-US --service-sandbox-type=search_indexer --message-loop-type-ui --string-annotations --always-read-main-dll --field-trial-handle=7016,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=7128 /prefetch:8", + "CreateTime": "2025-03-06T17:57:59+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201827619008, + "PID": 5604, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 14, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=entity_extraction_service.mojom.Extractor --lang=en-US --service-sandbox-type=entity_extraction --onnx-enabled-for-ee --string-annotations --always-read-main-dll --field-trial-handle=5520,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=5608 /prefetch:8", + "CreateTime": "2025-03-06T17:57:16+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201827774656, + "PID": 1000, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 9, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=renderer --string-annotations --pdf-upsell-enabled --disable-gpu-compositing --video-capture-use-gpu-memory-buffer --lang=en-US --js-flags=--ms-user-locale= --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=31 --time-ticks-at-unix-epoch=-1741283277737123 --launch-time-ticks=596993509 --always-read-main-dll --field-trial-handle=6904,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=7092 /prefetch:1", + "CreateTime": "2025-03-06T17:57:54+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201839592000, + "PID": 7080, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 15, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=renderer --string-annotations --pdf-upsell-enabled --disable-gpu-compositing --video-capture-use-gpu-memory-buffer --lang=en-US --js-flags=--ms-user-locale= --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=35 --time-ticks-at-unix-epoch=-1741283277737123 --launch-time-ticks=625057436 --always-read-main-dll --field-trial-handle=5592,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=5688 /prefetch:1", + "CreateTime": "2025-03-06T17:58:23+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201828201216, + "PID": 5132, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 17, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=renderer --string-annotations --pdf-upsell-enabled --disable-gpu-compositing --video-capture-use-gpu-memory-buffer --lang=en-US --js-flags=--ms-user-locale= --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=36 --time-ticks-at-unix-epoch=-1741283277737123 --launch-time-ticks=625148972 --always-read-main-dll --field-trial-handle=7112,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=6396 /prefetch:1", + "CreateTime": "2025-03-06T17:58:23+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201839919232, + "PID": 5388, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 15, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --string-annotations --always-read-main-dll --field-trial-handle=2180,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=2512 /prefetch:3", + "CreateTime": "2025-03-06T17:51:14+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201835704512, + "PID": 6448, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 16, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:51:16+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201668321408, + "PID": 6672, + "PPID": 3952, + "Path": null, + "SessionId": 2, + "Threads": 9, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=price_comparison_service.mojom.DataProcessor --lang=en-US --service-sandbox-type=entity_extraction --string-annotations --always-read-main-dll --field-trial-handle=6188,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=6580 /prefetch:8", + "CreateTime": "2025-03-06T17:58:44+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201830273728, + "PID": 6064, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 9, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=gpu-process --string-annotations --gpu-preferences=UAAAAAAAAADgAAAEAAAAAAAAAAAAAAAAAABgAAEAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAA --always-read-main-dll --field-trial-handle=2472,i,15721868202469256575,6833569417170289141,262144 --variations-seed-version --mojo-platform-channel-handle=2468 /prefetch:2", + "CreateTime": "2025-03-06T17:51:14+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201834049728, + "PID": 6456, + "PPID": 3952, + "Path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "SessionId": 2, + "Threads": 15, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:51:11+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "msedge.exe", + "Offset(V)": 145201786340096, + "PID": 6204, + "PPID": 3952, + "Path": null, + "SessionId": 2, + "Threads": 8, + "Wow64": false, + "__children": [] + } + ] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Users\\generic-user\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe", + "Cmd": "\"C:\\Users\\generic-user\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe\" /background", + "CreateTime": "2025-03-06T17:51:11+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "OneDrive.exe", + "Offset(V)": 145201834340544, + "PID": 6160, + "PPID": 4912, + "Path": "C:\\Users\\generic-user\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe", + "SessionId": 2, + "Threads": 22, + "Wow64": true, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\cmd.exe", + "Cmd": "\"C:\\Windows\\system32\\cmd.exe\" ", + "CreateTime": "2025-03-06T17:51:44+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "cmd.exe", + "Offset(V)": 145201834332288, + "PID": 784, + "PPID": 4912, + "Path": "C:\\Windows\\system32\\cmd.exe", + "SessionId": 2, + "Threads": 1, + "Wow64": false, + "__children": [ + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\conhost.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:51:49+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "conhost.exe", + "Offset(V)": 145201834446976, + "PID": 3896, + "PPID": 784, + "Path": null, + "SessionId": 2, + "Threads": 3, + "Wow64": false, + "__children": [] + } + ] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\notepad.exe", + "Cmd": "\"C:\\Windows\\system32\\notepad.exe\" ", + "CreateTime": "2025-03-06T17:52:33+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "notepad.exe", + "Offset(V)": 145201839497344, + "PID": 2968, + "PPID": 4912, + "Path": "C:\\Windows\\system32\\notepad.exe", + "SessionId": 2, + "Threads": 4, + "Wow64": false, + "__children": [] + } + ] + } + ] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\fontdrvhost.exe", + "Cmd": null, + "CreateTime": "2025-03-06T17:49:42+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "fontdrvhost.ex", + "Offset(V)": 145201770697088, + "PID": 3812, + "PPID": 3616, + "Path": null, + "SessionId": 2, + "Threads": 5, + "Wow64": false, + "__children": [] + }, + { + "Audit": "\\Device\\HarddiskVolume4\\Windows\\System32\\dwm.exe", + "Cmd": "\"dwm.exe\"", + "CreateTime": "2025-03-06T17:49:42+00:00", + "ExitTime": null, + "Handles": null, + "ImageFileName": "dwm.exe", + "Offset(V)": 145201770352768, + "PID": 3860, + "PPID": 3616, + "Path": "C:\\Windows\\system32\\dwm.exe", + "SessionId": 2, + "Threads": 16, + "Wow64": false, + "__children": [] + } + ] + } +} diff --git a/test/plugins/windows/test_data/windows.registry.hivescan.HiveScan.json b/test/plugins/windows/test_data/windows.registry.hivescan.HiveScan.json new file mode 100644 index 000000000..67d36af04 --- /dev/null +++ b/test/plugins/windows/test_data/windows.registry.hivescan.HiveScan.json @@ -0,0 +1,100 @@ +{ + "WINDOWS10_GENERIC": [ + { + "Offset": 213323072327680, + "__children": [] + }, + { + "Offset": 213323069669376, + "__children": [] + }, + { + "Offset": 213323011252224, + "__children": [] + }, + { + "Offset": 213322964488192, + "__children": [] + }, + { + "Offset": 213323011387392, + "__children": [] + }, + { + "Offset": 213322962362368, + "__children": [] + }, + { + "Offset": 213323041546240, + "__children": [] + }, + { + "Offset": 213323013046272, + "__children": [] + }, + { + "Offset": 213323061571584, + "__children": [] + }, + { + "Offset": 213323079548928, + "__children": [] + }, + { + "Offset": 213323067502592, + "__children": [] + }, + { + "Offset": 213323081900032, + "__children": [] + }, + { + "Offset": 213322954362880, + "__children": [] + }, + { + "Offset": 213322954346496, + "__children": [] + }, + { + "Offset": 213323014123520, + "__children": [] + }, + { + "Offset": 213323067707392, + "__children": [] + }, + { + "Offset": 213323070193664, + "__children": [] + }, + { + "Offset": 213323078791168, + "__children": [] + }, + { + "Offset": 213323069112320, + "__children": [] + }, + { + "Offset": 213323047776256, + "__children": [] + }, + { + "Offset": 213323013799936, + "__children": [] + }, + { + "Offset": 213322954985472, + "__children": [] + }, + { + "Offset": 213322954969088, + "__children": [] + }, + { + "Offset": 213323048636416, + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.registry.printkey.PrintKey.json b/test/plugins/windows/test_data/windows.registry.printkey.PrintKey.json new file mode 100644 index 000000000..ee069ec30 --- /dev/null +++ b/test/plugins/windows/test_data/windows.registry.printkey.PrintKey.json @@ -0,0 +1,61 @@ +{ + "WINDOWS10_GENERIC": [ + { + "Data": "", + "Hive Offset": 213322954346496, + "Key": "[NONAME]", + "Last Write Time": "2025-03-06T17:59:19+00:00", + "Name": "A", + "Type": "Key", + "Volatile": false + }, + { + "Data": "", + "Hive Offset": 213322954362880, + "Key": "\\REGISTRY\\MACHINE\\SYSTEM", + "Last Write Time": "2019-12-07T09:15:07+00:00", + "Name": "ControlSet001", + "Type": "Key", + "Volatile": false + }, + { + "Data": "", + "Hive Offset": 213322964488192, + "Key": "\\SystemRoot\\System32\\Config\\SOFTWARE", + "Last Write Time": "2025-03-06T17:38:01+00:00", + "Name": "Classes", + "Type": "Key", + "Volatile": false + }, + { + "Data": "", + "Hive Offset": 213323011252224, + "Key": "\\SystemRoot\\System32\\Config\\SAM", + "Last Write Time": "2025-01-31T13:01:49+00:00", + "Name": "SAM", + "Type": "Key", + "Volatile": false, + "__children": [] + }, + { + "Data": "", + "Hive Offset": 213323048636416, + "Key": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Last Write Time": "2025-03-06T17:50:04+00:00", + "Name": "SOFTWARE", + "Type": "Key", + "Volatile": false, + "__children": [] + }, + { + "Data": "", + "Hive Offset": 213323047776256, + "Key": "\\??\\C:\\Users\\generic-user\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat", + "Last Write Time": "2025-03-05T18:36:09+00:00", + "Name": ".eip", + "Type": "Key", + "Volatile": false, + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.registry.userassist.UserAssist.json b/test/plugins/windows/test_data/windows.registry.userassist.UserAssist.json new file mode 100644 index 000000000..6ae740822 --- /dev/null +++ b/test/plugins/windows/test_data/windows.registry.userassist.UserAssist.json @@ -0,0 +1,123 @@ +{ + "WINDOWS10_GENERIC": { + "Count": null, + "Focus Count": null, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": null, + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": null, + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "", + "Time Focused": null, + "Type": "Key", + "__children": [ + { + "Count": 7, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-05T18:34:13+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Accessories\\Paint.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 07 00 00 00 00 00 00 00 07 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff 90 86 6b 31 ..............k1\nfd 8d db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.507000", + "Type": "Value", + "__children": [] + }, + { + "Count": 1, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T12:46:34+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Administrative Tools\\Registry Editor.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff f0 82 cf ca ................\n95 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.501000", + "Type": "Value", + "__children": [] + }, + { + "Count": 4, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T17:36:33+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Windows PowerShell\\Windows PowerShell.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 04 00 00 00 00 00 00 00 04 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff 10 67 cf 4d .............g.M\nbe 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.504000", + "Type": "Value", + "__children": [] + }, + { + "Count": 1, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T17:51:44+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\System Tools\\Command Prompt.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff d0 99 66 6c ..............fl\nc0 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.501000", + "Type": "Value", + "__children": [] + }, + { + "Count": 1, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T17:52:33+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Accessories\\Notepad.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff 00 62 ba 89 .............b..\nc0 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.501000", + "Type": "Value", + "__children": [] + }, + { + "Count": 2, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T17:56:50+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Administrative Tools\\Task Scheduler.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff b0 24 49 23 .............$I#\nc1 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.502000", + "Type": "Value", + "__children": [] + }, + { + "Count": 1, + "Focus Count": 0, + "Hive Name": "\\??\\C:\\Users\\generic-user\\ntuser.dat", + "Hive Offset": 213323048636416, + "ID": null, + "Last Updated": "2025-03-06T17:57:09+00:00", + "Last Write Time": "2025-03-06T17:57:09+00:00", + "Name": "%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Microsoft Edge.lnk", + "Path": "ntuser.dat\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count", + "Raw Data": "\"\n00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf 00 00 80 bf 00 00 80 bf ................\n00 00 80 bf 00 00 80 bf ff ff ff ff 60 3d 89 2e ............`=..\nc1 8e db 01 00 00 00 00 ........ \"", + "Time Focused": "0:00:00.501000", + "Type": "Value", + "__children": [] + } + ] + } +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.sessions.Sessions.json b/test/plugins/windows/test_data/windows.sessions.Sessions.json new file mode 100644 index 000000000..30b202adb --- /dev/null +++ b/test/plugins/windows/test_data/windows.sessions.Sessions.json @@ -0,0 +1,36 @@ +{ + "WINDOWS10_GENERIC": [ + { + "Create Time": "2025-03-06T17:48:02+00:00", + "Process": "System", + "Process ID": 4 + }, + { + "Create Time": "2025-03-06T17:48:37+00:00", + "Process": "lsass.exe", + "Process ID": 696, + "Session ID": 0, + "Session Type": null, + "User Name": "/SYSTEM", + "__children": [] + }, + { + "Create Time": "2025-03-06T17:49:03+00:00", + "Process": "MsMpEng.exe", + "Process ID": 1956, + "Session ID": 0, + "Session Type": null, + "User Name": "WORKGROUP/Windows-generic$", + "__children": [] + }, + { + "Create Time": "2025-03-06T17:50:08+00:00", + "Process": "rdpclip.exe", + "Process ID": 4180, + "Session ID": 2, + "Session Type": null, + "User Name": "Windows-generic/generic-user", + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.shimcachemem.ShimcacheMem.json b/test/plugins/windows/test_data/windows.shimcachemem.ShimcacheMem.json new file mode 100644 index 000000000..b671f4c4b --- /dev/null +++ b/test/plugins/windows/test_data/windows.shimcachemem.ShimcacheMem.json @@ -0,0 +1,41 @@ +{ + "WINDOWS10_GENERIC": + [ + { + "Exec Flag": null, + "File Path": "C:\\Windows\\System32\\cmdl32.exe", + "File Size": null, + "Last Modified": "2019-12-07T09:09:07+00:00", + "Last Update": null, + "Order": 0, + "__children": [] + }, + { + "Exec Flag": null, + "File Path": "C:\\Windows\\System32\\cmdkey.exe", + "File Size": null, + "Last Modified": "2019-12-07T09:09:09+00:00", + "Last Update": null, + "Order": 1, + "__children": [] + }, + { + "Exec Flag": null, + "File Path": "C:\\Windows\\system32\\whoami.exe", + "File Size": null, + "Last Modified": "2019-12-07T09:09:51+00:00", + "Last Update": null, + "Order": 2, + "__children": [] + }, + { + "Exec Flag": null, + "File Path": null, + "File Size": null, + "Last Modified": "2023-12-13T16:43:28+00:00", + "Last Update": null, + "Order": 3, + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.timers.Timers.json b/test/plugins/windows/test_data/windows.timers.Timers.json new file mode 100644 index 000000000..88e8f339a --- /dev/null +++ b/test/plugins/windows/test_data/windows.timers.Timers.json @@ -0,0 +1,684 @@ +{ + "WINDOWSXP_GENERIC": [ + { + "DueTime": "0x00000001:0xb6912640", + "Module": "ntoskrnl", + "Offset": 2180960760, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xe2e5d9fc", + "Module": "ks", + "Offset": 2181100944, + "Period(ms)": 0, + "Routine": 4162614588, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000001:0x838d66d0", + "Module": "ntoskrnl", + "Offset": 2180726816, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xbe54efd0", + "Module": "NDIS", + "Offset": 2182586488, + "Period(ms)": 60000, + "Routine": 4164630316, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000000:0x6d915dc0", + "Module": "ntoskrnl", + "Offset": 2182771520, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xd5616870", + "Module": "HTTP", + "Offset": 4122586976, + "Period(ms)": 0, + "Routine": 4122527634, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa92535f", + "Module": "USBPORT", + "Offset": 2179614512, + "Period(ms)": 0, + "Routine": 4163343596, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000000:0x28ec7d80", + "Module": "ntoskrnl", + "Offset": 2167895896, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xd5f1ddd0", + "Module": "afd", + "Offset": 4289149728, + "Period(ms)": 0, + "Routine": 4146614848, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xe64e9c50", + "Module": "ntoskrnl", + "Offset": 4289091536, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000002:0x10691f50", + "Module": "BATTC", + "Offset": 2182647568, + "Period(ms)": 0, + "Routine": 4170619626, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000002:0x10691f50", + "Module": "BATTC", + "Offset": 2184852912, + "Period(ms)": 0, + "Routine": 4170619626, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xe650bd40", + "Module": "ntoskrnl", + "Offset": 4289091352, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xaf39aa70", + "Module": "watchdog", + "Offset": 2182133296, + "Period(ms)": 10000, + "Routine": 4170290884, + "Signaled": "Yes", + "Symbol": "_imp__KdSave", + "__children": [] + }, + { + "DueTime": "0x00000001:0xaf39aa70", + "Module": "watchdog", + "Offset": 2181849992, + "Period(ms)": 10000, + "Routine": 4170290884, + "Signaled": "Yes", + "Symbol": "_imp__KdSave", + "__children": [] + }, + { + "DueTime": "0x00000008:0x61e17090", + "Module": "ntoskrnl", + "Offset": 2153125248, + "Period(ms)": 0, + "Routine": 2152824977, + "Signaled": "-", + "Symbol": "ExpTimeRefreshDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xa9537f40", + "Module": "ntoskrnl", + "Offset": 2153083360, + "Period(ms)": 0, + "Routine": 2152814203, + "Signaled": "-", + "Symbol": "CmpLazyFlushDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xc5addbe0", + "Module": "TDI", + "Offset": 4147138000, + "Period(ms)": 0, + "Routine": 4169831408, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaadb3be0", + "Module": "netbt", + "Offset": 2182155920, + "Period(ms)": 0, + "Routine": 4146697354, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaadb9040", + "Module": "TDI", + "Offset": 2182059040, + "Period(ms)": 0, + "Routine": 4169831408, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xa9537f40", + "Module": "ntoskrnl", + "Offset": 2153083360, + "Period(ms)": 0, + "Routine": 2152814203, + "Signaled": "-", + "Symbol": "CmpLazyFlushDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x80000000:0x19eae820", + "Module": "ntoskrnl", + "Offset": 2182169704, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa9b2a20", + "Module": "NDIS", + "Offset": 2179568032, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000002:0x1a97a160", + "Module": "Ntfs", + "Offset": 4164841808, + "Period(ms)": 0, + "Routine": 4164732734, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000000:0x2c5fb7e0", + "Module": "ntoskrnl", + "Offset": 2180369200, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000002:0x3dcf47a0", + "Module": "afd", + "Offset": 2183169664, + "Period(ms)": 0, + "Routine": 4146614848, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xc4906e60", + "Module": "rdbss", + "Offset": 4146422176, + "Period(ms)": 0, + "Routine": 4146381701, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa92535f", + "Module": "USBPORT", + "Offset": 2179614512, + "Period(ms)": 0, + "Routine": 4163343596, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa8619e0", + "Module": "TDI", + "Offset": 2182064136, + "Period(ms)": 0, + "Routine": 4169831408, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xc45ec240", + "Module": "tcpip", + "Offset": 4147157776, + "Period(ms)": 100, + "Routine": 4146861021, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000000:0x35b72850", + "Module": "ntoskrnl", + "Offset": 2180437784, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xaad6fab0", + "Module": "NDIS", + "Offset": 2181321392, + "Period(ms)": 1000, + "Routine": 4164630316, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaadb9040", + "Module": "TDI", + "Offset": 2182059040, + "Period(ms)": 0, + "Routine": 4169831408, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xa9537f40", + "Module": "ntoskrnl", + "Offset": 2153083360, + "Period(ms)": 0, + "Routine": 2152814203, + "Signaled": "-", + "Symbol": "CmpLazyFlushDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xe2e5ee70", + "Module": "ipsec", + "Offset": 4147285920, + "Period(ms)": 60000, + "Routine": 4147221715, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xe2e5ee70", + "Module": "ipsec", + "Offset": 4147284744, + "Period(ms)": 0, + "Routine": 4147221577, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xe2e5d9fc", + "Module": "ks", + "Offset": 2181100944, + "Period(ms)": 0, + "Routine": 4162614588, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000098:0xa67683e0", + "Module": "NDIS", + "Offset": 2183038120, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xa6beb810", + "Module": "ntoskrnl", + "Offset": 2153086208, + "Period(ms)": 1000, + "Routine": 2152611575, + "Signaled": "Yes", + "Symbol": "IopTimerDispatch", + "__children": [] + }, + { + "DueTime": "0x00000001:0xe2f53650", + "Module": "ipnat", + "Offset": 4146164320, + "Period(ms)": 60000, + "Routine": 4146134936, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000001:0x838d66d0", + "Module": "ntoskrnl", + "Offset": 2180726816, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xa6c34da0", + "Module": "ntoskrnl", + "Offset": 2153118912, + "Period(ms)": 1000, + "Routine": 2152615232, + "Signaled": "Yes", + "Symbol": "PopScanIdleList", + "__children": [] + }, + { + "DueTime": "0x00000098:0xa67683e0", + "Module": "NDIS", + "Offset": 2183038120, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xa6d41cb0", + "Module": "ntoskrnl", + "Offset": 2153080200, + "Period(ms)": 0, + "Routine": 2152616496, + "Signaled": "-", + "Symbol": "CcScanDpc", + "__children": [] + }, + { + "DueTime": "0x80000000:0x14500b10", + "Module": "ntoskrnl", + "Offset": 2182113448, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xaba81b20", + "Module": "NDIS", + "Offset": 2182656416, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xab110bd0", + "Module": "ntoskrnl", + "Offset": 2181090272, + "Period(ms)": 0, + "Routine": 2152754200, + "Signaled": "-", + "Symbol": "CcPfTraceTimerRoutine", + "__children": [] + }, + { + "DueTime": "0x00000098:0xa6ad86a0", + "Module": "NDIS", + "Offset": 2182615456, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xd56a01e0", + "Module": "HTTP", + "Offset": 4122576520, + "Period(ms)": 60000, + "Routine": 4122481076, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xd56a7ca0", + "Module": "HTTP", + "Offset": 4122577120, + "Period(ms)": 30000, + "Routine": 4122510208, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xd56a7ca0", + "Module": "HTTP", + "Offset": 4122586816, + "Period(ms)": 0, + "Routine": 4122536296, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x80000000:0x14500b10", + "Module": "ntoskrnl", + "Offset": 2182113448, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000002:0x10691f50", + "Module": "BATTC", + "Offset": 2184852912, + "Period(ms)": 0, + "Routine": 4170619626, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000002:0x10691f50", + "Module": "BATTC", + "Offset": 2182647568, + "Period(ms)": 0, + "Routine": 4170619626, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa90b010", + "Module": "sr", + "Offset": 2184659528, + "Period(ms)": 0, + "Routine": 4165384494, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000131:0x3cf80b10", + "Module": "NDIS", + "Offset": 2181526704, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa9b2a20", + "Module": "NDIS", + "Offset": 2179568032, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa9cb150", + "Module": "NDIS", + "Offset": 2179569720, + "Period(ms)": 0, + "Routine": 4164628447, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa9e70c0", + "Module": "ntoskrnl", + "Offset": 2182248232, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xd56bd340", + "Module": "srv", + "Offset": 4128143248, + "Period(ms)": 0, + "Routine": 4128080773, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xbae86a40", + "Module": "ntoskrnl", + "Offset": 2182222184, + "Period(ms)": 0, + "Routine": 2152618407, + "Signaled": "-", + "Symbol": "ExpTimerDpcRoutine", + "__children": [] + }, + { + "DueTime": "0x00000001:0xacafcdd0", + "Module": "Ntfs", + "Offset": 4164841712, + "Period(ms)": 0, + "Routine": 4164719155, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaa92535f", + "Module": "USBPORT", + "Offset": 2179614512, + "Period(ms)": 0, + "Routine": 4163343596, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xad54f9d0", + "Module": "ntoskrnl", + "Offset": 2153085904, + "Period(ms)": 60000, + "Routine": 2152638914, + "Signaled": "Yes", + "Symbol": "IopIrpStackProfilerTimer", + "__children": [] + }, + { + "DueTime": "0x00000008:0x73b44670", + "Module": "ipsec", + "Offset": 4147284848, + "Period(ms)": 0, + "Routine": 4147221577, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaad6c270", + "Module": "NDIS", + "Offset": 2179663392, + "Period(ms)": 0, + "Routine": 4164642677, + "Signaled": "-", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000001:0xaad6fab0", + "Module": "NDIS", + "Offset": 2181321392, + "Period(ms)": 1000, + "Routine": 4164630316, + "Signaled": "Yes", + "Symbol": null, + "__children": [] + }, + { + "DueTime": "0x00000008:0x73bef8c0", + "Module": "netbt", + "Offset": 2182155520, + "Period(ms)": 0, + "Routine": 4146697354, + "Signaled": "-", + "Symbol": null, + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.unloadedmodules.UnloadedModules.json b/test/plugins/windows/test_data/windows.unloadedmodules.UnloadedModules.json new file mode 100644 index 000000000..e287d3c14 --- /dev/null +++ b/test/plugins/windows/test_data/windows.unloadedmodules.UnloadedModules.json @@ -0,0 +1,67 @@ +{ + "WINDOWS10_GENERIC": [ + { + "EndAddress": 18446735295750344704, + "Name": "hwpolicy.sys", + "StartAddress": 18446735295750275072, + "Time": "2025-03-06T17:47:55+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295728652288, + "Name": "WdBoot.sys", + "StartAddress": 18446735295728582656, + "Time": "2025-03-06T17:47:56+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295786053632, + "Name": "dam.sys", + "StartAddress": 18446735295785926656, + "Time": "2025-03-06T17:48:02+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295788797952, + "Name": "serial.sys", + "StartAddress": 18446735295788679168, + "Time": "2025-03-06T17:48:21+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295788875776, + "Name": "serenum.sys", + "StartAddress": 18446735295788810240, + "Time": "2025-03-06T17:48:21+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295761932288, + "Name": "dump_dumpfve.sys", + "StartAddress": 18446735295761809408, + "Time": "2025-03-06T17:48:27+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295761629184, + "Name": "dump_vmbkmcl.sys", + "StartAddress": 18446735295761481728, + "Time": "2025-03-06T17:48:27+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295761481728, + "Name": "dump_storvsc.sys", + "StartAddress": 18446735295761416192, + "Time": "2025-03-06T17:48:27+00:00", + "__children": [] + }, + { + "EndAddress": 18446735295761350656, + "Name": "dump_storport.sys", + "StartAddress": 18446735295761285120, + "Time": "2025-03-06T17:48:27+00:00", + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.vadinfo.VadInfo.json b/test/plugins/windows/test_data/windows.vadinfo.VadInfo.json new file mode 100644 index 000000000..d980b21a2 --- /dev/null +++ b/test/plugins/windows/test_data/windows.vadinfo.VadInfo.json @@ -0,0 +1,94 @@ +{ + "WINDOWS10_GENERIC": [ + { + "CommitCharge": 1, + "End VPN": 2147381247, + "File": null, + "File output": "Disabled", + "Offset": 18446607800399740208, + "PID": 4, + "Parent": 0, + "PrivateMemory": 1, + "Process": "System", + "Protection": "PAGE_READONLY", + "Start VPN": 2147377152, + "Tag": "VadS", + "__children": [] + }, + { + "CommitCharge": 1, + "End VPN": 2147356671, + "File": null, + "File output": "Disabled", + "Offset": 18446607800399739968, + "PID": 4, + "Parent": 18446607800399740208, + "PrivateMemory": 1, + "Process": "System", + "Protection": "PAGE_READONLY", + "Start VPN": 2147352576, + "Tag": "VadS", + "__children": [] + }, + { + "CommitCharge": 9, + "End VPN": 2004303871, + "File": "\\Windows\\SysWOW64\\ntdll.dll", + "File output": "Disabled", + "Offset": 18446607800410763840, + "PID": 4, + "Parent": 18446607800399739968, + "PrivateMemory": 0, + "Process": "System", + "Protection": "PAGE_EXECUTE_WRITECOPY", + "Start VPN": 2002583552, + "Tag": "Vad ", + "__children": [] + }, + { + "CommitCharge": 9, + "End VPN": 140703785033727, + "File": "\\Windows\\System32\\vertdll.dll", + "File output": "Disabled", + "Offset": 18446607800410768000, + "PID": 4, + "Parent": 18446607800399740208, + "PrivateMemory": 0, + "Process": "System", + "Protection": "PAGE_EXECUTE_WRITECOPY", + "Start VPN": 140703784828928, + "Tag": "Vad ", + "__children": [] + }, + { + "CommitCharge": 0, + "End VPN": 2873390796799, + "File": null, + "File output": "Disabled", + "Offset": 18446607800474375600, + "PID": 4, + "Parent": 18446607800410768000, + "PrivateMemory": 0, + "Process": "System", + "Protection": "PAGE_READWRITE", + "Start VPN": 2873390792704, + "Tag": "Vad ", + "__children": [] + }, + { + "CommitCharge": 16, + "End VPN": 140703787155455, + "File": "\\Windows\\System32\\ntdll.dll", + "File output": "Disabled", + "Offset": 18446607800410767520, + "PID": 4, + "Parent": 18446607800410768000, + "PrivateMemory": 0, + "Process": "System", + "Protection": "PAGE_EXECUTE_WRITECOPY", + "Start VPN": 140703785091072, + "Tag": "Vad ", + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.vadwalk.VadWalk.json b/test/plugins/windows/test_data/windows.vadwalk.VadWalk.json new file mode 100644 index 000000000..d7c884fca --- /dev/null +++ b/test/plugins/windows/test_data/windows.vadwalk.VadWalk.json @@ -0,0 +1,76 @@ +{ + "WINDOWS10_GENERIC": [ + { + "End": 2147381247, + "Left": 145201666899008, + "Offset": 145201666899248, + "PID": 4, + "Parent": 0, + "Process": "System", + "Right": 145201677927040, + "Start": 2147377152, + "Tag": "VadS", + "__children": [] + }, + { + "End": 2147356671, + "Left": 145201677922880, + "Offset": 145201666899008, + "PID": 4, + "Parent": 145201666899248, + "Process": "System", + "Right": 0, + "Start": 2147352576, + "Tag": "VadS", + "__children": [] + }, + { + "End": 2004303871, + "Left": 0, + "Offset": 145201677922880, + "PID": 4, + "Parent": 145201666899008, + "Process": "System", + "Right": 0, + "Start": 2002583552, + "Tag": "Vad ", + "__children": [] + }, + { + "End": 140703785033727, + "Left": 145201741534640, + "Offset": 145201677927040, + "PID": 4, + "Parent": 145201666899248, + "Process": "System", + "Right": 145201677926560, + "Start": 140703784828928, + "Tag": "Vad ", + "__children": [] + }, + { + "End": 2873390796799, + "Left": 0, + "Offset": 145201741534640, + "PID": 4, + "Parent": 145201677927040, + "Process": "System", + "Right": 0, + "Start": 2873390792704, + "Tag": "Vad ", + "__children": [] + }, + { + "End": 140703787155455, + "Left": 0, + "Offset": 145201677926560, + "PID": 4, + "Parent": 145201677927040, + "Process": "System", + "Right": 0, + "Start": 140703785091072, + "Tag": "Vad ", + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/test_data/windows.virtmap.VirtMap.json b/test/plugins/windows/test_data/windows.virtmap.VirtMap.json new file mode 100644 index 000000000..6b80068f2 --- /dev/null +++ b/test/plugins/windows/test_data/windows.virtmap.VirtMap.json @@ -0,0 +1,82 @@ +{ + "WINDOWS10_GENERIC": [ + { + "End offset": 17592186044416, + "Region": "MiVaBootLoaded", + "Start offset": 238594023227392, + "__children": [] + }, + { + "End offset": 549755813888, + "Region": "MiVaDriverImages", + "Start offset": 272678883688448, + "__children": [] + }, + { + "End offset": 549755813888, + "Region": "MiVaHal", + "Start offset": 258385232527360, + "__children": [] + }, + { + "End offset": 3848290697216, + "Region": "MiVaNonPagedPool", + "Start offset": 266081813921792, + "__children": [] + }, + { + "End offset": 2748779069440, + "Region": "MiVaPagedPool", + "Start offset": 278135644927560, + "__children": [] + }, + { + "End offset": 17592186044416, + "Region": "MiVaPfnDatabase", + "Start offset": 166026255794176, + "__children": [] + }, + { + "End offset": 17592186044416, + "Region": "MiVaProcessSpace", + "Start offset": 191315023233024, + "__children": [] + }, + { + "End offset": 549755813888, + "Region": "MiVaSessionGlobalSpace", + "Start offset": 186367220908032, + "__children": [] + }, + { + "End offset": 17592186044416, + "Region": "MiVaSessionSpace", + "Start offset": 213305255788544, + "__children": [] + }, + { + "End offset": 1099511627776, + "Region": "MiVaSpecialPoolPaged", + "Start offset": 261683767410688, + "__children": [] + }, + { + "End offset": 1099511627776, + "Region": "MiVaSystemCache", + "Start offset": 208907209277440, + "__children": [] + }, + { + "End offset": 549755813888, + "Region": "MiVaSystemPtes", + "Start offset": 274328151130112, + "__children": [] + }, + { + "End offset": 17592186044416, + "Region": "MiVaUnused", + "Start offset": 145135534866432, + "__children": [] + } + ] +} \ No newline at end of file diff --git a/test/plugins/windows/windows.py b/test/plugins/windows/windows.py index f07c8b20c..c9cf93391 100644 --- a/test/plugins/windows/windows.py +++ b/test/plugins/windows/windows.py @@ -10,7 +10,7 @@ from test import test_volatility, WindowsSamples class TestWindowsVolshell: def test_windows_volshell(self, image, volatility, python): out = test_volatility.basic_volshell_test( - image, volatility, python, globalargs=("-w",) + image, volatility, python, volshellargs=("-w",) ) assert out.count(b" 40 @@ -60,7 +60,8 @@ class TestWindowsPslist: class TestWindowsPsscan: - def test_windows_generic_psscan(self, volatility, python, image): + def test_windows_specific_psscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( "windows.psscan.PsScan", image, volatility, python ) @@ -75,40 +76,66 @@ class TestWindowsPsscan: class TestWindowsDlllist: def test_windows_generic_dlllist(self, volatility, python, image): rc, out, _err = test_volatility.runvol_plugin( - "windows.dlllist.DllList", image, volatility, python + "windows.dlllist.DllList", + image, + volatility, + python, + globalargs=("-r", "json"), ) assert rc == 0 - out = out.lower() - assert out.count(b"\n") > 10 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 2000 + expected_rows = [ + { + "Path": "C:\\Windows\\SYSTEM32\\kernel32.dll", + "Process": "csrss.exe", + }, + { + "Path": "C:\\Windows\\system32\\USER32.dll", + "Process": "csrss.exe", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row( + expected_row, json_out, case_sensitive=False + ) class TestWindowsModules: - def test_windows_generic_modules(self, volatility, python, image): + def test_windows_specific_modules(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( - "windows.modules.Modules", image, volatility, python + "windows.modules.Modules", + image, + volatility, + python, + globalargs=("-r", "json"), ) assert rc == 0 - out = out.lower() - assert out.count(b"\n") > 10 - - -class TestWindowsHivelist: - def test_windows_generic_hivelist(self, volatility, python, image): - rc, out, _err = test_volatility.runvol_plugin( - "windows.registry.hivelist.HiveList", image, volatility, python - ) - assert rc == 0 - out = out.lower() - - not_xp = out.find(b"\\systemroot\\system32\\config\\software") - if not_xp == -1: - assert ( - out.find( - b"\\device\\harddiskvolume1\\windows\\system32\\config\\software" - ) - != -1 - ) - assert out.count(b"\n") > 10 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 110 + expected_rows = [ + { + "Name": "ntoskrnl.exe", + "Offset": 2185216944, + "Path": "\\WINDOWS\\system32\\ntoskrnl.exe", + "Size": 2179328, + }, + { + "Name": "hal.dll", + "Offset": 2185216840, + "Path": "\\WINDOWS\\system32\\hal.dll", + "Size": 81280, + }, + { + "Name": "netbios.sys", + "Offset": 2182050616, + "Path": "\\SystemRoot\\System32\\DRIVERS\\netbios.sys", + "Size": 36864, + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) class TestWindowsDumpfiles: @@ -173,22 +200,57 @@ class TestWindowsHandles: assert out.count(b"\n") > 500 -class TestWindowsSvcscan: - def test_windows_generic_svcscan(self, volatility, python, image): +class TestWindowsSvcList: + def test_windows_generic_svclist(self, volatility, python, image): + image = WindowsSamples.WINDOWS10_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( - "windows.svcscan.SvcScan", image, volatility, python + "windows.svclist.SvcList", + image, + volatility, + python, + globalargs=("-r", "json"), ) assert rc == 0 - assert out.find(b"Microsoft ACPI Driver") != -1 - assert out.count(b"\n") > 250 + json_out = json.loads(out) + assert len(json_out) > 250 + expected_row = { + "Binary": "\\Driver\\ACPI", + "Display": "ACPI", + "Name": "ACPI", + "Start": "SERVICE_BOOT_START", + "State": "SERVICE_RUNNING", + "Type": "SERVICE_KERNEL_DRIVER", + } + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsSvcScan: + def test_windows_generic_svcscan(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.svcscan.SvcScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert len(json_out) > 250 + expected_rows = [ + {"Name": "ACPI", "Type": "SERVICE_KERNEL_DRIVER"}, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) class TestWindowsThrdscan: - def test_windows_generic_thrdscan(self, volatility, python, image): + def test_windows_specific_thrdscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( "windows.thrdscan.ThrdScan", image, volatility, python ) assert rc == 0 + assert out.count(b"\n") > 700 assert out.find(b"\t1812\t2768\t0x7c810856") != -1 assert out.find(b"\t840\t2964\t0x7c810856") != -1 assert out.find(b"\t2536\t2552\t0x7c810856") != -1 @@ -210,20 +272,47 @@ class TestWindowsPrivileges: assert out.count(b"\n") > 20 -class TestWindowsGetsids: +class TestWindowsGetSIDs: def test_windows_generic_getsids(self, volatility, python, image): rc, out, _err = test_volatility.runvol_plugin( "windows.getsids.GetSIDs", image, volatility, python, - pluginargs=("--pid", "4"), + globalargs=("-r", "json"), ) assert rc == 0 - assert out.find(b"Local System") != -1 - assert out.find(b"Administrators") != -1 - assert out.find(b"Everyone") != -1 - assert out.find(b"Authenticated Users") != -1 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 400 + expected_rows = [ + { + "Name": "Local System", + "Process": "csrss.exe", + "SID": "S-1-5-18", + }, + { + "Name": "Administrators", + "Process": "csrss.exe", + "SID": "S-1-5-32-544", + }, + { + "Name": "Everyone", + "Process": "csrss.exe", + "SID": "S-1-1-0", + }, + { + "Name": "Authenticated Users", + "Process": "csrss.exe", + "SID": "S-1-5-11", + }, + { + "Name": "System Mandatory Level", + "Process": "csrss.exe", + "SID": "S-1-16-16384", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) class TestWindowsEnvars: @@ -241,7 +330,8 @@ class TestWindowsEnvars: class TestWindowsCallbacks: - def test_windows_generic_callbacks(self, volatility, python, image): + def test_windows_specific_callbacks(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( "windows.callbacks.Callbacks", image, volatility, python ) @@ -253,20 +343,28 @@ class TestWindowsCallbacks: class TestWindowsVadwalk: - def test_windows_generic_vadwalk(self, volatility, python, image): + def test_windows_specific_vadwalk(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( - "windows.vadwalk.VadWalk", image, volatility, python + "windows.vadwalk.VadWalk", + image, + volatility, + python, + globalargs=("-r", "json"), + pluginargs=("--pid", "4"), ) assert rc == 0 - assert out.find(b"Vad") != -1 - assert out.find(b"VadS") != -1 - assert out.find(b"Vadl") != -1 - assert out.find(b"VadF") != -1 - assert out.find(b"0x0") != -1 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.vadwalk.VadWalk", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) class TestWindowsDevicetree: - def test_windows_generic_devicetree(self, volatility, python, image): + def test_windows_specific_devicetree(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path rc, out, _err = test_volatility.runvol_plugin( "windows.devicetree.DeviceTree", image, volatility, python ) @@ -324,3 +422,993 @@ class TestWindowsVadyarascan: ) assert rc == 0 assert out.count(b"\n") > 10 + + +class TestWindowsAmcache: + def test_windows_generic_amcache(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.amcache.Amcache", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 100 + # Win10+ expected package names + expected_rows = [ + { + "Path": "C:\\Windows\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy", + "ProductName": "Microsoft.Windows.StartMenuExperienceHost", + }, + { + "Path": "C:\\Windows\\SystemApps\\Microsoft.Windows.FileExplorer_cw5n1h2txyewy", + "ProductName": "c5e2524a-ea46-4f67-841f-6a9465d9d515", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsBigPools: + def test_windows_generic_bigpools(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.bigpools.BigPools", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 2000 + expected_rows = [ + { + "PoolType": "PagedPool", + }, + { + "PoolType": "PagedPoolCacheAligned", + }, + { + "PoolType": "NonPagedPoolNx", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +# FIXME: Empty on WIN10 and XP samples +# class TestWindowsCachedump: +# def test_windows_generic_cachedump(self, volatility, python, image): +# rc, out, _err = test_volatility.runvol_plugin( +# "windows.cachedump.Cachedump", +# image, +# volatility, +# python, +# globalargs=("-r", "json"), +# ) +# assert rc == 0 +# json_out = json.loads(out) + + +class TestWindowsCmdLine: + def test_windows_generic_cmdline(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.cmdline.CmdLine", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 20 + out = out.lower() + assert ( + out.find(b"C:\\Windows\\system32\\svchost.exe -k DcomLaunch -p".lower()) + != -1 + ) + assert ( + out.count( + b"C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -p".lower() + ) + > 3 + ) + + +class TestWindowsCmdScan: + def test_windows_specific_cmdscan(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.cmdscan.CmdScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + expected_row = { + "Process": "conhost.exe", + "Property": "_COMMAND_HISTORY", + } + assert test_volatility.match_output_row(expected_row, json.loads(out)) + + +class TestWindowsConsoles: + def test_windows_specific_consoles(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.consoles.Consoles", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + expected_row = { + "Process": "conhost.exe", + "Property": "_CONSOLE_INFORMATION", + } + assert test_volatility.match_output_row(expected_row, json.loads(out)) + + +class TestWindowsCrashinfo: + def test_windows_specific_crashinfo(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.crashinfo.Crashinfo", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + expected_row = { + "BitmapHeaderSize": 176128, + "BitmapPages": 511191, + "BitmapSize": 1310720, + "Comment": "PAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGEPAGE", + "DirectoryTableBase": 4610162688, + "DumpType": "Bitmap Dump (0x5)", + "MachineImageType": 34404, + "MajorVersion": 15, + "MinorVersion": 19041, + "NumberProcessors": 1, + "Signature": "PAGE", + "SystemTime": "2025-03-06T17:59:20+00:00", + "SystemUpTime": "0:11:23.199374", + "__children": [], + } + assert test_volatility.match_output_row(expected_row, json.loads(out)) + + +class TestWindowsDriverIrp: + def test_windows_specific_driverirp(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.driverirp.DriverIrp", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 2000 + assert out.count(b"ntoskrnl") > 400 + for irp in test_volatility.load_test_data( + "windows.driverirp.DriverIrp", "GENERIC" + ): + assert out.find(irp.encode()) != -1 + + +class TestWindowsDriverScan: + def test_windows_specific_driverscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.driverscan.DriverScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 50 + expected_rows = [ + { + "Name": "\\Driver\\ACPI_HAL", + "Service Key": "\\Driver\\ACPI_HAL", + }, + { + "Name": "\\Driver\\Tcpip", + "Service Key": "Tcpip", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsGetServiceSIDs: + def test_windows_generic_getservicesids(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.getservicesids.GetServiceSIDs", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"S-1-5-80-") > 90 + + +class TestWindowsIAT: + def test_windows_generic_iat(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.iat.IAT", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 2000 + expected_rows = [ + { + "Function": "NtTerminateProcess", + "Library": "ntdll.dll", + "Name": "csrss.exe", + }, + { + "Function": "RtlSetHeapInformation", + "Library": "ntdll.dll", + "Name": "csrss.exe", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsInfo: + def test_windows_specific_info(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.info.Info", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.info.Info", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsJobLinks: + def test_windows_specific_joblinks(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.joblinks.JobLinks", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 30 + expected_row = { + "Active": 1, + "JobLink": None, + "JobSess": 2, + "Name": "taskhostw.exe", + "Offset(V)": 145201782567040, + "PID": 4304, + "PPID": 1008, + "Process": "(Original Process)", + "Sess": 2, + "Term": 0, + "Total": 1, + "Wow64": False, + "__children": [ + { + "Active": 0, + "JobLink": "Yes", + "JobSess": 0, + "Name": "taskhostw.exe", + "Offset(V)": 145201782567040, + "PID": 4304, + "PPID": 1008, + "Process": "C:\\Windows\\system32\\taskhostw.exe", + "Sess": 2, + "Term": 0, + "Total": 0, + "Wow64": False, + "__children": [], + } + ], + } + + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsKPCRs: + def test_windows_generic_kpcrs(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.kpcrs.KPCRs", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + assert test_volatility.count_entries_flat(json.loads(out)) > 0 + + +class TestWindowsLdrModules: + def test_windows_specific_ldrmodules(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.ldrmodules.LdrModules", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 800 + out = out.lower() + assert out.find(b"\\Windows\\System32\\ntdll.dll".lower()) > 10 + + +class TestWindowsLsadump: + def test_windows_specific_lsadump(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.lsadump.Lsadump", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 5 + expected_row = { + "Hex": "01 00 00 00 2b 2b f1 09 a3 b3 4b af 02 19 5a 61 2f 09 3a 88 03 52 51 64 8a 6c d2 a8 34 07 cb 61 41 ca a4 5d f1 fb 4c e0 41 72 69 32", + "Key": "DPAPI_SYSTEM", + } + + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsMBRScan: + def test_windows_specific_mbrscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mbrscan.MBRScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 4300 + expected_rows = [ + { + "Bootcode MD5": "dbcef88b4d770658b0050bf20b2d3061", + "Disk Signature": "82-78-77-32", + "Full MBR MD5": "8eea93bb1c63863f6e7f95b084411672", + "Potential MBR at Physical Offset": 154029739, + }, + { + "Bootcode MD5": "591213a9dfef595735e419eff6eeb39d", + "Disk Signature": "7a-74-60-53", + "Full MBR MD5": "4e00711a5014941f5ad8b3a4cde69c9c", + "Potential MBR at Physical Offset": 437808348, + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsMemmap: + def test_windows_specific_memmap(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.memmap.Memmap", + image, + volatility, + python, + pluginargs=("--pid", "504"), + ) + assert rc == 0 + assert out.count(b"\n") > 12000 + + +class TestWindowsMFTscan: + def test_windows_specific_mftscan_ads_xp(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mftscan.ADS", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = [ + { + "ADS Filename": "Zone.Identifier", + "Filename": "libby_hoeler_part1.wmv", + "Hexdump": '"\n5b 5a 6f 6e 65 54 72 61 6e 73 66 65 72 5d 0d 0a [ZoneTransfer]..\n5a 6f 6e 65 49 64 3d 33 0d 0a ZoneId=3.. "', + "MFT Type": "DATA", + "Offset": 55926304, + "Record Number": 323, + "Record Type": "FILE", + }, + { + "ADS Filename": "Zone.Identifier", + "Filename": "NetZeroQuickHelpLite.exe", + "Hexdump": '"\n5b 5a 6f 6e 65 54 72 61 6e 73 66 65 72 5d 0d 0a [ZoneTransfer]..\n5a 6f 6e 65 49 64 3d 33 0d 0a ZoneId=3.. "', + "MFT Type": "DATA", + "Offset": 56102400, + "Record Number": 347, + "Record Type": "FILE", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + def test_windows_specific_mftscan_ads_win10(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mftscan.ADS", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = [ + { + "ADS Filename": "$Max", + "Filename": "$UsnJrnl", + "Hexdump": '"\n00 00 00 02 00 00 00 00 00 00 80 00 00 00 00 00 ................\nb9 dd f0 cc df 73 db 01 00 00 00 00 00 00 00 00 .....s.........."', + "MFT Type": "DATA", + "Offset": 1058018088, + "Record Number": 107240, + "Record Type": "FILE", + }, + { + "ADS Filename": "$Config", + "Filename": "$Repair", + "Hexdump": '"\n01 00 00 00 03 00 00 00 ........ "', + "MFT Type": "DATA", + "Offset": 5009678688, + "Record Number": 28, + "Record Type": "FILE", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + def test_windows_specific_mftscan_mftscan(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mftscan.MFTScan", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 15000 + assert out.count(b"STANDARD_INFORMATION") > 5000 + assert out.count(b"FILE_NAME") > 11000 + + def test_windows_specific_mftscan_residentdata_win10(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mftscan.ResidentData", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 850 + expected_rows = [ + { + "Filename": "index", + "Hexdump": '"\n30 5c 72 a7 1b 6d fb fc 09 00 00 00 00 00 00 00 0\\r..m..........\n00 00 00 00 00 00 00 00 ........ "', + "MFT Type": "DATA", + "Offset": 4961536280, + "Record Number": 116474, + "Record Type": "FILE", + }, + { + "Filename": "0.2.filtertrie.intermediate.txt", + "Hexdump": '"\n30 09 32 0d 0a 0.2.. "', + "MFT Type": "DATA", + "Offset": 619242944, + "Record Number": 113013, + "Record Type": "FILE", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsModScan: + def test_windows_generic_modscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.modscan.ModScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 90 + expected_rows = [ + { + "Name": "ntoskrnl.exe", + "Offset": 37733296, + "Path": "\\WINDOWS\\system32\\ntoskrnl.exe", + "Size": 2179328, + }, + { + "Name": "hal.dll", + "Offset": 37733192, + "Path": "\\WINDOWS\\system32\\hal.dll", + "Size": 81280, + }, + { + "Name": "netbios.sys", + "Offset": 34566968, + "Path": "\\SystemRoot\\System32\\DRIVERS\\netbios.sys", + "Size": 36864, + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsMutantScan: + def test_windows_specific_mutantscan(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.mutantscan.MutantScan", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 350 + + +class TestWindowsNetScan: + def test_windows_specific_netscan(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.netscan.NetScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 100 + expected_rows = [ + { + "Created": "2025-03-06T17:56:53+00:00", + "ForeignAddr": "13.107.246.254", + "ForeignPort": 443, + "LocalAddr": "10.0.0.4", + "LocalPort": 49929, + "Offset": 145201667934000, + "Owner": "SearchApp.exe", + "PID": 5644, + "Proto": "TCPv4", + "State": "CLOSE_WAIT", + }, + { + "Created": "2025-03-06T17:50:02+00:00", + "ForeignAddr": "168.63.129.16", + "ForeignPort": 80, + "LocalAddr": "10.0.0.4", + "LocalPort": 49689, + "Offset": 145201778694688, + "Owner": "WindowsAzureGu", + "PID": 1944, + "Proto": "TCPv4", + "State": "CLOSED", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsNetStat: + def test_windows_specific_netstat(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.netstat.NetStat", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 70 + expected_rows = [ + { + "Created": "2025-03-06T17:56:53+00:00", + "ForeignAddr": "13.107.246.254", + "ForeignPort": 443, + "LocalAddr": "10.0.0.4", + "LocalPort": 49929, + "Offset": 145201667934000, + "Owner": "SearchApp.exe", + "PID": 5644, + "Proto": "TCPv4", + "State": "CLOSE_WAIT", + }, + { + "Created": "2025-03-06T17:50:02+00:00", + "ForeignAddr": "168.63.129.16", + "ForeignPort": 80, + "LocalAddr": "10.0.0.4", + "LocalPort": 49688, + "Offset": 145201778506032, + "Owner": "WindowsAzureGu", + "PID": 1944, + "Proto": "TCPv4", + "State": "ESTABLISHED", + }, + ] + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsPESymbols: + def test_windows_specific_pe_symbols_processes(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.pe_symbols.PESymbols", + image, + volatility, + python, + globalargs=("-r", "json"), + pluginargs=( + "--source", + "processes", + "--module", + "ntdll.dll", + "--symbol", + "NtProtectVirtualMemory", + ), + ) + assert rc == 0 + expected_row = { + "Address": 2089868982, + "Module": "ntdll.dll", + "Symbol": "NtProtectVirtualMemory", + } + + assert test_volatility.match_output_row(expected_row, json.loads(out)) + + def test_windows_specific_pe_symbols_kernel(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.pe_symbols.PESymbols", + image, + volatility, + python, + globalargs=("-r", "json"), + pluginargs=( + "--source", + "kernel", + "--module", + "ntoskrnl.exe", + "--symbol", + "ZwOpenThread", + ), + ) + assert rc == 0 + expected_row = { + "Address": 2152583356, + "Module": "ntoskrnl.exe", + "Symbol": "ZwOpenThread", + } + + assert test_volatility.match_output_row(expected_row, json.loads(out)) + + +class TestWindowsPoolScanner: + def test_windows_specific_poolscanner(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.poolscanner.PoolScanner", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 4800 + assert out.find(b"_FILE_OBJECT") != -1 + assert out.find(b"_ETHREAD") != -1 + assert out.find(b"_RTL_ATOM_TABLE") != -1 + assert out.find(b"_KMUTANT") != -1 + + +class TestWindowsPsTree: + def test_windows_specific_pstree(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.pstree.PsTree", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 110 + expected_row = test_volatility.load_test_data( + "windows.pstree.PsTree", "WINDOWS10_GENERIC" + ) + + assert test_volatility.match_output_row( + expected_row, json_out, children_recursive=True + ) + + +class TestWindowsRegistry: + def test_windows_specific_registry_certificates(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.registry.certificates.Certificates", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 30 + expected_row = { + "Certificate ID": "ProtectedRoots", + "Certificate path": "Software\\Microsoft\\SystemCertificates", + "Certificate section": "Root", + } + assert test_volatility.match_output_row(expected_row, json_out) + + def test_windows_generic_registry_hivelist(self, volatility, python, image): + rc, out, _err = test_volatility.runvol_plugin( + "windows.registry.hivelist.HiveList", image, volatility, python + ) + assert rc == 0 + out = out.lower() + + not_xp = out.find(b"\\systemroot\\system32\\config\\software") + if not_xp == -1: + assert ( + out.find( + b"\\device\\harddiskvolume1\\windows\\system32\\config\\software" + ) + != -1 + ) + assert out.count(b"\n") > 10 + + def test_windows_specific_registry_hivescan(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.registry.hivescan.HiveScan", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.registry.hivescan.HiveScan", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + def test_windows_specific_registry_printkey(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.registry.printkey.PrintKey", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 450 + expected_rows = test_volatility.load_test_data( + "windows.registry.printkey.PrintKey", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + def test_windows_specific_registry_userassist(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.registry.userassist.UserAssist", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 35 + expected_row = test_volatility.load_test_data( + "windows.registry.userassist.UserAssist", "WINDOWS10_GENERIC" + ) + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsSessions: + def test_windows_specific_sessions(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.sessions.Sessions", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 115 + expected_rows = test_volatility.load_test_data( + "windows.sessions.Sessions", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsShimcacheMem: + def test_windows_specific_shimcachemem(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.shimcachemem.ShimcacheMem", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.shimcachemem.ShimcacheMem", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsSSDT: + def test_windows_specific_ssdt(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.ssdt.SSDT", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 770 + assert out.find(b"ntoskrnl") != -1 + assert out.find(b"Nt") != -1 + assert out.find(b"xHal") != -1 + + +class TestWindowsThreads: + def test_windows_specific_threads(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.threads.Threads", + image, + volatility, + python, + ) + assert rc == 0 + assert out.count(b"\n") > 1730 + + +class TestWindowsTimers: + def test_windows_specific_timers(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.timers.Timers", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.timers.Timers", "WINDOWSXP_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsVadInfo: + def test_windows_specific_vadinfo(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.vadinfo.VadInfo", + image, + volatility, + python, + globalargs=("-r", "json"), + pluginargs=("--pid", "4"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.vadinfo.VadInfo", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsVerInfo: + def test_windows_specific_verinfo(self, volatility, python): + image = WindowsSamples.WINDOWSXP_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.verinfo.VerInfo", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + assert test_volatility.count_entries_flat(json_out) > 125 + expected_row = { + "Base": 2152558592, + "Build": 2622, + "Major": 5, + "Minor": 1, + "Name": "ntoskrnl.exe", + "Product": 2600, + "__children": [], + } + assert test_volatility.match_output_row(expected_row, json_out) + + +class TestWindowsVirtMap: + def test_windows_specific_virtmap(self, volatility, python): + image = WindowsSamples.WINDOWS10_GENERIC.value.path + rc, out, _err = test_volatility.runvol_plugin( + "windows.virtmap.VirtMap", + image, + volatility, + python, + globalargs=("-r", "json"), + ) + assert rc == 0 + json_out = json.loads(out) + expected_rows = test_volatility.load_test_data( + "windows.virtmap.VirtMap", "WINDOWS10_GENERIC" + ) + for expected_row in expected_rows: + assert test_volatility.match_output_row(expected_row, json_out) + diff --git a/test/test_volatility.py b/test/test_volatility.py index 632a6bcde..9b7aff4be 100644 --- a/test/test_volatility.py +++ b/test/test_volatility.py @@ -11,8 +11,15 @@ import sys import tempfile import contextlib import functools +import json +import logging from typing import List, Tuple +from test import WINDOWS_TESTS_DATA_DIR + +test_logger = logging.getLogger(__name__) + + # # HELPER FUNCTIONS # @@ -55,9 +62,9 @@ def runvol_plugin( return runvol(args, volatility, python) -def runvolshell(img, volshell, python, volshellargs=None, globalargs=None): - volshellargs = volshellargs or [] - globalargs = globalargs or [] +def runvolshell( + img, volshell, python, volshellargs: Tuple = (), globalargs: Tuple = () +): args = ( globalargs + ( @@ -71,25 +78,100 @@ def runvolshell(img, volshell, python, volshellargs=None, globalargs=None): return runvol(args, volshell, python) +def load_test_data(plugin: str, test_key: str): + if plugin.startswith("windows."): + data_path = WINDOWS_TESTS_DATA_DIR / f"{plugin}.json" + # TODO: add Linux and macOS when any of these requires this API + else: + raise Exception(f"Cannot determine OS of plugin: {plugin}") + + if not data_path.exists(): + raise FileNotFoundError( + f"Test data not found for plugin {plugin} at {data_path}" + ) + + with open(data_path) as f: + # This will raise an explicit exception by itself on failures + return json.load(f)[test_key] + + +def dict_lower_strvalues(dict_to_convert: dict): + """Lower each value of type string of a dictionary + + Args: + dict_to_convert: The dictionary in which to lower the string values + Returns: + A copy of the dictionary with lowered string values + """ + + converted = {} + for key, value in dict_to_convert.items(): + if isinstance(value, str): + converted[key] = value.lower() + else: + converted[key] = value + return converted + + def match_output_row( - expected_row: dict, plugin_json_out: List[dict], exact_match: bool = False + expected_row: dict, + plugin_json_out: List[dict], + exact_match: bool = False, + case_sensitive: bool = True, + children_recursive: bool = False, ): - """Search each row of a plugin's JSON output for an expected row. Each row is a dict. + """Search each row in a plugin's JSON output for a matching row. + This method supports recursive comparisons using the "__children" key, making it useful for testing hierarchical plugins like windows.pstree. + It also maintains case sensitivity and exact matching behavior when traversing nested structures. Args: expected_row: The expected row to be found in the output plugin_json_out: The plugin's output in JSON format (typically obtained through -r json and json.loads) - exact_match: Whether to require exactly the expected row, no more no less, or to anticipate columns' addition by checking only + exact_match: Require exactly the expected row, no more no less, or anticipate columns' addition by checking only the expected row keys and values + case_sensitive: Operate case sensitive match for str values of both dictionaries or not + children_recursive: Perform a recursive match by inspecting "__children" keys of each expected_row + + Returns: + A boolean indicating whether a match was found or not """ + # Lower each string value of both dicts + if not case_sensitive: + expected_row = dict_lower_strvalues(expected_row) + plugin_json_out_tmp = [] + for row in plugin_json_out: + plugin_json_out_tmp.append(dict_lower_strvalues(row)) + plugin_json_out = plugin_json_out_tmp + if not exact_match: for row in plugin_json_out: if all( - expected_item in row.items() for expected_item in expected_row.items() + expected_item in row.items() + for expected_item in expected_row.items() + if not expected_item[0] == "__children" ): - return True + if ( + children_recursive + and "__children" in expected_row + and "__children" in row + ): + for children_expected_row in expected_row["__children"]: + if not match_output_row( + children_expected_row, + row["__children"], + case_sensitive=case_sensitive, + children_recursive=True, + ): + break + else: + # We matched all the children keys + return True + else: + # No recursion required and we already matched the row + return True else: + # No "__children" recursion here as we want to match the whole tree at once for row in plugin_json_out: if expected_row == row: return True @@ -97,12 +179,26 @@ def match_output_row( return False +def count_entries_flat(plugin_json_out: List[dict]): + """Count the number of entries as if -r json wasn't specified. Allows to get a non-hierarchical count, without running a plugin twice + (once with "-r json" and once without) while still preserving JSON features. + + Args: + plugin_json_out: The plugin's output in JSON format (typically obtained through -r json and json.loads) + """ + # Remove whitespaces between entries + # If a value contains {", it will be represented by {\" so no confusion + return json.dumps(plugin_json_out, separators=(",", ":")).count('{"') + + # # TESTS # -def basic_volshell_test(image, volatility, python, globalargs): +def basic_volshell_test( + image, volatility, python, volshellargs: Tuple = (), globalargs: Tuple = () +): # Basic VolShell test to verify requirements and ensure VolShell runs without crashing volshell_commands = [ @@ -122,7 +218,7 @@ def basic_volshell_test(image, volatility, python, globalargs): img=image, volshell=volatility, python=python, - volshellargs=("--script", filename), + volshellargs=("--script", filename) + volshellargs, globalargs=globalargs, ) finally: