adPEAS v2 Episode 5: Output & Reports - From Scan to Deliverable
How adPEAS v2 turns scan results into actionable output: color-coded console, interactive HTML reports, incremental scanning, offline conversion, and report diffing.
Introduction
In Episode 4 we saw which security checks adPEAS performs and what vulnerabilities it can uncover. But a scan is only as good as its output. What good is the most thorough check if the results get buried in a wall of text?
Anyone who runs pentests regularly knows the problem: the raw data is there, but getting from scan results to a client deliverable often takes more time than the scan itself. adPEAS solves this with a well-designed output system that serves three audiences: the pentester during live analysis, the report writer during documentation, and the client reading the final report.
Specifically, adPEAS offers two output modes:
- Console Output - Color-coded real-time output for interactive work
- File Reports - Text and/or HTML for documentation and client deliverables
Both modes internally use the same RenderModel pipeline, which ensures that severity classification remains consistent - whether on the console or in the HTML report. We’ll take a closer look at how this works in detail at the end of this post.
Part 1: Console Output
The console output is what you interact with most during day-to-day work. During a scan, the output scrolls by in real time - and the color-coded symbols ensure that critical findings immediately catch your eye. You don’t need to read the entire output; a glance at the colors is enough.
Symbols and Colors
adPEAS uses five color-coded symbols to categorize findings:
| Symbol | Color | Meaning | Example |
|---|---|---|---|
[?] | Blue | Section Header | [?] Analyzing Domain Configuration |
[!] | Red | Finding - Security issue | [!] minPwdLength: 3 characters |
[+] | Yellow | Hint - Worth investigating | [+] lockoutThreshold: Disabled |
[*] | Green | Note - Information | [*] Found 2 domain controller(s) |
[#] | Red on Yellow | Secure - Good configuration | [#] AdminSDHolder ACLs are secure |
A quick glance at the colors tells you where the fire is.
Real Console Output
So what does this look like in practice? Here’s an excerpt from an adPEAS scan:
_ _____ ______ _____
| | __ \| ____| /\ / ____|
____ __| | |__) | |__ / \ | (___
/ _ |/ _ | ___/| __| / /\ \ \___ \
| (_| | (_| | | | |____ / ____ \ ____) |
\__,_|\__,_|_| |______/_/ \_\_____/
Version 2.0.0
Active Directory Enumeration
by @61106960
Legend
[?] Searching for juicy information
[!] Found a vulnerability which may be exploitable
[+] Found some interesting information for further investigation
[*] Some kind of note
[#] Some kind of secure configuration
======================================================================
+++++ Establishing LDAP Connection +++++
======================================================================
[*] Successfully connected to domain 'contoso.com' on server 'DC01.contoso.com' as 'CONTOSO\jsmith' via Kerberos (SSPI)
Executing Modules: Domain, Creds, Rights, Delegation, ADCS, Accounts, GPO, Computer, Application, Bloodhound
======================================================================
+++++ Analyzing Domain Configuration +++++
======================================================================
[?] Analyzing password policy...
[!] Found password policy:
[!] minPwdLength: 3 characters
minPwdAge: 1 days
maxPwdAge: 42 days
passwordComplexity: Enabled
[+] lockoutThreshold: Disabled
[?] Analyzing LDAP Signing/Channel Binding via GPO (SYSVOL)...
[+] Found LDAP security configuration in 2 GPO(s):
displayName: Default Domain Policy
[!] LDAPSigning: Not Configured
[!] ChannelBinding: Not Configured
[#] AnonymousBinding: Restricted
Output Structure
Every scan follows a fixed structure. This makes the output predictable - you always know where you are and what’s coming next. Especially with large domains producing hundreds of lines of output, this structure helps you keep your bearings:
1. Banner & Legend
+-- Logo, Version, Symbol explanation
2. Connection Info
+-- Domain, DC, Auth method, Modules
3. Modules (depending on selection)
|-- +++++ Analyzing Domain Configuration +++++
|-- +++++ Analyzing Privileged Accounts +++++
|-- +++++ Analyzing Delegation Settings +++++
|-- +++++ Analyzing Access Permissions +++++
|-- +++++ Analyzing Computer Security +++++
|-- +++++ Analyzing Group Policy Objects +++++
|-- +++++ Analyzing Certificate Services +++++
|-- +++++ Analyzing Application Infrastructure +++++
|-- +++++ Analyzing Credential Exposure +++++
+-- +++++ Collecting BloodHound Data +++++
4. Scan Summary
+-- Duration, Report paths
Verbose Mode
Sometimes the standard output isn’t enough. When a check comes back unexpectedly empty or takes significantly longer than expected, you want to know what’s going on under the hood. With -Verbose, adPEAS shows every single step - which LDAP filters are being sent, how many results come back, and where time is being spent:
Invoke-adPEAS -Domain "contoso.com" -UseWindowsAuth -Verbose
VERBOSE: [Connect-adPEAS] Starting authentication...
VERBOSE: [Connect-adPEAS] Using Windows Authentication
VERBOSE: [Invoke-LDAPSearch] Filter: (objectClass=domain)
VERBOSE: [Invoke-LDAPSearch] Returned 1 results
VERBOSE: [Get-DomainInformation] Domain DN: DC=contoso,DC=com
Useful for:
- Debugging when something isn’t working
- Understanding which LDAP queries are being made
- Performance analysis
Verbose Logging to File
In practice, adPEAS often runs in the background while you’re working on other things. When a problem occurs, the console output has already scrolled past. -VerboseLogging solves this: all verbose messages are written to the text output file with timestamps. This way you can trace what happened and when, even after the fact:
# Verbose logging to file (automatically enables console verbose as well)
Invoke-adPEAS -Domain "contoso.com" -UseWindowsAuth -Outputfile .\report -VerboseLogging
The text file then contains additional timestamped entries:
2026-01-14 18:42:15 [Verbose] [Get-DomainUser] Querying users...
2026-01-14 18:42:16 [Verbose] [Invoke-LDAPSearch] Filter: (objectClass=user)
2026-01-14 18:42:16 [Verbose] [Invoke-LDAPSearch] Returned 1523 results
Note: -VerboseLogging automatically enables -Verbose for the console. The parameter requires -Outputfile with text format - without an output file, a warning is displayed and verbose messages are shown only in the console.
Under the Hood: The RenderModel Pipeline
For most users this section is optional - but if you want to understand why severity classification is always identical in the console and the HTML report, here’s the answer.
Internally, adPEAS uses a Unified RenderModel Pipeline. Check modules don’t worry about formatting - they simply call Show-Object and the pipeline handles the rest. The same AD object is automatically prepared for both the console and the HTML report:
Show-Object $user
|
v
Get-RenderModel # Builds a renderer-agnostic data model
|-- Detects object type (User, Computer, GPO, Cert Template)
|-- Maps attributes (Primary vs. Extended)
|-- Invokes AttributeTransformers (memberOf, UAC, SPN, etc.)
|-- Classifies severity (Finding/Hint/Note/Secure/Standard)
|
+---> Render-ConsoleObject # ANSI colors, prefixes, alignment
+---> Render-HtmlObject # HTML tables, tooltips, CSS classes
The AttributeTransformers are specialized functions for complex attributes:
| Transformer | Attribute | What it does |
|---|---|---|
Convert-MemberOfToRenderValues | memberOf | SID resolution, group classification |
Convert-UACToRenderValues | userAccountControl | Flag breakdown, per-flag severity |
Convert-SPNToRenderValues | servicePrincipalName | SPN formatting, Kerberoasting hint |
Convert-SIDHistoryToRenderValues | sIDHistory | Detection of privileged SIDs |
Convert-DangerousACEsToRenderValues | DangerousACEs | ACE classification |
Convert-EKUToRenderValues | ExtendedKeyUsage | OID-to-name mapping, PKINIT detection |
Attributes without a specialized transformer use Get-AttributeSeverity directly for simple value classification.
Part 2: File Reports
Console output is perfect for live analysis, but for documentation you need something persistent. On request, adPEAS generates two report formats: a text report for archiving and further processing, and an HTML report as an interactive dashboard for presentations and client deliverables. Both formats are created as standalone files with no external dependencies - copy one file and you’re done.
Generating Reports
# All formats (default)
Invoke-adPEAS -Domain "contoso.com" -Outputfile .\report
# HTML only
Invoke-adPEAS -Domain "contoso.com" -Outputfile .\report -Format HTML
# Text only
Invoke-adPEAS -Domain "contoso.com" -Outputfile .\report -Format Text
# Text without colors (for editors)
Invoke-adPEAS -Domain "contoso.com" -Outputfile .\report -Format Text -NoColor
At the end, adPEAS displays the paths:
======================================================================
+++++ Scan Summary +++++
======================================================================
[+] Duration: 24.3 seconds
[+] Text report saved to: report.txt
[+] HTML report saved to: report.html
[+] JSON export saved to: report.json
adPEAS automatically creates a JSON file (<basename>.json) alongside the report files on every scan with -Outputfile. This contains all findings as machine-readable, structured data — ideal for post-processing, external tools, or scripted analysis.
Incremental Scanning with OutputAppend
In practice, you don’t always want to run the full scan in one go. Maybe you want to check Domain and Accounts first, then add ADCS separately, or re-run specific modules after a configuration change. With -OutputAppend, results from multiple runs are merged into a single combined report:
# First run - creates report files + JSON
Invoke-adPEAS -Module Domain,Accounts -Outputfile .\audit
# Second run - findings are merged with previous ones
Invoke-adPEAS -Module ADCS,Rights -Outputfile .\audit -OutputAppend
# Third run - add more modules
Invoke-adPEAS -Module Creds,Delegation -Outputfile .\audit -OutputAppend
How does this work?
On every scan with -Outputfile, adPEAS automatically creates a JSON file (audit.json) alongside the report files. On each subsequent run with -OutputAppend, new findings are merged with the existing ones from the JSON file and the HTML report is regenerated with all combined results. The text report is appended at the end.
Run 1: Domain,Accounts -> audit.txt, audit.html, audit.json
Run 2: ADCS,Rights -> Merge with JSON -> Report updated
Run 3: Creds,Delegation -> Merge with JSON -> Report updated
Without -OutputAppend, existing reports are overwritten (default behavior).
Offline Report Conversion
The JSON file isn’t just useful for incremental scanning. It’s the interchange format that allows reports to be regenerated at any time — offline, without an active LDAP connection. This is particularly useful when:
- A newer adPEAS version is available and you want to re-render old scan data with updated finding definitions, scoring, or HTML templates
- You ran the scan on one system but want to create the report on another
Convert-adPEASReport takes a JSON file as input and produces fresh reports:
# All formats: HTML + Text + re-exported JSON
Convert-adPEASReport -InputJson ".\audit.json" -OutputPath ".\new_report"
# HTML only
Convert-adPEASReport -InputJson ".\audit.json" -OutputPath ".\new_report" -Format HTML
# Text only without colors (for editors)
Convert-adPEASReport -InputJson ".\audit.json" -OutputPath ".\new_report" -Format Text -NoColor
# Re-export JSON (with current adPEAS version metadata)
Convert-adPEASReport -InputJson ".\audit.json" -OutputPath ".\new_report" -Format JSON
# With license for branded reports
Convert-adPEASReport -InputJson ".\audit.json" -OutputPath ".\new_report" -License ".\license.json"
When the JSON file was created with an older adPEAS version, Convert-adPEASReport indicates this:
[*] Source: audit.json
[*] Domain: contoso.com, Server: DC01.contoso.com
[*] Original scan: 2026-01-15 14:30 (adPEAS 2.0.0+20260115-1430)
[*] Findings: 47
[+] Regenerating with adPEAS 2.0.1 (updated definitions/scoring)
Important: Conversion requires no LDAP connection. You only need the JSON file and an adPEAS installation.
Report Comparison (Diff)
If you scan regularly — whether quarterly for compliance or after a remediation phase — you want to know what changed. Compare-adPEASReport compares two JSON exports and shows the differences in a structured format:
# Compare two scans
Compare-adPEASReport -Baseline ".\scan_q1.json" -Current ".\scan_q2.json"
# Save diff report to file
Compare-adPEASReport -Baseline ".\scan_jan.json" -Current ".\scan_apr.json" -OutputPath ".\diff_report"
The comparison shows:
[?] adPEAS Report Comparison
[*] Baseline: scan_q1.json (2026-01-15 14:30, contoso.com, adPEAS 2.0.0)
[*] Current: scan_q2.json (2026-04-15 09:00, contoso.com, adPEAS 2.0.1)
[?] Comparison Summary
[!] New findings (added): 3
[#] Remediated findings (removed): 5
[+] Changed findings: 2
[*] Unchanged findings: 39
[*] Total baseline findings: 46
[*] Total current findings: 44
- New findings — New vulnerabilities since the last scan
- Remediated findings — Fixed issues (were in baseline, now gone)
- Changed findings — Changed severity or values (e.g., password policy adjusted)
When scan scopes differ (e.g., baseline included ADCS, current didn’t), the comparison flags missing categories so you don’t draw false conclusions.
Typical workflow:
Quarter 1: Scan -> audit_q1.json
| Remediation
Quarter 2: Scan -> audit_q2.json
|
Compare-adPEASReport -Baseline audit_q1.json -Current audit_q2.json
|
Diff report -> "5 fixed, 3 new, 2 changed"
The Text Report
The text report is the simplest form of documentation - essentially the console output captured to a file. It contains the same output as the console, including ANSI color codes:
- Readable with
catorGet-Contentin the terminal - With
-NoColor, also readable in editors without escape codes - Same structure as console output
The HTML Report
The HTML report is the highlight of the output system. While the text report delivers the raw data, the HTML report transforms the scan results into an interactive dashboard with search, filters, and collapsible finding cards. Ideal when presenting results to a client or pulling sections into a report:
Header
- adPEAS Logo and Version
- License Notice (for commercial use)
- Dark/Light Mode Toggle - Sun/moon switch
Sidebar (left)
Search Field:
- Free-text search across all findings
Severity Filter:
- All (count)
- Finding (count) - Red
- Hint (count) - Yellow/Orange
- Note (count) - Green
- Secure (count) - Blue
Category Filter:
- All
- Accounts
- ADCS
- Application
- Computer
- Creds
- Delegation
- Domain
- GPO
- Rights
Main Area
Summary Cards:
+----------+ +----------+ +----------+ +----------+
| 12 | | 16 | | 19 | | 16 |
| Findings | | Hints | | Notes | | Secure |
+----------+ +----------+ +----------+ +----------+
Clicking a card filters by that severity.
Finding Cards:
Each finding is a collapsible card:
+-------------------------------------------------------------+
| [FINDING] Password policy too weak [v] |
+-------------------------------------------------------------+
| Category: Domain |
| |
| minPwdLength: 7 characters |
| lockoutThreshold: Disabled |
| |
| Help via tooltip with explanation |
+-------------------------------------------------------------+
HTML Report Features
All features are contained in a single HTML file - no JavaScript from external CDNs, no CSS frameworks, no dependencies:
| Feature | Description |
|---|---|
| Dark/Light Mode | Toggle in the top right, persisted in the browser |
| Search | Free-text across all findings |
| Severity Filter | Show Finding/Hint/Note/Secure individually |
| Category Filter | Filter by module |
| Collapsible Cards | Expand/collapse details |
| Help Tooltips | Explanations for findings |
Colors in the HTML Report
| Severity | Color | CSS Variable |
|---|---|---|
| Finding | Red | --finding: #d32f2f |
| Hint | Orange | --hint: #f57c00 |
| Note | Green | --note: #388e3c |
| Secure | Blue | --secure: #2196f3 |
Summary
Depending on the situation, you’ll reach for different formats. Here’s an overview of what each format offers and where its strengths lie:
| Aspect | Console | Text Report | HTML Report |
|---|---|---|---|
| Real-time | Yes | No | No |
| Color-coded | Yes | Yes (ANSI) | Yes (CSS) |
| Searchable | grep/Select-String | grep/Select-String | Built-in |
| Filterable | No | No | Yes |
| Presentable | No | Somewhat | Yes |
| Dark Mode | Terminal | No | Yes |
When to use what?
- Console - Interactive work, quick checks
- Text Report - Archiving, scripting, diffing
- HTML Report - Presentations, documentation, client deliverables
← Episode 4: Security Checks | Episode 6: Offensive Operations — coming soon
About the Author
Related Articles
adPEAS v2 Blog Series: Active Directory Security Analysis with adPEAS
Introducing adPEAS v2 — a complete rewrite of the PowerShell-based Active Directory analysis tool with native Kerberos support, zero dependencies, and over 40 security checks.
adPEAS v2 Episode 2: Under the Hood - Anatomy of a Scan
What happens when adPEAS scans an Active Directory? From authentication and LDAP queries to context-dependent severity ratings and caching -- a look under the hood.
adPEAS v2 Episode 3: Authentication Deep-Dive - From Password to Certificate
Deep dive into adPEAS v2 authentication: Kerberos internals, Pass-the-Hash, Pass-the-Key, PKINIT with certificates, Shadow Credentials, and Pass-the-Cert via Schannel.