Static binary analysis framework for ELF, PE, and Mach-O executables. Written in Zig 0.13.0 with no external dependencies.
Requires Zig 0.13.0 (https://ziglang.org/download/).
zig build
zig build -Doptimize=ReleaseFast
zig build -Doptimize=ReleaseSmallThe compiled binary is at zig-out/bin/integritygap.
zig build test # embedded test blocks in each source file
cd tests && bash run_tests.sh # ~700 shell-based tests
├── build.zig
├── LICENSE
├── README.md
├── src/
│ ├── main.zig # CLI entry point, argument parsing, orchestration (621 lines)
│ ├── types.zig # Central type definitions, structs, enums, constants (565 lines)
│ ├── core/ # Core analysis pipeline
│ │ ├── parser.zig # ELF/PE/Mach-O binary parser (1148 lines)
│ │ ├── decoder.zig # x86/x86_64/ARM64 instruction decoder (989 lines)
│ │ ├── analyzer.zig # 10-dimension integrity gap scoring engine (888 lines)
│ │ ├── signatures.zig # Known API import signatures and call categorization (192 lines)
│ │ └── utils.zig # Integer reading, string utilities, hashing, entropy (228 lines)
│ ├── analysis/ # Specialized analysis engines
│ │ ├── concurrency_analyzer.zig # Data races, lock analysis, deadlock detection (560 lines)
│ │ ├── taint_analyzer.zig # Taint propagation from sources to sinks (505 lines)
│ │ ├── firmware_integrity.zig # Firmware image format analysis (541 lines)
│ │ ├── crypto_auditor.zig # Cryptographic algorithm and key analysis (562 lines)
│ │ ├── privacy_analyzer.zig # PII detection, consent, data flow (439 lines)
│ │ ├── compliance_engine.zig # PCI DSS, HIPAA, SOC2, ISO 27001 checks (530 lines)
│ │ ├── memory_safety.zig # Buffer overflow, use-after-free, format string (447 lines)
│ │ ├── dependency_checker.zig # CVE matching, license detection (352 lines)
│ │ ├── config_auditor.zig # Hardcoded credentials, insecure defaults (376 lines)
│ │ └── string_analyzer.zig # ASCII/Unicode string extraction and classification (514 lines)
│ ├── output/
│ │ ├── reporter.zig # JSON, plain text, DOT, CSV, diff output (529 lines)
│ │ └── report_engine.zig # HTML, Markdown, SARIF, JUnit XML reports (1209 lines)
│ ├── postproc/
│ │ ├── false_positive_reducer.zig # Context-based FP reduction (262 lines)
│ │ ├── cvss_scorer.zig # CVSS v3.1/v3.0/v2.0 scoring (282 lines)
│ │ ├── threat_model.zig # STRIDE classification, attack trees (203 lines)
│ │ └── remediation_engine.zig # Remediation suggestion generation (234 lines)
│ └── infra/
│ ├── logging.zig # Thread-safe file-rotating logger (171 lines)
│ ├── batch_analyzer.zig # Multi-target batch processing (185 lines)
│ ├── result_cache.zig # TTL-based analysis result cache (213 lines)
│ ├── config_file.zig # Configuration file parser (198 lines)
│ └── plugin_system.zig # Dynamic plugin loading with 8 hook points (192 lines)
├── tests/
│ └── run_tests.sh
├── examples/
│ └── sample_config.conf
integritygap --target <binary> [mode] [output flags] [options]
integritygap --target <binary> --diff <other>
integritygap --target <binary> --baseline <known_clean>
integritygap --help
integritygap --version
| Flag | Default pipeline additions |
|---|---|
--all |
All enabled engines (default) |
--integrity-gap |
10-dimension core scoring only |
--concurrency |
Concurrency analysis engine |
--taint |
Taint propagation analysis |
--firmware |
Firmware image analysis |
--crypto |
Cryptographic audit |
--privacy |
Privacy compliance analysis |
--compliance |
Regulatory compliance checks |
--memory |
Memory safety analysis |
--dependencies |
Dependency/CVE scanning |
--config |
Configuration audit |
--strings |
String extraction and classification |
| Flag | Format |
|---|---|
--json <path> |
JSON |
--plain |
Plain text to stdout |
--dot <path> |
Graphviz DOT |
--html <path> |
HTML |
--markdown <path> |
Markdown |
--sarif <path> |
SARIF v2.1.0 |
--csv <path> |
CSV |
| Flag | Effect |
|---|---|
--diff <path> |
Compare against another binary |
--baseline <path> |
Compare against known-clean baseline |
--batch <path> |
Process multiple targets from a batch file |
--firmware |
Enable firmware-specific analysis mode |
--max-bytes <N> |
Maximum bytes to read per target (default: 268435456) |
--verbose, -v |
Print progress to stderr |
--report-only |
Generate report from cached data, skip analysis |
--cache-enabled |
Enable result caching (default: enabled) |
--cache-directory <path> |
Cache storage directory |
--min-severity <level> |
Minimum severity threshold |
--max-findings <N> |
Maximum findings to report |
--fp-reduction |
Enable false positive reduction |
--enable-remediation |
Enable remediation suggestions |
--enable-cvss |
Enable CVSS scoring |
--config-file <path> |
Load configuration from file |
The pipeline executes in this order:
- main.zig — reads file, parses CLI flags, selects modes
- core/parser.zig — detects format by magic bytes, parses headers/sections/symbols/imports
- core/decoder.zig — decodes executable sections into instructions, detects function boundaries, builds call graph
- core/analyzer.zig — profiles each function across 10 dimensions (error_handling, resource_lifecycle, input_validation, cryptographic, logging_auditability, cleanup, concurrency, memory_safety, configuration, supply_chain), collects evidence, classifies threat
- analysis/*.zig — optional specialized engines (selected by mode flag)
- postproc/*.zig — optional post-processing (FP reduction, CVSS, STRIDE, remediation, caching)
- output/reporter.zig or output/report_engine.zig — serializes results to requested format
The system produces scoring dimensions at two levels: per-function category scores (10 dimensions from CategoryScores aggregated into a single function gap) and engine-level scores (from each specialized analyzer).
Every function receives a score from 0 to 100 per category. All 10 categories contribute to the function's aggregate gap via fixed weights:
| Category | Weight | What it measures |
|---|---|---|
| error_handling | 15% | Fraction of critical calls without return-value validation |
| resource_lifecycle | 12% | Fraction of resource acquires without matching release |
| cryptographic | 13% | Missing init/finalize/destroy, hardcoded IV, unchecked crypto calls |
| input_validation | 10% | Pointer dereference before validation, memcpy without bounds check |
| cleanup | 10% | Exit paths with unreleased resources |
| concurrency | 10% | Unsynchronized shared access, lock violations, deadlock patterns |
| memory_safety | 10% | Unbounded copies, format strings, use-after-free, buffer overflows |
| logging_auditability | 8% | High-risk operations without corresponding logging |
| configuration | 6% | Hardcoded credentials, insecure defaults, disabled security |
| supply_chain | 6% | Known CVEs in linked dependencies, unsigned libraries, license risk |
The aggregate gap per function is: clamp100(Σ(category_score × weight)).
If 4+ functions exist, scores are normalized against the local population:
- Functions near the average are penalized (35% retention)
- Functions significantly above average retain 28% of raw score plus up to 22 per z-score unit
Each specialized analysis engine outputs its own score (0–100 or 0–100%). These engine-level scores also feed back into the corresponding per-function category scores at a reduced weight (8–10%) to ensure that engine-level findings influence the core aggregate gap, anomaly confidence, and threat classification:
| Engine | Score field | Range | Meaning |
|---|---|---|---|
| concurrency_analyzer | concurrency_gap_score | 0–100 | Severity of data races, lock violations, unguarded shared data |
| concurrency_analyzer | deadlock_potential | 0–100% | Likelihood of circular wait conditions from lock ordering |
| taint_analyzer | taint_gap_score | 0–100 | Severity of unvalidated taint propagation paths |
| crypto_auditor | crypto_gap_score | 0–100 | Weak ciphers, hardcoded keys, static IVs, missing auth |
| firmware_integrity | integrity_score | 0–100 | Hash mismatches, missing signatures, rollback risk |
| memory_safety | safety_gap_score | 0–100 | Buffer overflows, use-after-free, format string, integer errors |
| privacy_analyzer | privacy_gap_score | 0–100 | PII collection without consent, third-party sharing |
| privacy_analyzer | gdpr_compliance_score | 0–100% | GDPR technical control coverage |
| privacy_analyzer | ccpa_compliance_score | 0–100% | CCPA technical control coverage |
| privacy_analyzer | hipaa_compliance_score | 0–100% | HIPAA technical safeguard coverage |
| compliance_engine | overall_score | 0–100% | Average pass rate across all checked frameworks |
| compliance_engine | pci_dss/hipaa/soc2/iso_27001 score | 0–100% | Per-framework requirement pass rate (ComplianceReport.score) |
| dependency_checker | supply_chain_score | 0–100% | CVE-free dependency ratio, signature validity |
| dependency_checker | cve_score | 0–100 | Severity-weighted score of matched known CVEs in detected dependencies |
| config_auditor | config_security_score | 0–100% | Security control implementation rate across 12 controls |
| threat_model | risk_score | 0–100 | STRIDE/PASTA-derived risk score per identified threat scenario |
The summary threat is decided by a rule-based decision tree in classifyThreat():
- If
aggregate < 15*scaleANDmax_conf < 35*scaleANDmaterial_ratio < 0.03→No_Material_Gap - If binary has >1000 functions AND
aggregate < 5.0ANDmaterial_ratio < 0.01→No_Material_Gap - If cryptographic > 40scale AND resource > 30scale AND error > 25*scale →
Ransomware - If logging > 40scale AND error > 40scale →
RAT - If resource > 50scale AND error < 35scale →
Dropper - If max_conf > 70scale AND aggregate < 35scale AND material < 0.06 →
Implant - If aggregate < 10 AND max_conf < 50 →
No_Material_Gap - Default →
Legitimate_Anomalous
scale is adaptiveThreatScale(function_count) * systemic_boost. The adaptive scale decreases for large binaries:
-
5000 functions: 0.78x
-
1000 functions: 0.88x
- <8 functions: 1.45x
anomaly_confidence = clamp100(aggregate_gap * 1.25) — derived from the mean aggregate across all functions, capped at 100.
| Format | Variants |
|---|---|
| ELF | ELF32, ELF64 (little-endian and big-endian) |
| PE | PE32 (0x10b), PE32+ (0x20b) |
| Mach-O | 32-bit, 64-bit, fat/universal |
IntegrityGap: ./target.bin
Format: elf64/x86_64 Entry: 0x401000
Classification: No_Material_Gap Gap: 0.91 Confidence: 1.13
Scores: error=0.0 resource=0.0 input=9.0 crypto=0.0 logging=0.0 cleanup=0.0
Functions identified/analyzed: 16083/16083 Instructions: 449828 Evidences: 2727
Functions with material gap:
0x11b6ba0-0x11b6c60 gap=20.50 conf=22.32 critical=2/2 resources=0/0 cleanup_dirty=0/0
-> error_handling: Syscall/sysenter without visible return validation (sev=80)
-> input_validation: Argument pointer deref before observable local validation (sev=55)
=== Concurrency Analysis ===
Detected Races: 0 | Threading Issues: 0 | Concurrency Risk Score: 55.00
Full structured output with tool metadata, binary metadata, per-function profiles, evidence items with CWE IDs, call graph edges, summary scores, threat classification, and engine-specific sections.
Self-contained report with inline CSS, collapsible sections, severity color coding.
GitHub-flavored markdown report.
Tabular output with function, finding type, severity, and score columns.
OASIS SARIF v2.1.0 format.
CI/CD integration format.
Graphviz directed graph with function nodes and call edges.
- Data races: unsynchronized shared memory access across threads
- Lock ordering violations: inconsistent lock acquisition order
- Double lock / lock leak: redundant or missing lock release
- Deadlock patterns: circular wait conditions
- Thread-unsafe APIs: calls from multi-threaded context
- Unguarded shared data access: writes without synchronization
Tracks data flow from 12 source types (network, file, user input, env var, registry, etc.) to 13 sink types (exec, file write, network send, SQL query, etc.). Reports unvalidated propagation paths.
Detects firmware format (UEFI FV, Intel ME, U-Boot, Android bootimg, cpio, initramfs). Checks: hash mismatches, missing signatures, certificate validation, rollback detection, backdoor strings.
When invoked with --firmware alone (without --html/--md/--sarif), firmware analysis runs standalone and produces its own output. When combined with --html/--md/--sarif in --all mode, firmware results are included in the comprehensive report alongside all other engines.
Identifies cipher algorithms (AES, DES, 3DES, RC4, ChaCha20, etc.). Detects: weak ciphers, hardcoded keys, static IVs, ECB mode, weak randomness, deprecated hashes, missing authentication, certificate validation bypass.
Detects PII-related function patterns (email, SSN, credit card, health data, biometric, location, etc.). Checks: data collection/sharing functions, consent mechanisms, third-party SDK sharing (Google Analytics, Firebase, Facebook, etc.). Maps to GDPR, CCPA, HIPAA, LGPD, PIPEDA.
Evaluates against framework requirements: PCI DSS (6 checks), HIPAA (6 checks), SOC2 (5 checks), ISO 27001 (4 checks). Checks: encryption usage, logging, access control, network security, configuration management.
Detects: unbounded string copies (strcpy, sprintf, gets), format string vulnerabilities, use-after-free (access within 10 instructions of free), double free, null pointer dereference, integer overflow in allocation size, stack buffer overflow (frame >512 bytes without canary).
Matches dependency names against 30+ embedded CVE records (OpenSSL: CVE-2014-0160 Heartbleed, CVE-2022-3602; log4j: CVE-2021-44228; curl, zlib, libpng, libssh2, sqlite3, etc.). Detects dependency types by filename pattern. Identifies SPDX licenses.
Note: The CVE database is statically compiled into the binary at build time. It reflects known vulnerabilities up to the release date of this version (v2.1.0). There is no live update mechanism — the database is a snapshot, not a live feed. To update, rebuild the binary against the latest source.
Searches binary sections for hardcoded credential patterns (password, secret, api_key, token, connection_string). Detects insecure defaults (admin, root, default, debug), disabled security, verbose errors, permissive permissions. Produces security control inventory (12 controls).
Extracts and classifies human-readable strings from binary sections, supporting both ASCII (single-byte) and UTF-16LE (wide char) encodings. Classification is regex-free — uses deterministic pattern matching to categorize strings into 10 interesting types:
| Type | Examples | Detection Logic |
|---|---|---|
| URL | https://api.example.com/auth |
Starts with http://, https://, ftp://, ws://, wss:// |
| IPv4 | 192.168.1.1 |
Four octets (0–255) separated by dots |
| IPv6 | 2001:db8::1, ::1 |
Hex groups with colons, shorthand ::, zone IDs |
user@domain.com |
\w+@\w+.\w+ with valid TLD (com, org, net, etc.) |
|
| Unix Path | /usr/local/bin, /dev/null |
Starts with /, contains valid path characters |
| Windows Path | C:\Users\admin, \\server\share |
Drive letter + :\ or UNC \\ prefix |
| Registry Key | HKLM\Software\Microsoft |
Starts with HKLM/HKCU/HKCR/HKCC/HKPD |
| Shell Command | wget, chmod +x, powershell -enc |
Matches known shell commands/operators from a 180+ entry dictionary |
| Crypto Key | -----BEGIN RSA PRIVATE KEY----- |
PEM armor boundaries, Base64-encoded key material ≥64 chars |
| JWT Token | eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0 |
Three dot-separated Base64url segments matching JWT structure |
| Hex String | 1A2B3C4D5E6F7890 |
Even-length hex characters, validated with Shannon entropy filter |
| Base64 | SGVsbG8gV29ybGQ= |
≥28 chars, valid Base64 alphabet, proper padding |
Output: When --strings mode is active, the tool prints a summary with total strings extracted, count per classification type, interesting ratio, and a detailed listing of each classified string with its offset, classification, severity (derived from type: crypto keys=90, shell commands=80, registry_keys=75, JWTs=70, URLs=65, emails=60, IPs/Base64=40, paths=20, hex=10) and a human-readable description.
Integration: Results are also embedded in JSON, HTML, Markdown, SARIF, and CSV reports when combined with other modes (--all).
Evaluates 10 context factors per evidence item: surrounding validation, compiler-optimized patterns, known library signatures, framework boilerplate, sanitizer checks, assertion guards, exception handling, indirect return use, RAII wrappers, FP signature matches. Adjusts confidence scores.
Computes CVSS v3.1 base, temporal, and environmental scores per finding. Supports v3.0 and v2.0. Produces vector strings and severity labels (none/low/medium/high/critical).
Classifies findings into STRIDE categories (Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege). Builds AND/OR attack trees. Performs PASTA risk analysis.
Generates per-finding suggestions with priority (immediate/short-term/medium-term/long-term/informational), category (code change, config change, dependency update, etc.), and effort hour estimates.
Thread-safe logger with 6 severity levels (debug/critical). File rotation at 10 MB, up to 5 backups. Mutex-based thread safety.
Processes multiple targets from a batch file. Modes: full, quick, integrity-only, compliance-only. Progress callbacks and per-target timing.
TTL-based cache keyed by file content hash. Get, set, invalidate, clear operations. Configurable storage directory and entry lifetime.
Parses .conf files: comments (# or ;), key=value (prefixed with --), default target as bare value. Supports all CLI flags as keys.
Loads shared libraries (.so, .dylib, .dll) via std.DynLib. 8 hook points: pre/post analysis, pre/post function-profile, pre/post report, pre/post filter. Plugin manifest with name, version, author.
Preserved:
- 10-dimension per-function scoring methodology (6 original + 4 new: concurrency, memory_safety, configuration, supply_chain)
- 9 engine-level scores (taint, crypto, firmware, memory, privacy ×4, compliance, dependency, config)
- Threat classification decision tree (with adjusted thresholds)
- Call categorization and return-value checking
- CFG-based cleanup path analysis
- Known API signature database
Added in v2.0.0:
- 9 specialized analysis engines (concurrency, taint, firmware, crypto, privacy, compliance, memory, dependencies, config)
Added in v2.1.0:
- String extraction and classification engine (
string_analyzer.zig): extracts ASCII/Unicode strings, classifies into 12 types (URLs, IPs, paths, registry keys, shell commands, crypto keys, emails, JWTs, base64, hex) with deterministic pattern matching — no regex dependency - 6 additional output formats (HTML, Markdown, CSV, SARIF, JUnit XML, DOT)
- 4 post-processing modules (FP reduction, CVSS, STRIDE, remediation)
- Plugin system, config file support, batch processing, result caching
- Modular file structure (27 files vs 1 file)
- All scores and thresholds adjusted for large binaries
The dependency checker includes 29 hardcoded CVE entries (e.g., OpenSSL 1.1.1 → CVE-2022-3602) compiled into the binary at build time. This is a static snapshot and is not dynamically updated. The database was last reviewed for the v2.1.0 release. Rebuild the binary to refresh from source.
Apache 2.0 — see LICENSE.