diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index dfc42499d..ce2722457 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -42,8 +42,13 @@ jobs: - name: Testing... run: | - pytest ./test/test_volatility.py --volatility=vol.py --image-dir=./test_images -k test_windows -v - pytest ./test/test_volatility.py --volatility=vol.py --image-dir=./test_images -k test_linux -v + # VolShell + pytest ./test/test_volatility.py --volatility=volshell.py --image-dir=./test_images -k test_windows_volshell -v + pytest ./test/test_volatility.py --volatility=volshell.py --image-dir=./test_images -k test_linux_volshell -v + + # Volatility + pytest ./test/test_volatility.py --volatility=vol.py --image-dir=./test_images -k "test_windows and not test_windows_volshell" -v + pytest ./test/test_volatility.py --volatility=vol.py --image-dir=./test_images -k "test_linux and not test_linux_volshell" -v - name: Clean up post-test run: | diff --git a/test/test_volatility.py b/test/test_volatility.py index 5bce07481..bb7c9a851 100644 --- a/test/test_volatility.py +++ b/test/test_volatility.py @@ -39,7 +39,9 @@ def runvol(args, volatility, python): return p.returncode, stdout, stderr -def runvol_plugin(plugin, img, volatility, python, pluginargs=[], globalargs=[]): +def runvol_plugin(plugin, img, volatility, python, pluginargs=None, globalargs=None): + pluginargs = pluginargs or [] + globalargs = globalargs or [] args = ( globalargs + [ @@ -54,13 +56,68 @@ def runvol_plugin(plugin, img, volatility, python, pluginargs=[], globalargs=[]) return runvol(args, volatility, python) +def runvolshell(img, volshell, python, volshellargs=None, globalargs=None): + volshellargs = volshellargs or [] + globalargs = globalargs or [] + args = ( + globalargs + + [ + "--single-location", + img, + "-q", + ] + + volshellargs + ) + + return runvol(args, volshell, python) + + # # TESTS # + +def basic_volshell_test(image, volatility, python, globalargs): + # Basic VolShell test to verify requirements and ensure VolShell runs without crashing + + volshell_commands = [ + "print(ps())", + "exit()", + ] + + # FIXME: When the minimum Python version includes 3.12, replace the following with: + # with tempfile.NamedTemporaryFile(delete_on_close=False) as fd: ... + fd, filename = tempfile.mkstemp(suffix=".txt") + try: + volshell_script = "\n".join(volshell_commands) + with os.fdopen(fd, "w") as f: + f.write(volshell_script) + + rc, out, _err = runvolshell( + img=image, + volshell=volatility, + python=python, + volshellargs=["--script", filename], + globalargs=globalargs, + ) + finally: + with contextlib.suppress(FileNotFoundError): + os.remove(filename) + + assert rc == 0 + assert out.count(b"\n") >= 4 + + return out + + # WINDOWS +def test_windows_volshell(image, volatility, python): + out = basic_volshell_test(image, volatility, python, globalargs=["-w"]) + assert out.count(b" 40 + + def test_windows_pslist(image, volatility, python): rc, out, _err = runvol_plugin("windows.pslist.PsList", image, volatility, python) out = out.lower() @@ -332,6 +389,11 @@ def test_windows_vadyarascan_yara_string(image, volatility, python): # LINUX +def test_linux_volshell(image, volatility, python): + out = basic_volshell_test(image, volatility, python, globalargs=["-l"]) + assert out.count(b" 100 + + def test_linux_pslist(image, volatility, python): rc, out, _err = runvol_plugin("linux.pslist.PsList", image, volatility, python) @@ -770,6 +832,10 @@ def test_linux_hidden_modules(image, volatility, python): # MAC +def test_mac_volshell(image, volatility, python): + basic_volshell_test(image, volatility, python, globalargs=["-m"]) + + def test_mac_pslist(image, volatility, python): rc, out, _err = runvol_plugin("mac.pslist.PsList", image, volatility, python) out = out.lower()