Files
Work-Tools/Cartographer.ps1

318 lines
11 KiB
PowerShell

# Cartographer - DNS Record Mapping Tool with GUI - Map - IP to DNS record based on subnet
# Import required assemblies for GUI
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Convert IP addresses to integers for comparison
function Convert-IPToInt {
param (
[string]$IPAddress
)
[array]$octets = $IPAddress.Split('.')
return [int]($octets[0]) * 16777216 + [int]($octets[1]) * 65536 + [int]($octets[2]) * 256 + [int]($octets[3])
}
# Convert integer back to IP address
function Convert-IntToIP {
param (
[int64]$Integer
)
$octet1 = [Math]::Floor($Integer / 16777216)
$remainder = $Integer % 16777216
$octet2 = [Math]::Floor($remainder / 65536)
$remainder = $remainder % 65536
$octet3 = [Math]::Floor($remainder / 256)
$octet4 = $remainder % 256
return "$octet1.$octet2.$octet3.$octet4"
}
# Get subnet range based on IP and mask
function Get-SubnetRange {
param (
[string]$IPAddress
)
# Assuming /24 subnet
$octets = $IPAddress.Split('.')
$networkPrefix = "$($octets[0]).$($octets[1]).$($octets[2])"
$rangeStart = "$networkPrefix.1"
$rangeEnd = "$networkPrefix.254"
return @{
Start = $rangeStart
End = $rangeEnd
}
}
# Get available DNS servers
function Get-AvailableDnsServers {
# $dnsServers = @("localhost")
$clientDnsServers = Get-DnsClientServerAddress |
Where-Object { $_.ServerAddresses -ne $null } |
ForEach-Object {
$_.ServerAddresses | Where-Object { $_ -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' }
} |
Select-Object -Unique
$dnsServers += $clientDnsServers
# Try to add domain controllers if we're in a domain environment
try {
$domainControllers = Get-ADDomainController -Filter * |
ForEach-Object { $_.HostName }
$dnsServers += $domainControllers
} catch {
# Not in a domain environment or AD module not available, continue without it
}
return $dnsServers | Select-Object -Unique
}
# Query DNS for records
function Search-DnsRecords {
param (
[string]$DnsServer,
[string]$IPRangeStart,
[string]$IPRangeEnd
)
$StartInt = Convert-IPToInt $IPRangeStart
$EndInt = Convert-IPToInt $IPRangeEnd
$Results = @()
try {
$Zones = Get-DnsServerZone -ComputerName $DnsServer -ErrorAction Stop
foreach ($Zone in $Zones) {
$Records = Get-DnsServerResourceRecord -ZoneName $Zone.ZoneName -ComputerName $DnsServer -ErrorAction SilentlyContinue
foreach ($Record in $Records) {
if ($Record.RecordType -eq "A") {
$IPInt = Convert-IPToInt $Record.RecordData.IPv4Address.ToString()
if ($IPInt -ge $StartInt -and $IPInt -le $EndInt) {
$Results += [PSCustomObject]@{
IPAddress = $Record.RecordData.IPv4Address
Hostname = $Record.HostName
Zone = $Zone.ZoneName
}
}
}
}
}
} catch {
[System.Windows.Forms.MessageBox]::Show("Error querying DNS server: $_", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
return $Results
}
# Create the main form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Cartographer - DNS Record Mapping Tool"
$form.Size = New-Object System.Drawing.Size(800, 600)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
$form.MaximizeBox = $false
# DNS Server selection
$dnsServerLabel = New-Object System.Windows.Forms.Label
$dnsServerLabel.Text = "DNS Server:"
$dnsServerLabel.Location = New-Object System.Drawing.Point(20, 20)
$dnsServerLabel.Size = New-Object System.Drawing.Size(100, 20)
$form.Controls.Add($dnsServerLabel)
$dnsServerComboBox = New-Object System.Windows.Forms.ComboBox
$dnsServerComboBox.Location = New-Object System.Drawing.Point(130, 20)
$dnsServerComboBox.Size = New-Object System.Drawing.Size(200, 20)
$dnsServerComboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$form.Controls.Add($dnsServerComboBox)
# Populate DNS Server dropdown
$dnsServers = Get-AvailableDnsServers
foreach ($server in $dnsServers) {
$dnsServerComboBox.Items.Add($server)
}
if ($dnsServerComboBox.Items.Count -gt 0) {
$dnsServerComboBox.SelectedIndex = 0
}
# IP Range Selection Group
$ipRangeGroupBox = New-Object System.Windows.Forms.GroupBox
$ipRangeGroupBox.Text = "IP Range Selection"
$ipRangeGroupBox.Location = New-Object System.Drawing.Point(20, 50)
$ipRangeGroupBox.Size = New-Object System.Drawing.Size(750, 120)
$form.Controls.Add($ipRangeGroupBox)
# Radio buttons for range selection
$subnetRadioButton = New-Object System.Windows.Forms.RadioButton
$subnetRadioButton.Text = "Scan Full /24 Subnet"
$subnetRadioButton.Location = New-Object System.Drawing.Point(20, 20)
$subnetRadioButton.Size = New-Object System.Drawing.Size(150, 20)
$subnetRadioButton.Checked = $true
$ipRangeGroupBox.Controls.Add($subnetRadioButton)
$customRangeRadioButton = New-Object System.Windows.Forms.RadioButton
$customRangeRadioButton.Text = "Custom IP Range"
$customRangeRadioButton.Location = New-Object System.Drawing.Point(20, 50)
$customRangeRadioButton.Size = New-Object System.Drawing.Size(150, 20)
$ipRangeGroupBox.Controls.Add($customRangeRadioButton)
# Subnet IP entry
$subnetIPLabel = New-Object System.Windows.Forms.Label
$subnetIPLabel.Text = "Subnet IP Address:"
$subnetIPLabel.Location = New-Object System.Drawing.Point(180, 20)
$subnetIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($subnetIPLabel)
$subnetIPTextBox = New-Object System.Windows.Forms.TextBox
$subnetIPTextBox.Location = New-Object System.Drawing.Point(300, 20)
$subnetIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$subnetIPTextBox.Text = "192.168.1.1"
$ipRangeGroupBox.Controls.Add($subnetIPTextBox)
# Custom range IP entries
$startIPLabel = New-Object System.Windows.Forms.Label
$startIPLabel.Text = "Start IP Address:"
$startIPLabel.Location = New-Object System.Drawing.Point(180, 50)
$startIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($startIPLabel)
$startIPTextBox = New-Object System.Windows.Forms.TextBox
$startIPTextBox.Location = New-Object System.Drawing.Point(300, 50)
$startIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$startIPTextBox.Text = "192.168.1.1"
$startIPTextBox.Enabled = $false
$ipRangeGroupBox.Controls.Add($startIPTextBox)
$endIPLabel = New-Object System.Windows.Forms.Label
$endIPLabel.Text = "End IP Address:"
$endIPLabel.Location = New-Object System.Drawing.Point(460, 50)
$endIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($endIPLabel)
$endIPTextBox = New-Object System.Windows.Forms.TextBox
$endIPTextBox.Location = New-Object System.Drawing.Point(580, 50)
$endIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$endIPTextBox.Text = "192.168.1.254"
$endIPTextBox.Enabled = $false
$ipRangeGroupBox.Controls.Add($endIPTextBox)
# Radio button event handlers
$subnetRadioButton.Add_CheckedChanged({
if ($subnetRadioButton.Checked) {
$subnetIPTextBox.Enabled = $true
$startIPTextBox.Enabled = $false
$endIPTextBox.Enabled = $false
}
})
$customRangeRadioButton.Add_CheckedChanged({
if ($customRangeRadioButton.Checked) {
$subnetIPTextBox.Enabled = $false
$startIPTextBox.Enabled = $true
$endIPTextBox.Enabled = $true
}
})
# Auto-calculate subnet range from subnet IP
$subnetIPTextBox.Add_TextChanged({
if ($subnetRadioButton.Checked -and $subnetIPTextBox.Text -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$') {
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
$startIPTextBox.Text = $range.Start
$endIPTextBox.Text = $range.End
}
})
# Search Button
$searchButton = New-Object System.Windows.Forms.Button
$searchButton.Text = "Search DNS Records"
$searchButton.Location = New-Object System.Drawing.Point(20, 180)
$searchButton.Size = New-Object System.Drawing.Size(150, 30)
$form.Controls.Add($searchButton)
# Status Label
$statusLabel = New-Object System.Windows.Forms.Label
$statusLabel.Text = "Ready"
$statusLabel.Location = New-Object System.Drawing.Point(180, 185)
$statusLabel.Size = New-Object System.Drawing.Size(590, 20)
$form.Controls.Add($statusLabel)
# Results DataGridView
$resultsDataGridView = New-Object System.Windows.Forms.DataGridView
$resultsDataGridView.Location = New-Object System.Drawing.Point(20, 220)
$resultsDataGridView.Size = New-Object System.Drawing.Size(750, 300)
$resultsDataGridView.AutoSizeColumnsMode = [System.Windows.Forms.DataGridViewAutoSizeColumnsMode]::Fill
$resultsDataGridView.AllowUserToAddRows = $false
$resultsDataGridView.AllowUserToDeleteRows = $false
$resultsDataGridView.ReadOnly = $true
$resultsDataGridView.MultiSelect = $false
$resultsDataGridView.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect
$form.Controls.Add($resultsDataGridView)
# Export Button
$exportButton = New-Object System.Windows.Forms.Button
$exportButton.Text = "Export Results"
$exportButton.Location = New-Object System.Drawing.Point(20, 530)
$exportButton.Size = New-Object System.Drawing.Size(120, 30)
$exportButton.Enabled = $false
$form.Controls.Add($exportButton)
# Search button click event
$searchButton.Add_Click({
$statusLabel.Text = "Searching DNS records..."
$resultsDataGridView.DataSource = $null
$exportButton.Enabled = $false
$selectedDnsServer = $dnsServerComboBox.SelectedItem.ToString()
$ipRangeStart = ""
$ipRangeEnd = ""
if ($subnetRadioButton.Checked) {
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
$ipRangeStart = $range.Start
$ipRangeEnd = $range.End
} else {
$ipRangeStart = $startIPTextBox.Text
$ipRangeEnd = $endIPTextBox.Text
}
$results = Search-DnsRecords -DnsServer $selectedDnsServer -IPRangeStart $ipRangeStart -IPRangeEnd $ipRangeEnd
if ($results.Count -gt 0) {
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("IPAddress", [string])
$dataTable.Columns.Add("Hostname", [string])
$dataTable.Columns.Add("Zone", [string])
foreach ($result in $results) {
$dataTable.Rows.Add($result.IPAddress.ToString(), $result.Hostname, $result.Zone)
}
$resultsDataGridView.DataSource = $dataTable
$statusLabel.Text = "Found $($results.Count) DNS records"
$exportButton.Enabled = $true
} else {
$statusLabel.Text = "No DNS records found in the specified range"
}
})
# Export button click event
$exportButton.Add_Click({
$saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveFileDialog.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
$saveFileDialog.Title = "Export DNS Records"
$saveFileDialog.FileName = "DNSRecords_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
if ($saveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$dataTable = $resultsDataGridView.DataSource
$dataTable | Export-Csv -Path $saveFileDialog.FileName -NoTypeInformation
$statusLabel.Text = "Exported to $($saveFileDialog.FileName)"
}
})
# Show the form
[void]$form.ShowDialog()