SEKurity GmbH Logo
adPEAS

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.

Alexander Sturz

Founder & Red Team Lead

13 min read
Share:

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:

  1. Console Output - Color-coded real-time output for interactive work
  2. 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:

SymbolColorMeaningExample
[?]BlueSection Header[?] Analyzing Domain Configuration
[!]RedFinding - Security issue[!] minPwdLength: 3 characters
[+]YellowHint - Worth investigating[+] lockoutThreshold: Disabled
[*]GreenNote - Information[*] Found 2 domain controller(s)
[#]Red on YellowSecure - 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:

TransformerAttributeWhat it does
Convert-MemberOfToRenderValuesmemberOfSID resolution, group classification
Convert-UACToRenderValuesuserAccountControlFlag breakdown, per-flag severity
Convert-SPNToRenderValuesservicePrincipalNameSPN formatting, Kerberoasting hint
Convert-SIDHistoryToRenderValuessIDHistoryDetection of privileged SIDs
Convert-DangerousACEsToRenderValuesDangerousACEsACE classification
Convert-EKUToRenderValuesExtendedKeyUsageOID-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 cat or Get-Content in 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:

  • adPEAS Logo and Version
  • License Notice (for commercial use)
  • Dark/Light Mode Toggle - Sun/moon switch

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:

FeatureDescription
Dark/Light ModeToggle in the top right, persisted in the browser
SearchFree-text across all findings
Severity FilterShow Finding/Hint/Note/Secure individually
Category FilterFilter by module
Collapsible CardsExpand/collapse details
Help TooltipsExplanations for findings

Colors in the HTML Report

SeverityColorCSS Variable
FindingRed--finding: #d32f2f
HintOrange--hint: #f57c00
NoteGreen--note: #388e3c
SecureBlue--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:

AspectConsoleText ReportHTML Report
Real-timeYesNoNo
Color-codedYesYes (ANSI)Yes (CSS)
Searchablegrep/Select-Stringgrep/Select-StringBuilt-in
FilterableNoNoYes
PresentableNoSomewhatYes
Dark ModeTerminalNoYes

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

Alexander Sturz

Founder & Red Team Lead

Active Directory Ninja and offensive security expert specializing in enterprise infrastructure compromise and post-exploitation techniques.

Related Articles