Domain Impersonation and OSINT Triage Tool. Compares a known-legitimate domain (target) against a suspect domain using DNS resolution, X.509 TLS certificates, and RDAP registration data, then produces a deterministic risk score and verdict. Single static binary; standard library plus golang.org/x/sync only.
git clone https://github.com/MARKMENTAL/phisherslapper.git cd phisherslapper CGO_ENABLED=0 go build -ldflags="-s -w" -o phisherslapper ./cmd/phisherslapper ./phisherslapper jdsoft.com jdsoftcareers.com go test ./... |
| Flag | Description |
|---|---|
| -v, --verbose | Append raw cert policy OIDs, TLS details, and RDAP JSON. |
| -j, --json | Output the result summary as JSON for scripting. |
| -k, --insecure | Skip TLS verification for RDAP (weakens results; last resort for devices without CA certificates). |
| --timeout=DUR | Per-call deadline for DNS/TLS/RDAP; Go duration, default 5s. |
| --scale | Print the scoring scale table and exit. |
| -h, --help | Display usage and exit. |
Both domains are fetched concurrently with golang.org/x/sync/errgroup under a 15 second global deadline; each DNS, TLS, and RDAP call carries a 5 second deadline (adjustable with --timeout) and is retried up to 3 times. Total run time equals the slower of the two domains. Fail-closed errors name the underlying cause(s).
parse args --> DNS pre-flight (target + suspect, parallel; keeps per-path IPs, checks hosts file)
--> fetch target = RDAP + TLS + per-path TLS + ASN in parallel
--> fetch suspect = RDAP + TLS + per-path TLS + ASN in parallel
--> sender authority = target SPF for suspect IP + target DMARC (fail-open)
--> fail-closed verify --> score --> render |
Exit codes: 0 on success (including --scale and --help), 1 on bad flags, invalid domains, DNS failure, or failed data-quality verification.
Each domain is probed once by the system resolver plus pinned 1.1.1.1 and 8.8.8.8 servers, and the outcomes are reused downstream. Only state is compared, never raw addresses: system-dark/public-live suppression splits and NS delegation splits flag tampering (+50 on the suspect), while system-live/public-dark split-horizon shapes and target-side splits stay display-only NOTEs. CDN/GeoDNS address churn stays quiet. Inconclusive resolvers abstain; filtered resolvers are excluded by design. The pre-flight gate aborts on system failure with hijack-aware messaging.
Beyond state comparison, the first live A record per side is retained and each endpoint is interrogated: the TLS identity served at the system-resolved IP is compared against the public-resolved IP (issuer, validation class, SANs, leaf fingerprint; SNI preserved). Origin autonomous systems for both IPs are attributed via Team Cymru (origin.asn.cymru.com TXT through the pinned resolver), and the OS hosts file is checked for static overrides. Divergent per-path TLS (+50), split origin AS (+30), and hosts-file overrides (+50) score on the suspect; target-side and inconclusive probes stay display-only. Raw addresses are never compared, so CDN/GeoDNS fronting stays quiet. Max total is 330.
The tool runs on embedded ARM devices (verified on a Miyoo Mini Plus), but minimal firmware often ships without a CA certificate store. DNS and certificate inspection still work there, while verified HTTPS (RDAP) fails; the fail-closed error names the cause (x509: certificate signed by unknown authority). Install ca-certificates and fix the clock where possible, otherwise use -k/--insecure as a last resort.
| Signal | Points |
|---|---|
| Suspect < 30d (CRITICAL), stacked w/ signal | +80 |
| Suspect < 30d (CRITICAL), isolated | +40 |
| Suspect 30-89d (WARNING), stacked w/ signal | +40 |
| Suspect 30-89d (WARNING), isolated | +20 |
| Shared cert infrastructure (halves age tier) | x0.5 |
| SPF endorsement (halves age tier) | x0.5 |
| Identical target/suspect (forced LEGITIMATE) | +0 |
| Resolution tampering: suppression split (suspect) | +50 |
| DNS split-horizon / target-side (display only) | +0 |
| Cert downgrade: target EV/OV vs suspect DV | +40 |
| Registrar mismatch | +30 |
| Same-class issuer difference (display only) | +0 |
| Rogue TLS: per-path cert divergence (suspect) | +50 |
| Rogue ASN: per-path AS split (suspect) | +30 |
| Hosts-file override (suspect) | +50 |
| Rogue signals target-side/inconclusive (info) | +0 |
| Chronology inversion: suspect far older than young target (info) | +0 |
| Score | Verdict |
|---|---|
| 0-14 | LIKELY LEGITIMATE (related pair) |
| 15-39 | LIKELY MALICIOUS OR NEGLIGENT (related pair) |
| 40-50 | SUSPICIOUS - MANUAL REVIEW RECOMMENDED |
| 51+ | LIKELY PHISHING / IMPERSONATION ATTEMPT |
| 0-39* | UNRELATED - NO AUTHORITY OVER TARGET |
* Unrelated pair: no shared SANs, SPF coverage, or label similarity. LEGITIMATE requires a relationship (endorsed or lookalike). Two clean companies sharing nothing still means zero cross-domain authority, so the verdict never reads legitimate for them.
Every pair is classified as identical, SAN-endorsed, SPF-endorsed, lookalike (confusable-aware root-label similarity), or unrelated. The target's SPF record is evaluated for the suspect's IP (RFC 7208 subset through the pinned resolver, 10-lookup budget, fail-open) and the target's DMARC policy is shown as context. Absence from SANs/SPF is never scored — it only proves no authority, which the UNRELATED verdict states.