From b7003bc231b4a5382db3b9b01393adf1700d2aa8 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Tue, 15 Feb 2022 12:43:37 +0200 Subject: [PATCH] Agent: split up nt and lm hashes into separate credential components --- .../credential_collectors/__init__.py | 3 ++- .../credential_components/lm_hash.py | 7 +++++++ .../credential_components/nt_hash.py | 7 +++++++ .../credential_components/nt_hashes.py | 9 --------- .../mimikatz_cred_collector.py | 17 +++++++++++------ .../test_mimikatz_collector.py | 14 ++++++-------- 6 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 monkey/infection_monkey/credential_collectors/credential_components/lm_hash.py create mode 100644 monkey/infection_monkey/credential_collectors/credential_components/nt_hash.py delete mode 100644 monkey/infection_monkey/credential_collectors/credential_components/nt_hashes.py diff --git a/monkey/infection_monkey/credential_collectors/__init__.py b/monkey/infection_monkey/credential_collectors/__init__.py index 4ec480246..7d48c7bb1 100644 --- a/monkey/infection_monkey/credential_collectors/__init__.py +++ b/monkey/infection_monkey/credential_collectors/__init__.py @@ -1,5 +1,6 @@ from .i_credential_collector import ICredentialCollector -from .credential_components.nt_hashes import NTHashes +from .credential_components.nt_hash import NTHash +from .credential_components.lm_hash import LMHash from .credential_components.password import Password from .credential_components.ssh_keypair import SSHKeypair from .credential_components.username import Username diff --git a/monkey/infection_monkey/credential_collectors/credential_components/lm_hash.py b/monkey/infection_monkey/credential_collectors/credential_components/lm_hash.py new file mode 100644 index 000000000..d9557c9b0 --- /dev/null +++ b/monkey/infection_monkey/credential_collectors/credential_components/lm_hash.py @@ -0,0 +1,7 @@ +from ..credential_type import CredentialType +from .i_credential_component import ICredentialComponent + + +class LMHash(ICredentialComponent): + def __init__(self, lm_hash: str): + super().__init__(type=CredentialType.NTLM_HASH, content={"lm_hash": lm_hash}) diff --git a/monkey/infection_monkey/credential_collectors/credential_components/nt_hash.py b/monkey/infection_monkey/credential_collectors/credential_components/nt_hash.py new file mode 100644 index 000000000..ae412310e --- /dev/null +++ b/monkey/infection_monkey/credential_collectors/credential_components/nt_hash.py @@ -0,0 +1,7 @@ +from ..credential_type import CredentialType +from .i_credential_component import ICredentialComponent + + +class NTHash(ICredentialComponent): + def __init__(self, nt_hash: str): + super().__init__(type=CredentialType.NTLM_HASH, content={"nt_hash": nt_hash}) diff --git a/monkey/infection_monkey/credential_collectors/credential_components/nt_hashes.py b/monkey/infection_monkey/credential_collectors/credential_components/nt_hashes.py deleted file mode 100644 index 13acd83f6..000000000 --- a/monkey/infection_monkey/credential_collectors/credential_components/nt_hashes.py +++ /dev/null @@ -1,9 +0,0 @@ -from ..credential_types import CredentialTypes -from .i_credential_component import ICredentialComponent - - -class NTHashes(ICredentialComponent): - def __init__(self, ntlm_hash: str, lm_hash: str): - super().__init__( - type=CredentialTypes.NTLM_HASH, content={"ntlm_hash": ntlm_hash, "lm_hash": lm_hash} - ) diff --git a/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py b/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py index 534580145..708bc7a32 100644 --- a/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py +++ b/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py @@ -3,7 +3,8 @@ from typing import List from infection_monkey.credential_collectors import ( Credentials, ICredentialCollector, - NTHashes, + LMHash, + NTHash, Password, Username, ) @@ -15,10 +16,10 @@ from .windows_credentials import WindowsCredentials class MimikatzCredentialCollector(ICredentialCollector): def collect_credentials(self) -> List[Credentials]: creds = pypykatz_handler.get_windows_creds() - return MimikatzCredentialCollector.to_credentials(creds) + return MimikatzCredentialCollector._to_credentials(creds) @staticmethod - def to_credentials(win_creds: List[WindowsCredentials]) -> [Credentials]: + def _to_credentials(win_creds: List[WindowsCredentials]) -> [Credentials]: all_creds = [] for win_cred in win_creds: creds_obj = Credentials(identities=[], secrets=[]) @@ -30,9 +31,13 @@ class MimikatzCredentialCollector(ICredentialCollector): password = Password(win_cred.password) creds_obj.secrets.append(password) - if win_cred.lm_hash or win_cred.ntlm_hash: - hashes = NTHashes(ntlm_hash=win_cred.ntlm_hash, lm_hash=win_cred.lm_hash) - creds_obj.secrets.append(hashes) + if win_cred.lm_hash: + lm_hash = LMHash(lm_hash=win_cred.lm_hash) + creds_obj.secrets.append(lm_hash) + + if win_cred.ntlm_hash: + lm_hash = NTHash(nt_hash=win_cred.ntlm_hash) + creds_obj.secrets.append(lm_hash) if creds_obj.identities != [] or creds_obj.secrets != []: all_creds.append(creds_obj) diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py index 5882315c4..0bf0c3628 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py @@ -1,4 +1,4 @@ -from infection_monkey.credential_collectors import Credentials, NTHashes, Password, Username +from infection_monkey.credential_collectors import Credentials, LMHash, NTHash, Password, Username from infection_monkey.credential_collectors.mimikatz_collector.mimikatz_cred_collector import ( MimikatzCredentialCollector, ) @@ -32,9 +32,7 @@ def test_pypykatz_result_parsing(monkeypatch): WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash=""), WindowsCredentials(username="", password="", ntlm_hash="ntlm_hash", lm_hash="lm_hash"), WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash=""), - WindowsCredentials( - username="user2", password="secret2", ntlm_hash="ntlm_hash2", lm_hash="lm_hash2" - ), + WindowsCredentials(username="user2", password="secret2", lm_hash="lm_hash"), ] patch_pypykatz(win_creds, monkeypatch) @@ -43,14 +41,14 @@ def test_pypykatz_result_parsing(monkeypatch): username2 = Username("user2") password = Password("secret") password2 = Password("secret2") - hash = NTHashes(ntlm_hash="ntlm_hash", lm_hash="lm_hash") - hash2 = NTHashes(ntlm_hash="ntlm_hash2", lm_hash="lm_hash2") + nt_hash = NTHash(nt_hash="ntlm_hash") + lm_hash = LMHash(lm_hash="lm_hash") expected = [ Credentials(identities=[username], secrets=[password]), - Credentials(identities=[], secrets=[hash]), + Credentials(identities=[], secrets=[lm_hash, nt_hash]), Credentials(identities=[username], secrets=[password]), - Credentials(identities=[username2], secrets=[password2, hash2]), + Credentials(identities=[username2], secrets=[password2, lm_hash]), ] collected = MimikatzCredentialCollector().collect_credentials() assert expected == collected