lsassy
lsassy copied to clipboard
Help Needed: Automating tests
lsassy
Description
lsassy is a Python tool designed to remotely extract credentials from a set of hosts, particularly targeting the lsass process on these hosts. This is done in two steps First, code must be executed on the remote target to dump lsass. Then, the dump must be parsed remotely to extract the passwords.
Workflow
Here is how a dump and parsing works in a nutshell:
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/console.py#L99
From console.py, the ThreadPool is used to execute different lsassy instances in different threads
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/core.py#L149
Get an SMB session with the target and provided credentials (checks for admin rights)
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/core.py#L170
Get the dumping method (defined globally in https://github.com/Hackndo/lsassy/blob/master/lsassy/dumpmethod/init.py and every dump method will override get_commands)
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/core.py#L175 to actually dump lsass remotely.
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/dumpmethod/init.py#L291
For dumping lsass, a command line is remotely executed on the target using one of the executors (SMB using services by default, code stolen from impacket)
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/dumpmethod/init.py#L300
Checks if dump was successful
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/core.py#L193
Then back to core.py, instantiating Parser that will use Pypykatz project to parse the lsass dump remotely.
https://github.com/Hackndo/lsassy/blob/4b1ddf1b3491b014aa27a68f3aa26cb0c962b0a5/lsassy/core.py#L208
To write credentials in console (and file if asked)
Goal
I want to create tests for lsassy to ensure that all features and options work correctly with each new version release. I know how to create tests for everything that happens locally on my machine (and on Github actions), like testing threads number, instantiating classes dynamically, stuff like that.
My issue
The problem I encounter is testing network functionalities. I know about mock from unittest but I don't think it's enough for what I need.
For instance:
- How to test that command execution works on a remote target:
- Is there an issue with the command line sent to the target
- https://github.com/Hackndo/lsassy/blob/master/lsassy/dumpmethod/comsvcs.py#L16
- ...
- Does the execution method used work
- Service creation & execution https://github.com/Hackndo/lsassy/blob/master/lsassy/exec/smb.py
- Scheduled task creation and launch https://github.com/Hackndo/lsassy/blob/master/lsassy/exec/task.py
- ...
- Is there an issue with the command line sent to the target
- How to test that the filtering parameters provided to the command line are taken into account
- Tickets harversting
- DPAPI master keys
- Dump only users
- How to test the dumping/parsing options
- Don't delete remote dump
- Only parse remote dump
- Only dump lsass, without parsing
- ...
- How to test authentication mechanism
- Using NTML
- Using Kerberos
These are behaviors I can test if I execute lsassy in a controlled environment, with a Windows machine whose IP address I know. However, I would like to be able to launch tests from anywhere.
Ideas
One solution I can think of would be to use Docker, with a Linux machine executing the tool, and a Windows machine that would be the target.
But I'm not sure it's a good solution, and I would really appreciate some input
Thanks a lot
It is possible to create a GitHub Workflow (actions), that will execute jobs on 2 separates runners (See https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job ).
I think here, that you can create a workflow that will trigger on commit on the main branch. I'm not an expert in writing workflow but it could be something like this :
name: Lsassy tests
on:
push:
branches:
- main
jobs:
windows:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Running lsassy on windows
run: |
<YOUR CODE HERE>
linux:
runs-on: ubuntu-latest
needs: windows #So you make sure the windows tests have been done
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checking the results and trying remote executions
run: |
<YOUR CODE HERE>
It is also possible to use self-hosted runners. ( https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners ) It will allow you to control your environment so you'll be able to do every network tests.
Hope it will help you.
I think I found a workaround. I use a windows runner (provided by Github), I run lsassy on this runner, and I dump lsass on localhost. For this to work, I need to add a local admin and set a registry key, but it seems to work quite well https://github.com/Hackndo/lsassy/commit/92e4ae429404bc68052870e4ddcd6346fd4dd8cf
@Hackndo, great workaround.
It sounds that
- all data related commands can be tested through unit tests ( like parsing the dump )
- all "client" (remote handler) can be tested by mocking cases (wrong responses, good ones and special cases)
- all remote operations (that run on windows hosts) can be either tested directly on the host based on configuration and in that case would require to setup several hosts to test your cases
- and of course have complete (or integration) tests cases you'll need to pop off the whole stack.
Of course everything I described can be combined. I'm so sorry I didn't had time to look at the code you provided.
But if you can have a quick win by checking the whole is working correctly do so ! Your idea and "workaround" is the way to go. But when you'll need to identify which part is faulty then try to unit test it as the fault arise. So it doesn't happen again. Not sure I would have time but I'll look at the code and try to see how all the above is possible
Cya