# 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()