This walkthrough takes you end-to-end against a Windows Server 2019 domain controller in the ignite.local lab. You start exactly where the exam drops you — holding a single low-privileged credential — and finish with the krbtgt hash in hand, full domain compromise on the board, and NT AUTHORITY\SYSTEM on a downstream MSSQL host via PrintSpoofer. Every command is explained, every flag justified, and every step mapped to a phase of the OSCP attack methodology so you always know where you are on the kill chain — and, more importantly, what the next move should be.
If you are chasing the OSCP, the Active Directory set is the section that decides your fate. It is worth 40 points — enough to fail you outright if you skip it, and enough to carry you across the 70-point passing line if you own it cleanly. Yet most aspirants arrive at the exam comfortable throwing Nmap at a Windows box and frozen the moment they hold one valid domain credential and stare at a domain controller. The gap between holding raj:Password@1 and standing as NT AUTHORITY\SYSTEM on every host in the forest is exactly what this article closes.
NetExec (formerly CrackMapExec, invoked as nxc) is the modern Swiss Army knife for Active Directory penetration testing, and the single tool that survives every stage of that journey. It bundles authentication, enumeration, lateral movement, credential extraction, and post-exploitation across SMB, LDAP, WinRM, MSSQL, RDP, FTP, and SSH into one scriptable interface. Where exam labs once demanded juggling a dozen Impacket scripts, a fluent NetExec operator answers the same questions in a single line — making it the highest-leverage skill an OSCP aspirant can build in the final weeks before sitting the exam.
The walkthrough is deliberately structured to mirror the OSCP attack methodology, so each section answers a question an aspirant must answer in the exam: what do I have, what can I see, what can I do with it, what can I steal, and where can I pivot next. Read it linearly the first time to absorb the chain end-to-end; on later passes, jump directly to the phase you need to drill. The journey unfolds in seven phases.
By the time you reach the conclusion, the same command set that compromised ignite.local will have become a mental flowchart you can execute under exam pressure — and the report you write afterwards will read like the work of a professional.
The lab simulates a realistic small-enterprise Active Directory deployment. The domain ignite.local is hosted on a Windows Server 2019 domain controller at 192.168.1.9, with an additional Windows host at 192.168.1.7 running Microsoft SQL Server. The starting credential is the low-privileged user raj: Password@1 — the type of foothold typically obtained through phishing, password spraying, or a Kerberoast crack. The attacking host is a Kali Linux machine on the same subnet.
Hosts in scope:
Before any domain-aware tool runs, the attacker must teach Kali how to resolve the target by name. Kerberos exchanges, LDAP referrals, and BloodHound collection all rely on FQDN resolution; without it, modules silently fail or fall back to NTLM. The /etc/hosts file is opened by using the following command:
cat /etc/hosts

Once the file is opened and an entry is added that maps the controller’s IP address to its fully qualified name, the short NetBIOS name, and the bare domain name. Once this mapping is in place, every subsequent NetExec invocation can cleanly target the controller while still honouring the domain name in tickets and queries.
With name resolution prepared, NetExec validates the foothold credential against the directory service on port 389 by using the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1

A simple LDAP bind serves three purposes at once: it confirms the credentials are correct, that the account is not locked, and that the user is permitted to read the directory.
Appending the –users flag instructs NetExec to query the directory and list every domain user along with the timestamp of the last password change and the bad-password counter with the help of the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 –users

The output reveals 27 enumerated accounts, including standard service accounts (Administrator, krbtgt, Guest) and personal accounts such as raj, aarti, sanjeet, krishna, ram, and others. The Last PW Set column is invaluable for spotting stale credentials, while elevated BadPwdCount values quickly highlight accounts already targeted by lockout-aware spray attempts.
The –admin-count switch narrows the result set to accounts whose adminCount attribute equals 1, which refers to the AdminSDHolder marker that Active Directory automatically applies to current and former members of protected groups such as Domain Admins, Enterprise Admins, and Schema Admins.
nxc ldap 192.168.1.9 -u raj -p Password@1 --admin-count

The list returned (Administrator, krbtgt, raj, aarti, ram, sita, krishna, raaz, aaru, jerry, ankur) is effectively a roadmap of high-value targets. Compromising any one of these accounts is likely to yield privileged access somewhere in the domain.
Switching the flag to –active-users excludes disabled accounts and produces the live attack that surfaces all the accounts that are active, with the use of the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 --active-users

NetExec reports 27 total records with 2 disabled, leaving 25 enabled users in scope. This filter must be applied before launching any password-spray, AS-REP-roast, or credential-stuffing attack — hammering disabled accounts wastes attempts and risks triggering audit alerts without ever returning a usable session.
When a specific user warrants a closer look, the –query flag accepts a raw LDAP filter and dumps every attribute on the matching object. Querying (sAMAccountName=krishna) returns the account’s full record which you can see by using the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 --query "(sAMAccountName=krishna)" ""

The highlighted line shows that krishna belongs to CN=Domain Admins, CN=Users, DC=ignite, DC=local, immediately flagging this account as a domain-wide administrator. Compromising krishna is therefore equivalent to compromising the entire domain.
The groupmembership module reverses the question: instead of asking what groups a user belongs to by reading their attributes, it walks the directory and returns every group that lists the supplied user as a member. This can be done with the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 -M groupmembership -o USER="ram"

Running it against ram reveals membership in Remote Management Users, Backup Operators, and Domain Users. The first group implies WinRM access; the second is a classic privilege-escalation primitive on a domain controller because Backup Operators can read the SAM, SYSTEM, and SECURITY hives and therefore extract every credential on the box.
The complementary –groups query lists every member of a named group as shown through the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 --groups "Backup Operators"

The result confirms that ram is the sole non-default member of Backup Operators on this domain controller. From an attacker’s standpoint, this is the single most valuable piece of intelligence gathered so far — owning ram is now the shortest path to a full hash dump of the directory.
Rather than pivoting through every group manually, the –bloodhound module collects the data needed to graph the entire domain. NetExec walks the directory, RDP, local admin, ACL, PSRemote, DCOM, container, and session collection methods, and packages the JSON output into a zip archive at /root/.nxc/logs/. This can be done through the following command:
nxc ldap 192.168.1.9 -u raj -p Password@1 --bloodhound --collection All --dns-server 192.168.1.9

Importing this zip into BloodHound CE or Legacy reveals every privilege-escalation, Kerberos delegation, and ACL-abuse path in the environment — typically reducing hours of manual enumeration to a single Cypher query.
Once an administrative credential is in hand — here, administrator: Ignite@987 — the rdp module flips the registry remotely to enable Remote Desktop. NetExec connects over SMB, calls WMI through the ncacn_ip_tcp transport, sets fDenyTSConnections to 0, and confirms RDP is listening on 3389. All this will be done with the help of the following commands:
nxc smb 192.168.1.9 -u administrator -p Ignite@987 -M rdp -o ACTION=enable rdesktop 192.168.1.9

A simple rdesktop invocation then drops the operator straight onto the DC’s logon screen with a fully interactive session, ready to be paired with a stolen credential or a passed hash.
The PowerShell_history module reads every user’s ConsoleHost_history.txt with the following command:
nxc smb 192.168.1.9 -u administrator -p Ignite@987 -M powershell_history

On this controller, the history is a goldmine: it shows past administrative work including LAPS rollout, gMSA configuration (New-ADServiceAccount), and — most damagingly — two cleartext credential operations: net user jerry Password@1 /add /domain and net user tom Password@1 /add /domain. Those plaintext passwords are now logged credentials available for immediate reuse.
The lsassy module dumps LSASS memory remotely and parses it for cached secrets without writing any binary to disk with the following command:
nxc smb 192.168.1.9 -u administrator -p Ignite@987 -M lsassy

It extracts 19 Kerberos tickets, the NTLM hash for IGNITE\Administrator , and — most usefully — the cleartext local administrator credential for a second host: 192.168.1.17\administrator: Password@123. That single line provides a ready-made pivot to another machine with full local administrative rights.
Returning to the earlier discovery that ram is a Backup Operator, the backup_operator module weaponises that privilege end-to-end. NetExec triggers RemoteRegistry, saves SAM, SYSTEM, and SECURITY to SYSVOL, downloads them, parses the registry hives offline, and finally dumps the full NTDS.dit by using the following command:
nxc smb 192.168.1.9 -u ram -p Password@1 -M backup_operator

The result is the complete hash list of every account in ignite.local — Administrator, krbtgt, every user, every machine account, plus the LSA secrets, DPAPI machine key, and gMSA hashes. With krbtgt and the Administrator hash in hand, the operator now controls the forest: Golden Tickets, Silver Tickets, DCSync, and pass-the-hash attacks are all on the table.
BloodHound surfaces an interesting ACL primitive between two ordinary users: SHREYA holds a ForceChangePassword right over YASHIKA. This abuse path lets shreya set yashika’s password without knowing the current one, effectively hijacking the account. The graph below visualises the relationship as a single attacker-controlled edge from [email protected] to [email protected].

The change-password module operationalises this graph edge in one command. Authenticating as shreya, NetExec invokes SAMR’s SamrChangePasswordUser2 routine and resets yashika’s password to Admin@123. The tool reports successfully changed password for yashika, and the operator now owns yashika’s account with a credential of their choice — no exploit, no malware, just a misconfigured ACL leveraged exactly the way Active Directory was designed to allow. And to do this, we will use the following command:
nxc smb 192.168.1.9 -u shreya -p Password@1 -M change-password -o USER=yashika NEWPASS=Admin@123

Switching the protocol from ldap/smb to winrm and supplying a userlist instead of a single account turns NetExec into a focused WinRM spray. NetExec attempts the same password against every name in users.txt over port 5985, with the use of the following command:
nxc winrm 192.168.1.9 -u users.txt -p Password@1

The output shows raj, aarti, sanjeet, and komal failing, while ram succeeds with the Pwn3d! tag — meaning ram is not only authenticated but also a member of Remote Management Users and therefore eligible for an interactive evil-winrm shell on the DC.
Pivoting to the MSSQL server at 192.168.1.7, the enum_impersonate module authenticates with local SQL credentials as shown in the following command and lists every login the current user can impersonate via EXECUTE AS.
nxc mssql 192.168.1.7 -u ignite -p 'Password@2' -M enum_impersonate --local-auth

The result is decisive: ignite can impersonate sa, the SQL Server super-user. This single right is enough to turn a low-privileged database login into full server control.
The mssql_priv module independently corroborates the finding: it reports that Ignite can impersonate sa (sysadmin). Two different modules now agree on the privilege path, so the attack proceeds with confidence by the use of the following command:
nxc mssql 192.168.1.7 -u ignite -p 'Password@2' -M mssql_priv --local-auth

The -q flag executes a raw SQL query through NetExec. Running the following command will return sa, proving the impersonation works in practice.
nxc mssql 192.168.1.7 -u ignite -p 'Password@2' --local -q "EXECUTE AS LOGIN='sa'; SELECT SYSTEM_USER;"

From this point forward, every statement issued in the same session executes with sysadmin authority on the SQL instance.
The next query chains three operations: it impersonates sa, sets show advanced options to 1 with RECONFIGURE and then enables xp_cmdshell with another RECONFIGURE. With xp_cmdshell live, the SQL service account can spawn arbitrary operating-system commands — typically used to launch a reverse shell, add a local administrator, or stage a Cobalt Strike beacon. Use the following command to achieve this:
nxc mssql 192.168.1.7 -u ignite -p 'Password@2' --local -q "EXECUTE AS LOGIN='sa'; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;"

The xp_cmdshell extended stored procedure shells out to cmd.exe under the security context of the SQL Server service account, returning each line of stdout as a row in the result set.
nxc mssql 192.168.1.7 -u ignite -p 'Password@2' --local -q "EXECUTE AS LOGIN='sa'; EXEC xp_cmdshell 'ipconfig';"

Wrapping an EXECUTE AS LOGIN=’sa’ statement around an xp_cmdshell call and running ipconfig is the canonical first command — it is harmless, produces deterministic output, and instantly confirms the channel is live. The response stream returns the familiar Windows IP Configuration banner followed by the Ethernet0 adapter block. Each NULL row corresponds to a blank line in the original ipconfig output, preserved verbatim by xp_cmdshell.
NetExec depends on LDAP for initial enumeration. Block it at the source.
Eliminate weak edges like Domain Admins, Backup Operators, ForceChangePassword.
Defeat lsassy, PS history, NTDS dumps.
Block NetExec’s SMB/RDP execution vectors.
Collapse enum_impersonate, xp_cmdshell chains.
NetExec modules generate distinct on-wire signatures. Tune SIEM for these indicators.
NetExec is not the threat — it is the spotlight that exposes pre-existing weakness. Every command demonstrated in the preceding walkthrough succeeded because of an architectural decision a defender had previously made: granting Backup Operators a ram account, leaving xp_cmdshell available behind a sysadmin impersonation grant, allowing the Print Spooler to run on a database server, or letting a service account keep SeImpersonatePrivilege out of habit. The tool simply executes, in seconds, the same plan a determined attacker would arrive at over hours.
Defenders therefore gain the most by treating each NetExec module as a curriculum item rather than a signature to detect. The mitigation matrix above maps directly to the modules used in the walkthrough — LDAP signing breaks the enumeration phase, BloodHound-driven ACL remediation kills the ForceChangePassword path, LSA Protection and Credential Guard neutralise LSASSY, gMSA plus stripped privileges defeats PrintSpoofer, and a single sp_configure ‘xp_cmdshell’, 0 closes the MSSQL chain. None of these controls is exotic; all are documented in Microsoft’s Securing Privileged Access roadmap and the CIS Benchmarks. The challenge is operational, not technical.
Mature security programmes therefore adopt a continuous-validation posture: run NetExec, BloodHound, and PingCastle on a defined schedule against the production domain, treat every successful module as a finding with a ticket, and measure the closure rate as a key performance indicator. The same toolkit that compromised ignite.local in this walkthrough becomes, in the hands of a skilled blue team, the most efficient hardening engine available. The objective is not to make Active Directory unattackable — that is impossible — but to ensure that when the attack happens, every step generates a high-fidelity alert and the chain breaks long before krbtgt leaves the domain controller.