udfx.git

udfx

~
git clone https://github.com/debuman/udfx.git
commit 25e997c7f6d29f9d312ae83cf050d03b7f861cd3
Author: unknown <hjan@aispera.com>
Date: Fri, 6 Feb 2026 18:19:10 +0900

Initial commit: UDFX v1.0.0

Diffstat:
A.gitignore | 17+++++++++++++++++
ADEVELOPMENT.md | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AGet-ADDnsRecords.ps1 | 378+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALICENSE | 21+++++++++++++++++++++
AREADME.md | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 719 insertion(+), 0 deletion(-)

diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,17 @@
+# Output files
+dns_records.csv
+dns_records.json
+dns_records.txt
+dns_records_root_domains.csv
+*.log
+
+# Windows
+Thumbs.db
+Desktop.ini
+
+# IDE
+.vscode/
+.idea/
+
+# Claude Code
+.claude/
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
@@ -0,0 +1,184 @@
+# UDFX - Ultimate Domain Finder X 개발 명세서
+
+## 프로젝트 정보
+
+| 항목 | 내용 |
+|------|------|
+| 프로젝트명 | UDFX (Ultimate Domain Finder X) |
+| 버전 | 1.0.0 |
+| 개발일 | 2025-02-06 |
+| 개발언어 | PowerShell |
+| 대상환경 | Windows Server / Windows 10+ |
+
+## 개발 배경
+
+- 에어갭(Air-Gap) 환경에서 사용 가능한 도메인 탐색 도구 필요
+- 기존 도구(usfx 등)는 인터넷 연결 또는 DNS 브루트포스 방식에 의존
+- AD 통합 DNS의 경우 LDAP을 통해 직접 레코드 조회 가능
+
+## 아키텍처
+
+```
+┌─────────────────────────────────────────────────────────┐
+│                 UDFX (Get-ADDnsRecords.ps1)             │
+├─────────────────────────────────────────────────────────┤
+│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
+│  │ Zone 검색   │→ │ Record 수집 │→ │ 결과 출력       │  │
+│  │ (LDAP)      │  │ (dnsRecord) │  │ (CSV/JSON/TXT)  │  │
+│  └─────────────┘  └─────────────┘  └─────────────────┘  │
+└─────────────────────────────────────────────────────────┘
+                           │
+                           ▼
+              ┌────────────────────────┐
+              │  Active Directory      │
+              │  DC=DomainDnsZones     │
+              │  (LDAP Query)          │
+              └────────────────────────┘
+```
+
+## 핵심 함수
+
+### Get-RootDomain
+
+루트 도메인 추출 함수
+
+```powershell
+function Get-RootDomain {
+    param([string]$domain)
+    # .co.kr, .or.kr 등 3단계 TLD 처리
+    # 일반 도메인: example.com → example.com
+    # 한국 도메인: example.co.kr → example.co.kr
+}
+```
+
+**지원 TLD:**
+- 일반: .com, .net, .org, .io 등
+- 한국: .co.kr, .or.kr, .go.kr, .ac.kr 등
+- 영국: .co.uk, .org.uk 등
+- 일본: .co.jp, .or.jp 등
+
+### Get-DnsNameFromRecord
+
+AD DNS 바이너리 레코드에서 도메인명 추출
+
+```powershell
+function Get-DnsNameFromRecord {
+    param(
+        [byte[]]$data,
+        [int]$offset
+    )
+    # DNS wire format (길이-프리픽스) 파싱
+    # 라벨별로 분리 후 점(.)으로 결합
+}
+```
+
+**DNS 레코드 바이너리 구조:**
+```
+Offset  | Size | Field
+--------|------|------------------
+0-1     | 2    | Data Length
+2-3     | 2    | Record Type
+4-7     | 4    | Version/Serial
+8-11    | 4    | TTL
+12-15   | 4    | Reserved
+16-19   | 4    | Timestamp
+20-23   | 4    | Reserved
+24+     | N    | Record Data
+```
+
+### Convert-DNSRecord
+
+바이너리 DNS 레코드를 파싱하여 구조화된 데이터로 변환
+
+```powershell
+function Convert-DNSRecord {
+    param([byte[]]$RecordData)
+    # Record Type에 따라 적절한 파싱 수행
+    # A: IPv4 (4 bytes)
+    # AAAA: IPv6 (16 bytes)
+    # NS/CNAME: DNS Name
+    # MX: Priority(2) + DNS Name
+    # SRV: Priority(2) + Weight(2) + Port(2) + DNS Name
+}
+```
+
+## 레코드 타입 코드
+
+| 타입 | 코드 | 데이터 형식 |
+|------|------|-------------|
+| A | 1 | 4 bytes (IPv4) |
+| NS | 2 | DNS Name |
+| CNAME | 5 | DNS Name |
+| SOA | 6 | DNS Name + Serial 등 |
+| PTR | 12 | DNS Name |
+| MX | 15 | 2 bytes (Priority) + DNS Name |
+| TXT | 16 | Length-prefixed string |
+| AAAA | 28 | 16 bytes (IPv6) |
+| SRV | 33 | 6 bytes (Pri/Wt/Port) + DNS Name |
+
+## LDAP 쿼리 구조
+
+### DNS Zone 검색
+
+```
+Base DN: DC=DomainDnsZones,DC=corp,DC=example,DC=com
+Filter: (objectClass=dnsZone)
+```
+
+### DNS Record 검색
+
+```
+Base DN: DC=<ZoneName>,CN=MicrosoftDNS,DC=DomainDnsZones,...
+Filter: (objectClass=dnsNode)
+Attributes: name, dnsRecord
+```
+
+## 알려진 이슈
+
+### 1. NS/SRV 레코드 이름 파싱
+
+**현상**: NS, SRV 레코드의 대상 호스트명이 점(.) 없이 출력됨
+
+```
+예: hq-dc-01corpexamplecom (실제: hq-dc-01.corp.example.com)
+```
+
+**원인**: AD DNS 바이너리 포맷의 첫 바이트(전체 이름 길이)와 라벨 구분 처리 문제
+
+**상태**: 미해결 (A 레코드 IP는 정상 동작)
+
+### 2. SRV 레코드 포트/우선순위 값
+
+**현상**: 포트, 우선순위, 가중치 값이 비정상적으로 표시됨
+
+**원인**: 빅엔디안/리틀엔디안 바이트 순서 문제
+
+**상태**: 부분 해결
+
+## 향후 개선 사항
+
+1. [ ] NS/SRV 레코드 이름 파싱 정확도 개선
+2. [ ] Excel 다중 시트 출력 지원 (COM 또는 ImportExcel 모듈)
+3. [ ] 역방향 DNS (PTR) 대역 스캔 기능 추가
+4. [ ] 결과 비교 기능 (이전 스캔과 차이점 분석)
+5. [ ] HTML 리포트 생성 기능
+
+## 파일 구조
+
+```
+UDFX/
+├── Get-ADDnsRecords.ps1    # 메인 스크립트
+├── README.md               # 사용자 매뉴얼
+├── DEVELOPMENT.md          # 개발 명세서
+└── [출력 파일]
+    ├── dns_records.csv
+    ├── dns_records_root_domains.csv
+    ├── dns_records.json
+    └── dns_records.txt
+```
+
+## 참고 자료
+
+- [MS-DNSP: Domain Name Service Protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/)
+- [AD DNS Record Binary Format](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/f97756c9-3783-428b-9451-b376f877f238)
+- [USFX - Ultimate Subdomain Finder X](https://github.com/devastator-x/usfx)
diff --git a/Get-ADDnsRecords.ps1 b/Get-ADDnsRecords.ps1
@@ -0,0 +1,378 @@
+<#
+.SYNOPSIS
+    UDFX - Ultimate Domain Finder X
+    AD 통합 DNS 레코드를 LDAP으로 직접 조회하는 에어갭 환경용 도구
+.DESCRIPTION
+    도메인 사용자 권한으로 Active Directory에 저장된 DNS 레코드를 조회합니다.
+    인터넷 연결 없이 에어갭 환경에서 사용 가능합니다.
+.EXAMPLE
+    .\Get-ADDnsRecords.ps1 -Domain corp.example.com
+    .\Get-ADDnsRecords.ps1 -Domain corp.example.com -Output results
+.NOTES
+    Version: 1.0.0
+    Author: UDFX Project
+#>
+
+param(
+    [Parameter(Mandatory=$true)]
+    [string]$Domain,
+
+    [string]$Output = "dns_records",
+
+    [switch]$ShowDebug
+)
+
+$banner = @"
+
+    __  ______  _________  __
+   / / / / __ \/ ____/ |/ /
+  / / / / / / / /_   |   /
+ / /_/ / /_/ / __/  /   |
+ \____/_____/_/    /_/|_|
+
+ ╔═══════════════════════════════════════════════════╗
+ ║  Ultimate Domain Finder X                         ║
+ ║  Air-Gap AD DNS Enumeration Tool v1.0             ║
+ ╠═══════════════════════════════════════════════════╣
+ ║  [*] LDAP-based AD DNS Record Extraction          ║
+ ║  [*] No Internet Connection Required              ║
+ ║  [*] Domain User Privileges Only                  ║
+ ╚═══════════════════════════════════════════════════╝
+
+"@
+
+Write-Host $banner -ForegroundColor Cyan
+
+# 루트 도메인 추출 함수
+function Get-RootDomain {
+    param([string]$domain)
+
+    $parts = $domain.Split(".")
+    if ($parts.Count -lt 2) { return $domain }
+
+    # .co.kr, .or.kr, .go.kr, .ac.kr 등 3단계 TLD 처리
+    if ($parts.Count -ge 3) {
+        $sld = $parts[-2]
+        $tld = $parts[-1]
+        if ($tld -eq "kr" -and $sld -match "^(co|or|go|ac|ne|re|pe|hs|ms|es|sc|kg)$") {
+            return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+        }
+        if ($tld -eq "uk" -and $sld -match "^(co|org|ac|gov)$") {
+            return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+        }
+        if ($tld -eq "jp" -and $sld -match "^(co|or|ac|go|ne)$") {
+            return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+        }
+    }
+
+    # 일반 도메인: example.com, example.io
+    return "$($parts[-2]).$($parts[-1])"
+}
+
+# DNS 이름 파싱 함수
+function Get-DnsNameFromRecord {
+    param(
+        [byte[]]$data,
+        [int]$offset
+    )
+
+    $nameParts = @()
+    $pos = $offset
+
+    try {
+        while ($pos -lt $data.Length) {
+            $len = $data[$pos]
+            if ($len -eq 0) { break }
+            if ($len -gt 63) { break }
+            if (($pos + 1 + $len) -gt $data.Length) { break }
+
+            $label = [System.Text.Encoding]::ASCII.GetString($data, $pos + 1, $len)
+            $nameParts += $label
+            $pos += $len + 1
+        }
+    } catch {
+        return "unknown"
+    }
+
+    if ($nameParts.Count -eq 0) { return "" }
+    return ($nameParts -join ".")
+}
+
+# DNS 레코드 변환 함수
+function Convert-DNSRecord {
+    param([byte[]]$RecordData)
+
+    if ($RecordData.Length -lt 24) { return $null }
+
+    $recordType = [BitConverter]::ToUInt16($RecordData, 2)
+
+    $typeName = switch ($recordType) {
+        1 { "A" }
+        2 { "NS" }
+        5 { "CNAME" }
+        6 { "SOA" }
+        12 { "PTR" }
+        15 { "MX" }
+        16 { "TXT" }
+        28 { "AAAA" }
+        33 { "SRV" }
+        default { "TYPE$recordType" }
+    }
+
+    $result = @{
+        Type = $typeName
+        TypeId = $recordType
+        Data = ""
+    }
+
+    try {
+        switch ($recordType) {
+            1 { # A Record
+                if ($RecordData.Length -ge 28) {
+                    $ip = "{0}.{1}.{2}.{3}" -f $RecordData[24], $RecordData[25], $RecordData[26], $RecordData[27]
+                    $result.Data = $ip
+                }
+            }
+            28 { # AAAA Record
+                if ($RecordData.Length -ge 40) {
+                    $ipv6Bytes = $RecordData[24..39]
+                    $ip = [System.Net.IPAddress]::new($ipv6Bytes).ToString()
+                    $result.Data = $ip
+                }
+            }
+            2 { # NS Record
+                $result.Data = Get-DnsNameFromRecord $RecordData 24
+            }
+            5 { # CNAME Record
+                $result.Data = Get-DnsNameFromRecord $RecordData 24
+            }
+            12 { # PTR Record
+                $result.Data = Get-DnsNameFromRecord $RecordData 24
+            }
+            15 { # MX Record
+                if ($RecordData.Length -ge 28) {
+                    $priority = [BitConverter]::ToUInt16($RecordData, 24)
+                    $exchange = Get-DnsNameFromRecord $RecordData 26
+                    $result.Data = "[$priority] $exchange"
+                }
+            }
+            6 { # SOA Record
+                $result.Data = Get-DnsNameFromRecord $RecordData 24
+            }
+            16 { # TXT Record
+                if ($RecordData.Length -gt 24) {
+                    $txtLen = $RecordData[24]
+                    if ($txtLen -gt 0 -and $RecordData.Length -ge (25 + $txtLen)) {
+                        $result.Data = [System.Text.Encoding]::ASCII.GetString($RecordData, 25, $txtLen)
+                    }
+                }
+            }
+            33 { # SRV Record
+                if ($RecordData.Length -ge 32) {
+                    $priority = [BitConverter]::ToUInt16($RecordData, 24)
+                    $weight = [BitConverter]::ToUInt16($RecordData, 26)
+                    $port = [BitConverter]::ToUInt16($RecordData, 28)
+                    $target = Get-DnsNameFromRecord $RecordData 30
+                    $result.Data = "${target}:$port (pri:$priority wt:$weight)"
+                }
+            }
+            default {
+                $result.Data = "Binary (type:$recordType)"
+            }
+        }
+    } catch {
+        $result.Data = "Parse error"
+    }
+
+    return $result
+}
+
+# 메인 실행
+Write-Host "[*] Target Domain: $Domain" -ForegroundColor White
+Write-Host ""
+
+# 도메인 DN 생성
+$domainParts = $Domain.Split(".")
+$domainDN = ($domainParts | ForEach-Object { "DC=$_" }) -join ","
+
+Write-Host "[*] Searching for DNS Zones in Active Directory..." -ForegroundColor Cyan
+
+# DNS 영역 검색
+$zones = @()
+$searchBase = "LDAP://DC=DomainDnsZones,$domainDN"
+
+try {
+    $searcher = New-Object DirectoryServices.DirectorySearcher
+    $searcher.SearchRoot = [ADSI]$searchBase
+    $searcher.Filter = "(objectClass=dnsZone)"
+    $searcher.PageSize = 1000
+
+    $results = $searcher.FindAll()
+    foreach ($result in $results) {
+        $zoneName = $result.Properties["name"][0]
+        if ($zoneName -and $zoneName -ne "RootDNSServers") {
+            $zones += @{
+                Name = $zoneName
+                Path = $result.Path
+            }
+        }
+    }
+} catch {
+    Write-Host "[!] Error accessing DNS zones: $_" -ForegroundColor Red
+    exit 1
+}
+
+if ($zones.Count -eq 0) {
+    Write-Host "[!] No DNS zones found." -ForegroundColor Red
+    exit 1
+}
+
+Write-Host "[+] Found $($zones.Count) DNS zone(s)" -ForegroundColor Green
+Write-Host ""
+
+# 모든 레코드 수집
+$allRecords = @()
+
+foreach ($zone in $zones) {
+    Write-Host "[*] Dumping: $($zone.Name)" -ForegroundColor Cyan
+
+    try {
+        $zoneSearcher = New-Object DirectoryServices.DirectorySearcher
+        $zoneSearcher.SearchRoot = [ADSI]$zone.Path
+        $zoneSearcher.Filter = "(objectClass=dnsNode)"
+        $zoneSearcher.PageSize = 1000
+        $zoneSearcher.PropertiesToLoad.AddRange(@("name", "dnsRecord"))
+
+        $nodeResults = $zoneSearcher.FindAll()
+        $zoneRecordCount = 0
+
+        foreach ($node in $nodeResults) {
+            $nodeName = $node.Properties["name"][0]
+            $dnsRecords = $node.Properties["dnsRecord"]
+
+            if ($nodeName -eq "@") {
+                $fqdn = $zone.Name
+            } else {
+                $fqdn = "$nodeName.$($zone.Name)"
+            }
+
+            foreach ($recordData in $dnsRecords) {
+                $parsed = Convert-DNSRecord -RecordData $recordData
+                if ($parsed -and $parsed.Data -and $parsed.Type -ne "SOA") {
+                    # Zone 유형 분류
+                    $zoneType = "External"
+                    if ($zone.Name -eq $Domain) {
+                        $zoneType = "Primary"
+                    } elseif ($zone.Name.EndsWith(".$Domain")) {
+                        $zoneType = "Subdomain"
+                    }
+
+                    # 루트 도메인 추출
+                    $rootDomain = Get-RootDomain $zone.Name
+
+                    $record = [PSCustomObject]@{
+                        Domain = $fqdn
+                        RecordType = $parsed.Type
+                        Value = $parsed.Data
+                        Zone = $zone.Name
+                        ZoneType = $zoneType
+                        RootDomain = $rootDomain
+                    }
+                    $allRecords += $record
+                    $zoneRecordCount++
+
+                    if ($ShowDebug) {
+                        Write-Host "    [$($parsed.Type)] $fqdn -> $($parsed.Data)" -ForegroundColor Gray
+                    }
+                }
+            }
+        }
+
+        Write-Host "    Found $zoneRecordCount records" -ForegroundColor Gray
+
+    } catch {
+        Write-Host "    [!] Error: $_" -ForegroundColor Red
+    }
+}
+
+Write-Host ""
+Write-Host "[*] Saving results..." -ForegroundColor Cyan
+
+# JSON 출력
+$jsonOutput = @{
+    Target = $Domain
+    ScanTime = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
+    TotalRecords = $allRecords.Count
+    ZoneCount = $zones.Count
+    Zones = $zones | ForEach-Object { $_.Name }
+    Records = $allRecords
+} | ConvertTo-Json -Depth 10
+$jsonOutput | Out-File -FilePath "$Output.json" -Encoding UTF8
+
+# CSV 출력
+$allRecords | Export-Csv -Path "$Output.csv" -NoTypeInformation -Encoding UTF8
+
+# Root Domain CSV 출력 (중복 제거)
+$uniqueRootDomains = $allRecords | Select-Object -ExpandProperty RootDomain -Unique | Sort-Object | ForEach-Object {
+    [PSCustomObject]@{
+        RootDomain = $_
+    }
+}
+$uniqueRootDomains | Export-Csv -Path "${Output}_root_domains.csv" -NoTypeInformation -Encoding UTF8
+
+# TXT 출력
+$txtContent = @"
+# AD DNS Record Dump
+# Target: $Domain
+# Time: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
+# Total Records: $($allRecords.Count)
+# Zones: $($zones.Count)
+#
+# Format: RootDomain | ZoneType | Type | Domain | Value | Zone
+# =============================================================
+
+"@
+foreach ($record in $allRecords) {
+    $txtContent += "$($record.RootDomain) | $($record.ZoneType) | $($record.RecordType) | $($record.Domain) | $($record.Value) | $($record.Zone)`n"
+}
+$txtContent | Out-File -FilePath "$Output.txt" -Encoding UTF8
+
+Write-Host ""
+Write-Host "========== SCAN COMPLETE ==========" -ForegroundColor Green
+Write-Host "Total Zones: $($zones.Count)" -ForegroundColor White
+Write-Host "Total Records: $($allRecords.Count)" -ForegroundColor White
+Write-Host ""
+Write-Host "Results saved to:" -ForegroundColor White
+Write-Host "    - $Output.json" -ForegroundColor Cyan
+Write-Host "    - $Output.csv" -ForegroundColor Cyan
+Write-Host "    - ${Output}_root_domains.csv (unique root domains)" -ForegroundColor Cyan
+Write-Host "    - $Output.txt" -ForegroundColor Cyan
+Write-Host "===================================" -ForegroundColor Green
+
+# 루트 도메인 목록
+Write-Host ""
+Write-Host "Root Domains Found:" -ForegroundColor White
+$allRecords | Select-Object -ExpandProperty RootDomain -Unique | Sort-Object | ForEach-Object {
+    Write-Host "    $_" -ForegroundColor Gray
+}
+
+# Zone 유형별 통계
+Write-Host ""
+Write-Host "Records by Zone Type:" -ForegroundColor White
+$allRecords | Group-Object ZoneType | Sort-Object Count -Descending | ForEach-Object {
+    Write-Host "    $($_.Name): $($_.Count)" -ForegroundColor Gray
+}
+
+# 레코드 타입별 통계
+Write-Host ""
+Write-Host "Records by Record Type:" -ForegroundColor White
+$allRecords | Group-Object RecordType | Sort-Object Count -Descending | ForEach-Object {
+    Write-Host "    $($_.Name): $($_.Count)" -ForegroundColor Gray
+}
+
+# 상위 도메인 출력
+Write-Host ""
+Write-Host "Sample Records (first 20):" -ForegroundColor White
+$allRecords | Select-Object -First 20 | ForEach-Object {
+    Write-Host "    [$($_.RecordType)] $($_.Domain) -> $($_.Value)" -ForegroundColor Gray
+}
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 UDFX Project
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
@@ -0,0 +1,119 @@
+# UDFX - Ultimate Domain Finder X
+
+Active Directory 통합 DNS에서 도메인 및 DNS 레코드를 수집하는 에어갭 환경용 도구입니다.
+
+## 개요
+
+- **목적**: AD DNS에 등록된 모든 도메인/서브도메인 및 레코드 수집
+- **환경**: Windows 도메인 환경 (에어갭 지원)
+- **권한**: 일반 도메인 사용자 권한으로 실행 가능
+- **방식**: LDAP을 통한 AD DNS 직접 조회
+
+## 요구사항
+
+- Windows PowerShell 5.1 이상
+- Active Directory 도메인 가입된 시스템
+- 도메인 사용자 계정
+
+## 사용법
+
+### 기본 실행
+
+```powershell
+.\Get-ADDnsRecords.ps1 -Domain <도메인명>
+```
+
+### 예시
+
+```powershell
+# 기본 실행
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com
+
+# 출력 파일명 지정
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com -Output scan_results
+
+# 디버그 모드 (상세 출력)
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com -ShowDebug
+```
+
+### 파라미터
+
+| 파라미터 | 필수 | 설명 | 기본값 |
+|----------|------|------|--------|
+| `-Domain` | O | 대상 AD 도메인명 | - |
+| `-Output` | X | 출력 파일 기본명 | dns_records |
+| `-ShowDebug` | X | 상세 출력 활성화 | False |
+
+## 출력 파일
+
+| 파일 | 설명 |
+|------|------|
+| `dns_records.csv` | 전체 DNS 레코드 (CSV) |
+| `dns_records_root_domains.csv` | 루트 도메인 목록 (중복 제거) |
+| `dns_records.json` | 전체 DNS 레코드 (JSON) |
+| `dns_records.txt` | 전체 DNS 레코드 (텍스트) |
+
+## 출력 필드
+
+| 필드 | 설명 | 예시 |
+|------|------|------|
+| Domain | FQDN | vcsa.example.com |
+| RecordType | DNS 레코드 타입 | A, NS, CNAME, MX, SRV, TXT |
+| Value | 레코드 값 | 10.1.10.100 |
+| Zone | DNS 영역명 | vcsa.example.com |
+| ZoneType | 영역 분류 | Primary, Subdomain, External |
+| RootDomain | 루트 도메인 | example.com |
+
+### ZoneType 분류
+
+| 타입 | 설명 |
+|------|------|
+| Primary | 메인 AD 도메인 |
+| Subdomain | 메인 도메인의 서브도메인 |
+| External | 외부 도메인 |
+
+## 지원 레코드 타입
+
+- **A**: IPv4 주소
+- **AAAA**: IPv6 주소
+- **NS**: 네임서버
+- **CNAME**: 별칭
+- **MX**: 메일 서버
+- **SRV**: 서비스 레코드
+- **TXT**: 텍스트 레코드
+- **PTR**: 역방향 DNS
+
+## 활용 예시
+
+### 내부 IP 호스트만 필터링
+
+```powershell
+Import-Csv .\dns_records.csv | Where-Object {
+    $_.RecordType -eq "A" -and
+    ($_.Value -match "^10\." -or $_.Value -match "^172\.(1[6-9]|2[0-9]|3[01])\." -or $_.Value -match "^192\.168\.")
+} | Export-Csv .\internal_hosts.csv -NoTypeInformation
+```
+
+### 특정 도메인만 필터링
+
+```powershell
+Import-Csv .\dns_records.csv | Where-Object {
+    $_.RootDomain -eq "example.com"
+} | Export-Csv .\filtered_records.csv -NoTypeInformation
+```
+
+### 루트 도메인 목록 확인
+
+```powershell
+Import-Csv .\dns_records_root_domains.csv
+```
+
+## 제한사항
+
+- AD 통합 DNS만 지원 (독립 DNS 서버 미지원)
+- NS, SRV 레코드의 대상 호스트명에 점(.)이 누락될 수 있음
+- Zone Transfer가 허용되지 않은 환경에서는 LDAP 방식으로 대체
+
+## 라이선스
+
+MIT License