Domain and DC Migrations: How To Monitor LDAP, Kerberos and NTLM Traffic To Your Domain Controllers
Published Sep 20 2018 12:53 AM 163K Views

 

First published on TechNet on Dec 15, 2013

 

Hi everyone Adrian Corona here, this time I’d like to talk about a scenario that I get asked about a lot: Domain / Domain Controller Migrations.

A very (if not the most) important piece of a successful migration is to know when there’s a system or application still using your domain services before decommissioning your domain / domain controller.

Usually IT departments will have visibility of the most important applications in the environment as well as any specific configuration (hard coded IPs, server names, etc). However it is very common to have not-so-important services using AD and not having any documentation (or even knowledge) about them. It’s also very common to not have any documentation for those important services :).

One the most common question I get from customers is: “How can I monitor if there are applications still using my domain?”

This question extends too many scenarios such as domain migrations, consolidation or simple curiosity. Maybe you want to build that documentation you were missing. Seriously please do. Regardless of your scenario, it is very important to know which systems are using your domain controllers and for what.

A data collector set is a component that leverages and consolidates different sources of performance information into a single view. A Data Collector Set can be created and then recorded individually, grouped with other Data Collector Set and incorporated into logs, viewed in Performance Monitor, configured to generate alerts when thresholds are reached, or used by other non-Microsoft applications in other words, awesome!

I won’t get into much detail on how the DCS works but I’ll show you how to use them to get key AD information from your domain controllers. We’ll be taking advantage of ETW tracing which is very powerful, you can read a lot about it here .

Note : For this to work correctly you’ll need to run this part of the process from a domain controller. In this example I’m using a 2012 R2 DC but the process should be the same for 2008 and 2008 R2, unfortunately this process doesn’t apply to 2003 DCs, for sure you can use SPA and get similar information but the good thing is that you’ve got rid of those old 2k3 DCs right?

Data collector sets are very useful, there are built-in collectors and the reporting is great, for instance I can start the Built-in Active directory Diagnostics collector and it will run for 5 minutes (if you want to change that you’ll need to create your own DCS ) after finished, you can see this awesome reports which will show you very important information about your domain controller’s performance.

This looks great but the only problem is that this reports are limited to a maximum number of results, however the data on the ETW trace is there so there must be a way to take advantage of it, let’s see how.

First begin by launching Performance Monitor:

 

Expand Data Collector Sets:

 

Right click User Defined – New – Data Collector Set

 

Type the name you want to add to the DCS, select Create Manually (Advanced) and click next:

 

Select Event Trace Data:

 

On the Event Providers click add and select the following providers:

- Active directory Domain services: Core

- Active Directory: Kerberos KDC

- NTLM Security Protocol.

Note: there are many more providers available, you can customize your monitoring to anything you want to include, just bear in mind that the more providers you add the larger your file will grow.

 

 

Click next, select the path where you want to save this file and click finish.

 

On Perfmon console right click your newly created DCS and select properties:

 

In this window you can configure many options but we are interested on the stop condition which tells your system how long you will be collecting information.

Warning: DCS ETW grows very fast in a heavily utilized system a 5 minute trace grew ~100MB so be careful where do you place this file, also you want to run this process when there is the most user activity.

In this case I will be running my test for 1 hour:

 

After your collector is created, select it and click start on the toolbar:

 

After the data is collected you’ll have a file called datacollector01.etl, if you try to open it you’ll only see garble since this file is in binary format, so what can I do to read it?

 

Don’t worry, “After a while you don't even see the code anymore”.

 

If you are not as advanced as Cypher here you can always use tracerpt to convert this files to a human readable and convenient CSV file.

For that, open up an elevated command prompt on the Domain controller and run the following command:

Tracerpt –l “file.etl” –of CSV

If you run this command on other machine the providers might not be available and the events decoding will be incomplete.

 

When the process is done, you’ll have 2 files:

- Summary.csv – You can use this file to validate that all the providers were found, to do that just check that all rows on the eventname column are populated, if you have one or more empty rows, the system you used does not have the correct providers (which shouldn’t happen if you run this on the DC since it has all of them)

 

 

 

 

- Dumpfile.csv: this file contains the human readable information (or is it?)

 

Panic no more, you can open this file with Excel and you’ll see a nicely formatted document that can filter and sort as you please, however it isn’t that convenient if I have to manually review all my domain controllers manually, so I created a simple macro that you can use to consume this file and give you a nicer format (as of the moment of this writhing this macro can process one file at the time), the only thing you have to do is follow this steps:

1. Download the Import-DC-Info.xlsm document attached at the bottom of this post. It works with Excel 2010 and 2013.

2. Place the document in the same folder where you have the dumpfile.csv

3. Open the file and if necessary enable macros.

4. Click on Import File.

5. Sit down and relax.

 

After this process is done you’ll have and excel file called DCInfo.xlsx with some tabs and pivot tables created:

LDAP.

It contains a list of all the LDAP queries performed against your DC with a list of IP (with duplicates removed), IP:Port combination and also the query that was executed, with this you can see who is requesting what info and from what IP this query was originated.

Kerberos-Pivot .

This is a Pivot table populated from the Kerberos tab which is sorted by the total number of hits to a particular service, this table is helpful to have a quick glance of what service is still using Kerberos authentication. To get this information I filtered and cleaned up the TGS-Start requests, I excluded the AS requests since they could potentially increase the number of results and we won’t gain much additional information by including it.

 

Kerberos.

This table is a consolidated (and duplicate removed) list of all the TGS requests made, you’ll use this tab if you want to see more detail from the pivot table, more specifically the User column will show you the actual user/computer/service account that is requesting a service while the service column indicates what service is being requested. Take for example the following row:

FabrikamDC3 is a domain controller that is requesting a Kerberos ticket to access a file share on fabrikamdc (probably Sysvol contents)

 

NTLM-Pivot.

This table is very similar to the Kerberos-Pivot, it will give you a list of the total number of NTLMValidateUser requests being performed from clients to services.

 

NTLM.

A full list of every NTLMValidateUser requests, similar to the Kerberos tab.

 

 

As I explained earlier, this process should be performed from all your DC’s preferably during the same time window so you’ll have unique authentication requests and queries logged. If you log information from different DCs at different times you might get the same client(s) hitting different DCs thus, duplicated information.

If your exported csv files are not very large, one suggestion is to manually consolidate all the exported data into one big csv, but beware that a huge file might consume a lot of memory and will take longer to process, if time is not necessary a concern, go for it!

The macro doesn’t have much error control but it will serve the purpose if it is used as instructed, the good news is that even if you don’t use the macro you still have great information that can be exploited anyway you like.

Keep tuned.

 

**Update 10/12/2014- I replaced the macro file with a non-protected file for those of you adventurous debuggers, you’ll find my code is not complex, so any improvements will be well received. Thanks.

 

Adrian “ETW: Event Tracing for Windows not East to West” Corona.

18 Comments
Copper Contributor

Hi Mark --

 

Excellent article! The last time I visited this post, I believe there were numerous comments, what happened to them? I believe there was someone offering up powershell script(s) to do further parsing of the data. Do you know where I might be able to get my hands on that?

 

Also, I'm unable to download the .zip. Is the link broken or is it just a PEBKAC error on my end?

 

Thanks,

Jordan

Copper Contributor

Mark,

 

Import-DC_Info_V2.zip download is not working.

Copper Contributor
Microsoft

Hi all-

 

We are still working on getting attachments and everything moved over post-migration. I will have these corrected as soon as I can :)

 

Copper Contributor

Hi

I just found the script on my machine, I saved it when I first read this blog post earlier this year. I forgot who wrote it, but thank you!

# ==============================================================
# === Initialize and Set variable ==============================
# ==============================================================
$StartTime=(Get-Date -format “dd-MMM-yyyy HH:mm”).ToString()
$EndTime=””

$UniqueIps = New-Object System.Collections.Generic.HashSet[String]
$Kerberos = New-Object System.Collections.Generic.HashSet[String]
$NTLM = New-Object System.Collections.Generic.HashSet[String]

$CounterFileLines=0
$CounterDsDirSearch=0
$CounterUniqueIPs=0
$CounterTGSRequest=0
$CounterNtlmValidateUser=0

$IpsReqsArray = @()
$KerberosReqsArray = @()
$NtlmReqsArray = @()

# — Get File Folder and File Name —————————-
$LogFileName = Read-Host “Enter Path to dumpfile.csv”
If ((Test-Path $LogFileName) -eq $false)
{
Write-Error “File not found”; break
}

# — Get the IP Address of the Source Domain Controller ——-
$SourceDC = Read-Host “Enter IP of Source Domain Controller”

# — Open the Input File for reading (per line) —————
$LogfileReader = [System.IO.File]::OpenText(“$($LogFileName)”)

# — Main loop for processing each line in the file ———–
While ($null -ne ($LogfileLine = $LogfileReader.ReadLine()))
{
$CounterFileLines++
$Class = $LogfileLine.Split(“,”)

# — Check if the line matches a LDAP request —————–
If (($Class[0].Trim() -eq “DsDirSearch”) -and ($Class[1].Trim() -eq “Start”) -and ($Class[24] -like “*.*”) -and ($Class[24] -notlike “*127.0.0.1*”) -and ($Class[24] -notlike “*$($SourceDC)*”))
{
$IsolatedIpAddress=$Class[24].Split(“:”)[0].Replace(“`””,””).TrimStart()

$UniqueIps.Add($($IsolatedIpAddress)) | Out-Null
$CounterDsDirSearch++
Write-Host “Found LDAP Request number $($CounterDsDirSearch) and adding it to the collection” -ForegroundColor Cyan
}

# — Check if the line matches a Kerberos request ————-
ElseIf ($Class[0].Trim() -eq “TGSRequest”)
{
$Kerberos.Add($Class[20..22]) | Out-Null
$CounterTGSRequest++
Write-Host “Found Kerberos request number $($CounterTGSRequest) and adding it to the collection” -ForegroundColor Green
}

# — Check if the line matches a NTLM request —————–
ElseIf ($Class[0].Trim() -eq “NtlmValidateUser”)
{
$NTLM.Add($Class[22..23]) | Out-Null
$CounterNtlmValidateUser++
Write-Host “Found NTLM request number $($CounterNtlmValidateUser) and adding it to the collection” -ForegroundColor Yellow
}
}

$LogfileReader.Close()

# — Process Unique LDAP Requests and write to file ———–
Write-Host
Write-Host “Start Processing All Unique LDAP connection IP’s” -ForegroundColor White
$IpsEnum = $UniqueIps.GetEnumerator()
#Disable, Not supported by Powershell V2
#$IpsEnum.Reset()

While ($IpsEnum.MoveNext())
{
$CounterUniqueIPs++
$RetrievedIp = $(get-variable -name IpsEnum).Value.Current
$IpReqLine = New-Object -TypeName PsObject
Add-Member -InputObject $IpReqLine -MemberType NoteProperty -Name “IP” -Value $RetrievedIp

$IpsReqsArray += $IpReqLine
}
Write-Host “Writing Unique LDAP connection IP’s to log file: $($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Ips.csv” -ForegroundColor White
Write-Host
$IpsReqsArray | Export-Csv -Path “$($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Ips.csv” -NoTypeInformation -Delimiter “`t”

# — Process Kerberos Requests and write to file ————–
Write-Host “Start Processing All Kerberos Items” -ForegroundColor White
$KerberosEnum = $Kerberos.GetEnumerator()
#Disable, Not supported by Powershell V2
#$KerberosEnum.Reset()

While ($KerberosEnum.MoveNext())
{
$RetrievedKerberos = $(get-variable -name KerberosEnum).Value.Current.Replace(“`””, “”).Trim().Replace(” “, “,”).Split(“,”)

$KerberosReqLine = New-Object -TypeName PsObject
Add-Member -InputObject $KerberosReqLine -MemberType NoteProperty -Name “User” -Value $RetrievedKerberos[0]
Add-Member -InputObject $KerberosReqLine -MemberType NoteProperty -Name “Service” -Value $RetrievedKerberos[1]
Add-Member -InputObject $KerberosReqLine -MemberType NoteProperty -Name “Domain” -Value $RetrievedKerberos[2]

$KerberosReqsArray += $KerberosReqLine
}
Write-Host “Writing Kerberos Entries to log file: $($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Kerberos.csv” -ForegroundColor White
Write-Host
$KerberosReqsArray | Export-Csv -Path “$($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Kerberos.csv” -NoTypeInformation -Delimiter “`t”

# — Process NTLM Requests and write to file —————–
Write-Host “Start Processing All NTLM Items” -ForegroundColor White
$NtlmEnum = $Ntlm.GetEnumerator()
#Disable, Not supported by Powershell V2
#$NtlmEnum.Reset()

While ($NtlmEnum.MoveNext())
{
$RetrievedNtlm = $(get-variable -name NtlmEnum).Value.Current.Replace(“`””, “”).Trim().Replace(” “, “,”).Split(“,”)

$NtlmReqLine = New-Object -TypeName PsObject
Add-Member -InputObject $NtlmReqLine -MemberType NoteProperty -Name “User” -Value $RetrievedNtlm[0]
Add-Member -InputObject $NtlmReqLine -MemberType NoteProperty -Name “Computer” -Value $RetrievedNtlm[1]

$NtlmReqsArray += $NtlmReqLine
}
Write-Host “Writing NTLM Entries to log file: $($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Ntlm.csv” -ForegroundColor White
Write-Host
$NtlmReqsArray | Export-Csv -Path “$($LogFileName.Substring(0,$LogFileName.LastIndexOf(“\”)+1))Ntlm.csv” -NoTypeInformation -Delimiter “`t”

# — Display processing statistics —————————
Write-Host “Processed File Lines: $($CounterFileLines)” -ForegroundColor White
Write-Host “Found LDAP Request(s): $($CounterDsDirSearch)” -ForegroundColor Cyan
Write-Host “Found Kerberos Request(s): $($CounterTGSRequest)” -ForegroundColor Green
Write-Host “Found NTLM Request(s): $($CounterNtlmValidateUser)” -ForegroundColor Yellow
Write-Host
Write-Host “Found Unique LDAP IP(s): $($CounterUniqueIPs)” -ForegroundColor Cyan
Write-Host

$EndTime=(Get-Date -format “dd-MMM-yyyy HH:mm”).ToString()

Write-Host “Start Time: $($StartTime)” -ForegroundColor Magenta
Write-Host “End Time: $($EndTime)” -ForegroundColor Magenta
Write-Host

Write-Host “Done !!!” -ForegroundColor White
Copper Contributor
AlanMullett, the attachment is working. Thank you
Copper Contributor

@AlanMullett- The micro to convert the CSV file to xls file is not working for CSV file size above 6 GB. It shows this error -

 

MicrosoftTeams-image (1).png

 

 

Any workaround ?

Copper Contributor

Thank you guys...This helped me with a recent project... 

Copper Contributor

@Mark Morowczynski 

Great Article and equally useful macro. I intend to capture DNS and SMB traffic to my DC's using DCS. Is there a macro that can parse DNS and SMB as well from the dumpfile.csv file?

 

 

 

Copper Contributor

@Mark Morowczynski , Hi I am not able to download the macro file, kindly reload or share the new link.

 

warm regards.

Naveen

Copper Contributor

@Mark Morowczynski or @AlanMullett can you please share a working download URL please?

Copper Contributor

@Mark Morowczynski or @AlanMullett can you please share a working download URL please?

 

i need this  

 

please

Copper Contributor

@Mark Morowczynski or @AlanMullett  please share a working download URL for  Import-DC_Info_V2.zip

I need it please.

Copper Contributor

@brandon wilson Hello Brandon , 

Please share a working download URL for  Import-DC_Info_V2.zip.

The macro file which has been used to read the report as per the article. Need it. Thanks

Copper Contributor

Hi, this excell tool is exactly what I need !  But there's an error msg when I run the macro : runtime error '5'.  Any idea why ?  Thank you !

Brass Contributor

@wolandy2k

Thank you for posting the PowerShell script. For everyone's benefit, I was pulling my hair out because of a PIBKAC error:

 

Enter Path to dumpfile.csv: Downloads
Enter IP of Source Domain Controller: 10.132.39.105
Exception calling "OpenText" with "1" argument(s): "Access to the path 'C:\Users\adminuser\Downloads' is denied."
At C:\PerfMonDCS.ps1:36 char:48
+ $LogfileReader = [System.IO.File]::OpenText(“$($LogFileName)”)
+                                                ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : UnauthorizedAccessException

 

Turns out, you need to specify the dumpfile.csv filename as well as the path to the file. The dumpfile.csv is created per the instructions above

Tracerpt -l “file.etl” -of CSV

In other words, the correct response to the PowerShell prompt is C:\Users\adminuser\Downloads\dumpfile.csv

Brass Contributor

This blog's solutions works well when an entire domain is being retired - allows you to find who is still logging into the old domain. However, if all you are doing is retiring an old domain controller but keeping the same domain, as long as the old domain controller is running it will randomly keep serving the instance of Active Directory and SYSVOL.  So the LDAP, Kerberos, NTLM, and CIFS connections that Perfmon DCS is pulling are all quite legitimate and of no use to finding anything with hard-coded IP addresses, or domain controller server names!     :(

Copper Contributor

thanks for the great article ..

Version history
Last update:
‎Nov 09 2023 11:10 AM
Updated by: