Skip to content

JSON Output

ppee-cli --json writes one JSON document to stdout. The MCP tools return the same document, so this reference applies to both.

Conventions

Convention Example Notes
Values read from the file are uppercase hex strings without 0x "FileHeader.Machine": "8664" Convert with tonumber in a language, or ("0x"+.) style helpers in jq, see recipes
Counts, indexes, sizes and ordinals are JSON numbers "numberOfFunctions": 12
Measurements are JSON numbers "entropy": 6.231031
Optional directories carry "present": true/false "exports": {"present": false, ...} The object is still emitted, so check present first
List-type directories are arrays, empty when absent "boundImports": []
Text is UTF-8 Non-printable bytes are escaped

Top level

{
  "path": "/abs/path/sample.dll",   // absolute path of the analyzed file
  "size": 650752,                   // file size in bytes
  "is64Bit": true,                  // PE32+ (true) or PE32 (false)
  "headers": { ... },               // --headers
  "dataDirectories": { ... },       // --dirs
  "sections": { ... },              // --sections
  "fileInfo": { ... },              // --hashes / --similarity
  "similarity": { ... },            // --similarity
  "imports": [ ... ],               // --imports
  "exports": { ... },               // --exports
  "baseRelocations": [ ... ],       // --basereloc
  "tls": { ... },                   // --tls
  "debug": [ ... ],                 // --debug
  "boundImports": [ ... ],          // --bound-imports
  "delayImports": [ ... ],          // --delay-imports
  "resources": { ... },             // --resources
  "exception": { ... },             // --exception
  "security": { ... },              // --security
  "loadConfig": { ... },            // --loadconfig
  "net": { ... },                   // --net
  "richHeader": { ... },            // --richheader
  "appManifest": { ... },           // --appmanifest
  "analysis": { ... },              // --analysis / --analysis-deep
  "strings": { ... },               // --strings
  "disasm": { ... },                // --disasm
  "xrefs": { ... },                 // --xrefs
  "functions": { ... }              // --functions
}

Only the sections you select are present. Keys always appear in this order.

Sections

headers, dataDirectories, sections

Flat objects that map a field name to a hex string. The names are the ones --set accepts.

"headers": {
  "DosHeader.e_magic": "5A4D",
  "FileHeader.Machine": "8664",
  "FileHeader.TimeDateStamp": "F8929A64",
  "OptionalHeader.DllCharacteristics": "4160"
},
"dataDirectories": { "DataDirectory[1].VirtualAddress": "425638", "DataDirectory[1].Size": "AB4" },
"sections": { "Section[0].Name": ".text", "Section[0].Characteristics": "60000020" }

A section whose name is a COFF long name (/29) also has Section[i].LongName, the name it stands for (.debug_info).

fileInfo

"fileInfo": {
  "crc32": "B1A68BA9", "entropy": 6.231031,
  "md5": "706FCA0D…", "sha1": "E56F1366…", "sha256": "5027E704…",
  "ssdeep": "12288:LplT1X0l8…", "tlsh": "T11DD45B2E…",
  "impHash": "6501FFF7…", "authentihash": "4D6CFACB…"
}

See Hashes & Entropy.

similarity

"similarity": {
  "available": true,                 // false if the database could not be opened (read-only location)
  "dbRecordCount": 2,
  "matches": [ { "peerPath": "/samples/explorer.exe", "kind": "SHA256 identical" } ]
}

imports, delayImports, boundImports

"imports": [
  { "name": "msvcrt.dll", "originalFirstThunk": "94A90", "timeDateStamp": "0",
    "forwarderChain": "0", "firstThunk": "72540",
    "functions": [ { "hint": 1280, "name": "wcscat_s" }, { "ordinal": 12 } ] }
],
"delayImports": [
  { "name": "Bcp47Langs.dll", "attributes": "1", "timeDateStamp": "0",
    "functions": [ { "hint": 42, "name": "GetSerializedUserLanguageProfile" } ] }
]

A function imported by ordinal has ordinal instead of hint/name.

exports

"exports": {
  "present": true, "name": "AEPIC.dll", "characteristics": "0", "timeDateStamp": "F8929A64",
  "majorVersion": 0, "minorVersion": 0, "base": 1,
  "numberOfFunctions": 12, "numberOfNames": 12,
  "functions": [ { "ordinal": 1, "name": "GetAppInventoryCore", "rva": "29CB0" },
                 { "ordinal": 12, "name": "ADsSetLastError", "forwarder": "ADSLDPC.ADsSetLastError" } ]
}

A forwarded export has forwarder instead of rva.

baseRelocations

"baseRelocations": [ { "pageRVA": "70000", "sizeOfBlock": 868,
                       "entries": [ { "offset": "0", "type": 10 } ] } ]

type 10 is IMAGE_REL_BASED_DIR64, 3 is HIGHLOW, 0 is padding (ABSOLUTE).

tls

"tls": { "present": true, "startAddressOfRawData": "1403F4A48", "endAddressOfRawData": "1403F4A50",
         "addressOfIndex": "140433518", "addressOfCallBacks": "1403A0478",
         "sizeOfZeroFill": "0", "characteristics": "300000", "callbacks": [] }

debug

"debug": [ { "type": 2, "timeDateStamp": "F8929A64", "sizeOfData": 34, "pointerToRawData": "82908",
             "codeView": { "format": "RSDS", "pdbPath": "aepic.pdb", "age": 1,
                           "guid": "D269A603-CE82-ED0C-3EBD-B5FB71DA278C" } } ]

type: 2 = CodeView, 12 = VC feature, 13 = POGO, 16 = repro, 20 = extended DLL characteristics.

resources

"resources": {
  "present": true, "numberOfNamedEntries": 0, "numberOfIdEntries": 1,
  "types": [ { "id": 16, "typeName": "RT_VERSION",
    "names": [ { "id": 1,
      "languages": [ { "id": 1033, "offsetToData": "507580", "size": 120, "codePage": 0,
                       "entropy": 5.66, "md5": "927E8608…",
                       "firstBytesHex": "89 50 4E 47 …", "firstBytesAscii": ".PNG…",
                       "typeDetected": "PNG" } ] } ] } ]
}

Named entries have name instead of id. offsetToData is an RVA (as in the PE format).

exception

"exception": { "present": true, "machine": "AMD64",
  "entries": [ { "beginAddress": "1008", "endAddress": "10B0", "unwindInfoAddress": "89FFC",
                 "unwindInfo": { "version": 1, "flags": 3, "sizeOfProlog": 38, "countOfCodes": 9 } } ] }

security

"security": {
  "present": true,
  "certificates": [ { "fileOffset": "8600", "length": 9336, "revision": "200",
                      "certificateType": "2", "sha256": "95E27476…" } ],
  "validity": { "available": false, "result": "Not available on this platform",
                "comment": "Signature validity is checked by the Windows version of ppee" },
  "signatures": [ {
      "certificateIndex": 0, "nested": false, "parsed": true,
      "programName": "Microsoft Windows", "publisherLink": "http://www.microsoft.com/windows",
      "digestAlgorithm": "SHA256", "signatureAlgorithm": "RSA",
      "embeddedDigestAlgorithm": "SHA256", "embeddedDigest": "7C1A1478…", "authentihash": "7C1A1478…",
      "signerCertificate": { "serialNumber": "…", "issuerName": "…", "issuer": "C=US, …",
                             "subjectName": "Microsoft Windows", "subject": "C=US, …",
                             "validFrom": "2019/03/27 19:21:43", "validTo": "2020/03/27 19:21:43",
                             "signatureAlgorithm": "SHA256 RSA", "publicKey": "RSA 2048-bit",
                             "enhancedKeyUsage": "…, Code Signing" },
      "timestamp": { "kind": "RFC3161 token", "date": "2019/12/07 04:35:20", "certificate": { … } } } ]
}
  • embeddedDigest == authentihash means the file hasn't been modified since it was signed.
  • validity.available is true only on Windows builds, where result carries the WinVerifyTrust verdict.

loadConfig

"loadConfig": { "present": true, "isPe64": true,
  "header": { "size": "118", "securityCookie": "140431C68", "guardFlags": "417500",
              "guardCFFunctionTable": "1403A097C", "guardCFFunctionCount": "F71", … },
  "safeSeh":              { "present": false, "entries": [] },
  "guardCFFunction":      { "present": true,  "entries": [ { "rva": "4F10" } ] },
  "guardAddressTakenIat": { "present": true,  "entries": [ … ] },
  "guardLongJumpTarget":  { "present": false, "entries": [] },
  "guardEHContinuation":  { "present": true,  "entries": [ … ] } }

net

"net": { "present": true,
  "header": { "cb": "48", "majorRuntimeVersion": 2, "minorRuntimeVersion": 5, "flags": "18",
              "entryPointToken": "26314", "metaDataRva": "8DA0", "metaDataSize": "13504", … },
  "metadataRoot": { "present": true, "signature": "424A5342", "versionString": "v2.0.50727",
                    "numberOfStreams": 5,
                    "streams": [ { "name": "#~", "offset": "6C", "size": "66F4" } ] },
  "vTableFixups": [ … ] }

richHeader, appManifest

Row lists that mirror the GUI's Member / Value / Comment columns:

"richHeader":  { "present": true, "rows": [ { "member": "Product ID", "value": "0104", "comment": "C object, VS2015" } ] },
"appManifest": { "present": true, "rows": [ { "member": "Level", "value": "asInvoker", "comment": "No additional permissions" } ] }

analysis

Derived views for the runtimes PPEE detected, kept under one key so a consumer can never mistake them for data read from the file. runtimes is empty when nothing was detected.

"analysis": { "runtimes": [ {
  "key": "go", "name": "Go",                                  // key: net | go | rust | aot
  "evidence": "Go build info at offset 0x5B0220; Go 1.20+ pclntab at offset 0x8C61E0",
  "views": [
    { "key": "analysis.go.summary", "title": "Summary",
      "source": "the Go build info, build ID and pclntab, and the file layout",
      "tone": "warning",                                      // normal | warning | error | muted
      "blocks": [                                             // rich views (Summary)
        { "kind": "heading",   "spans": [ { "text": "Identity" } ] },
        { "kind": "fact",      "label": "Go version",
          "spans": [ { "text": "go1.24.2", "link": 0 } ] },   // link: index into this view's "links"
        { "kind": "note",      "tone": "warning", "spans": [ { "text": "Overlay (appended data): 1177.6 KB" } ] } ],
      "links": [ { "offset": "5B0220", "length": "20", "where": "offset 0x5B0220" } ] },
    { "key": "analysis.go.packages", "title": "Packages", "source": "the pclntab (the runtime's function table)",
      "tone": "normal",
      "table": { "columns": [ "Package", "Functions", "Source files" ],   // table views
                 "rows": [ { "cells": [ "main", "4", "1" ],
                             "tone": "warning",                          // only when not normal
                             "link": 0,                                  // optional link index
                             "detail": { "columns": [ … ], "rows": [ … ] } } ] },   // optional nested table
      "links": [ … ] } ] } ] }
Object Fields
runtime key, name, evidence, views[]
view key, title, source, tone, and either blocks[] (rich) or table (rows), plus links[]
block kind (heading, fact, note, paragraph), label (facts), tone (notes), spans[] (text, optional link)
table row cells[], optional link, tone, detail (a nested table)
link {va, where} (code, opens the Code window) or one of {node, where}, {node, row, where} (a tree node or table row), {offset, length, where} (a file range, hex strings) or {action: "deep", where} (a hint that the deep pass would add more)

View keys: analysis.net.{summary,imports,nativeimports,exports,resources}, analysis.go.{summary,packages,modules,build}, analysis.rust.{summary,sources}, analysis.aot.summary, analysis.code.{summary,calls,patterns,functions}.

The Code runtime (key: "code") adds two things: a block of kind: "code" holding instruction evidence as lines[] (va, text), and code links {va, where} that point at an address in code rather than a file range. Go and NativeAOT function rows also link with va. Tables that would be empty are omitted. See Runtime Analysis.

strings

"strings": {
  "ascii":      [ { "offset": "4D", "sectionName": "Inside header area", "text": "!This program cannot be run in DOS mode." } ],
  "unicode":    [ … ],
  "url":        [ { "offset": "76600", "sectionName": ".rdata [R] (#2 section)", "type": "ASCII", "text": "…" } ],
  "registry":   [ … ],
  "suspicious": [ … ]
}

offset is a file offset. Tagged hits (url, registry, suspicious) add type (ASCII / UNICODE). The MCP get_strings tool adds omittedByLimit with per-group counts.

disasm, xrefs, functions

Present only with --disasm, --xrefs and --functions; see that page for the shapes and examples.

Validating output in scripts

ppee-cli --json --hashes "$f" | jq -e '.fileInfo.sha256 | length == 64' > /dev/null \
  || echo "unexpected output for $f"

Related: jq recipes · CI policy gates · MCP tools

References

  • jq manual: the filter language used in the JSON examples on this page.