Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions windows/powershell/dnscheck.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
param (
# Domain name being checked
[Parameter(Mandatory = $false)]
[string]$Name,

# These 2 are only for listing
[Parameter(Mandatory = $false)]
[string]$DnsServer,

[switch]$List
)

# Usage was done by AI but its so cool
function Show-Usage {
Write-Host "`nUsage:" -ForegroundColor Yellow
Write-Host " .\$(Split-Path -Leaf $PSCommandPath) -Name <DomainName> [-List] [-DnsServer <ServerNameOrIP>]" -ForegroundColor White
Write-Host "`nParameters:" -ForegroundColor Yellow
Write-Host " -Name Domain name to resolve or check." -ForegroundColor White
Write-Host " -List List all records for the given domain (requires -DnsServer)." -ForegroundColor White
Write-Host " -DnsServer Target DNS server for listing." -ForegroundColor White
Write-Host "`nExamples:" -ForegroundColor Yellow
Write-Host " Check DNS servers and resolve a name:" -ForegroundColor White
Write-Host " .\dnscheck.ps1 -Name example.com" -ForegroundColor DarkGray
Write-Host " List records from a specific DNS server:" -ForegroundColor White
Write-Host " .\dnscheck.ps1 -Name example.com -List -DnsServer 192.168.1.1" -ForegroundColor DarkGray
Write-Host ""
}

# Show usage if parameters are invalid
if ($List -and -not $DnsServer) {
Write-Error "You must specify -DnsServer when using -List."
Show-Usage
exit 1
}

if (-not $Name) {
Write-Error "Missing required parameter: -Name."
Show-Usage
exit 1
}


# Function returns all of the records on a given DNS server. Only run when List is true
function Show-Records {
param(
[string]$Target,
[string]$Zone
)

try {
$records = dnscmd $Target /enumrecords $Zone '@' 2>&1
# since dnscmd is a cmd utility and not a cmdlet, error handling was a bit weird. This should work
if ($LASTEXITCODE -ne 0) {
throw "Failed to enumerate records from $Target"
}
# Returns the string value of dnscommand
$records
}
catch {
Write-Error "Error retrieving DNS records: $_"
}
}


function Test-Servers {
$dnsInfo = Get-DnsClientServerAddress | # Grabs all DNS servers for each interface
Where-Object { $_.AddressFamily -eq 2 } | # Only ones with ipv4 addresses
Select-Object InterfaceAlias, ServerAddresses # Selects both the interface its on, and the IP of the dns server

foreach ($entry in $dnsInfo) {
if (-not $entry.ServerAddresses -or $entry.ServerAddresses.Count -eq 0) { # if the entry is either null or 0, skip it. This does happen, as if the record is only ipv6 then it will still grab it unfortunatly
continue # Continue is neat- it skips the current loop but doesnt break and moves on to the next item
}


# if you are struggling to read the next 2 lines, its nested arrays.
Write-Host "`nInterface: $($entry.InterfaceAlias)" -ForegroundColor Cyan
foreach ($server in $entry.ServerAddresses) {
Write-Host -NoNewline "Checking DNS server: $server... "
# Test-NetConnection returns a bool when Informationlevel is set to Quiet. very neat!
if (Test-NetConnection -ComputerName $server -Port 53 -InformationLevel Quiet -ErrorAction SilentlyContinue) {
Write-Host "Port 53 Reachable and accepting." -ForegroundColor Green
}
else {
# Actually a great error check. This step *can* be slow, but it will give an overview of if it can connect to the host VIA ICMP, what its route was, etc etc.
Write-Host "ICMP Check Failed. Target may be unreachable, or Port 53 may be closed" -ForegroundColor Red
Test-NetConnection -ComputerName $server -TraceRoute -informationlevel detailed
}
}
}
}

function Resolve-Dns {
param(
[string]$QueryName
)

try {
# prints out the responding DNS server, along with its address
$nsResult = nslookup $QueryName 2>&1 | Where-Object { $_ -match '^(Server:|Address:)' }
if ($nsResult) {
Write-Host "`nNSLookup Results:" -ForegroundColor Yellow
$nsResult
}
else {
Write-Warning "No nslookup results. Check to see if computer is on fire and/or someone ran chatgpt powershell"
}

# Resolve-DnsName
Write-Host "`nResolve-DnsName Results:" -ForegroundColor Yellow
Resolve-DnsName -Name $QueryName -ErrorAction Stop # throws if an error occurs. Otherwise prints all of the records associated with the query
}
catch {
Write-Host "DNS resolution failed." -ForegroundColor Red
Write-Warning $_.Exception.Message
}
}

# --- Main ---

if ($List) {
if (-not $DnsServer) {
Write-Error "You must specify a target DNS server with -DnsServer when using -List."
exit 1
}
Show-Records -Target $DnsServer -Zone $Name
}
else {
Test-Servers
Resolve-Dns -QueryName $Name
}




49 changes: 49 additions & 0 deletions windows/powershell/ldapcheck.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Script still in testing phase. Idea behind it is very cool, but complexity is high, and I want to be able to document it well

# Prompt user for input
# Hard code domain prior to running in comp

# Will add the ability to pass in parameters later, but for now I need to run more testing first
$domain = Read-Host "Enter domain (example.com)"
$username = Read-Host "Enter username"
$password = Read-Host "Enter password" -AsSecureString
# Prevents the password from being displayed in plain text in the console. This makes the script messier, but more secure.
# When marshal is used to convert the secure string to a plain text string, it will expose the password in memory. This is not ideal
# Solution to the memory problem given by AI:
#$ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
#$plainPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto($ptr)

# Zero out and free the unmanaged memory (important for security)
#[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr)
# Requires more testing to see if this is trustworthy or neccesary


# Convert secure string to plain text for LDAP use
# Marshal is a NET class used to convert between managed and unmanaged code (In this case, raw memory)
# Second half turns the secure string into a BSTR (Binary String), and then returns a pointer to that BSTR (This is the piece that exposes the password in memory)
# The pointer is then converted to a plain string using the PtrToStringAuto
$plainPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
)

# Construct the LDAP path and credentials
$ldapPath = "LDAP://$domain"
$userPrincipal = "$domain\$username"

try {
# Create the DirectoryEntry object with credentials
# This does not create an object in the directory, it creates a local object that represents the LDAP path and credentials you want to use to access it
$entry = New-Object System.DirectoryServices.DirectoryEntry($ldapPath, $userPrincipal, $plainPassword)

# Attempt to access a property to trigger the bind
# This takes the path and credentials you provided before, and attempts to bind to the LDAP server using those credentials
# This seems like a really weird and specific way to do this, but stackoverflow said it was a good idea, and I cant see any reason why it wouldnt wory or be insecure.
$native = $entry.NativeObject

Write-Host "LDAP authentication successful."
}
catch {
Write-Host "LDAP connection to $domain as $username failed with error:" -ForegroundColor Red
Write-Host $_.Exception.GetType().FullName "`n" -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
}