DEV Community

Cover image for Fuck Around and Find Out: How a $6.99 Phishing Scam Got 1.2 Million Fake Victims
Mr. 0x1
Mr. 0x1

Posted on • Originally published at github.com

Fuck Around and Find Out: How a $6.99 Phishing Scam Got 1.2 Million Fake Victims

A forensic teardown and hostile response to the Smishing Triad's Lighthouse phishing kit.

fuck-around-and-find-out


The Hustle

It started, as these things always do, with a text message.

California DMV Final Notice: Enforcement will begin on March 21.
Our system indicates you have an unresolved traffic violation.
Per relevant regulations, if payment is not completed by March 20, 2026, the following will apply:

  1. Update your record in the DMV system
  2. Suspend your vehicle registration starting March 21
  3. Temporarily restrict driving privileges for 30 days
  4. Refer your account for further processing with an additional administrative fee
  5. Possible legal follow-up and impact to your credit record

Please settle this promptly to avoid service restrictions and additional procedures.
Link: https://ca.gov-axb.cfd/dmv

Classic. Urgency. Authority. Escalating consequences. A $6.99 "traffic violation" — just low enough that a panicked person might pay it without thinking. The link even starts with ca.gov- to give it that government feel, like the digital equivalent of a trench coat and a fake badge.

They sent this to the wrong phone.


The Forensics

Twenty-two hours. That's the entire lifespan of this operation from domain registration to active phishing campaign. Let's appreciate the speedrun:

Timestamp Event
2026-03-19 14:10 Domain gov-axb.cfd registered via Gname.com (Singapore)
2026-03-20 ~12:17 Let's Encrypt SSL certificate issued for ca.gov-axb.cfd
2026-03-20 ~13:00 Smishing messages begin arriving

The domain was registered on a .cfd TLD — that's "Clothing Fashion Design," in case you were wondering what haute couture has to do with the California DMV. It costs about $0.98 to register. The attackers configured wildcard DNS pointing everything at 47.89.135.90 — an Alibaba Cloud server — so ca.gov-axb.cfd, tx.gov-axb.cfd, fl.gov-axb.cfd, and literally any subdomain you can dream up all resolve to the same phishing kit. Seven confirmed state-targeted subdomains on a single domain. Assembly line phishing.

The nameservers (share-dns.com, share-dns.net) are a Chinese DNS provider. The registrar abuse contact is in Singapore. The hosting is Alibaba Cloud's US allocation. It's a jurisdictional lasagna designed to make takedowns as painful as possible.


Meet the Kit: Lighthouse

The phishing page itself is a slick California DMV impersonation — official logo, official color scheme, footer links to real .ca.gov pages. It's built on Vue.js 3, bundled with Vite, communicating over Socket.IO with AES-128-CBC encrypted WebSocket messages. This isn't some amateur HTML form. This is a commercial product.

It's called Lighthouse — a phishing-as-a-service (PhaaS) platform operated by the Smishing Triad, a Chinese cybercrime operation that Google literally filed a federal lawsuit against in November 2025. The operator, attributed to someone going by Wang Duo Yu, runs a platform serving ~300 "front desk staff" worldwide, targeting 316+ brands across 74 countries through an estimated 194,000+ malicious domains.

The kit has a real-time operator panel. When a victim lands on the page, the operator sees their session appear in real time. As the victim fills in their name, address, credit card — the data streams live to the operator's dashboard. They can push the victim through verification steps in real time: "Enter the code we just sent to your phone." "Now enter your card PIN." It's live, interactive social engineering at industrial scale.

The victim flow:

Landing Page → Contact Info Form → Credit Card Form → Verification Codes → 💀
Enter fullscreen mode Exit fullscreen mode

Every field submission, every page navigation, every keystroke-level interaction — all wrapped in AES encryption and shuttled over WebSocket. The kit even has anti-debugging protections in its JavaScript, string obfuscation tables, and mobile User-Agent gating (it won't even load if you're not on a phone browser).

They thought of everything.

Almost.


The Reverse Engineering

The kit's JavaScript is two files totaling ~570KB of heavily obfuscated code. Here's what that looks like:

function xe(){const t=["YWdl","message","Y2hhbm","Zmllb","c3VibW","bm90a..."];
// ... 260,000 more characters of this
Enter fullscreen mode Exit fullscreen mode

Every meaningful string — event names, API paths, encryption keys — is routed through a deobfuscation function (be()) that indexes into a shuffled, Base64-encoded string table. The Socket.IO connection path isn't /socket.io/ like normal. It's been moved. The encryption key and IV aren't in plaintext. Nothing is where it should be.

Step 1: Find the Socket.IO Path

After failing to statically decode the obfuscation (the string table uses a self-modifying shuffle — it rearranges itself during initialization), I pivoted to empirical observation. Loaded the page in a headless browser with a mobile User-Agent, captured the WebSocket traffic:

wss://ca.gov-axb.cfd:443/console/?uuid=<uuid>&EIO=4&transport=websocket
Enter fullscreen mode Exit fullscreen mode

The Socket.IO path is /console/. Not /socket.io/. Not /ws/. Not anything in the standard playbook.

Step 2: Crack the Encryption

All WebSocket messages are encrypted. Client sends 42["message","<base64>"], server responds the same way. The actual event data is AES-128-CBC encrypted inside that base64 blob.

From the obfuscated source, I could see the key and IV were assembled from string fragments:

const We = Be(226) + ye(250) + ze(254) + "LDND";   // AES key
const Se = "OJGJHHFMJEJB" + we(259);                // AES IV
Ne = CryptoJS.enc.Utf8.parse(We);                    // → WordArray
Te = CryptoJS.enc.Utf8.parse(Se);                    // → WordArray
Enter fullscreen mode Exit fullscreen mode

The Be(), ye(), ze(), we() functions are all aliases for the same deobfuscator, returning short string fragments. I couldn't decode them statically — the shuffle function defeats that approach.

So I intercepted the JavaScript in flight. Using Playwright's route API, I caught the JS file as it loaded, injected a single line that exposed the computed key values to the global scope, and read them out:

await context.route('**/CPD9iRZf.js', async (route) => {
    const response = await route.fetch();
    let body = await response.text();
    body = body.replace(
        /Se="OJGJHHFMJEJB"\+\w+\(\d+\)/,
        (match) => match + ';window.__AES_KEY=We;window.__AES_IV=Se'
    );
    await route.fulfill({ response, body });
});
Enter fullscreen mode Exit fullscreen mode

Key: KIKOCCJCFILDLDND
IV: OJGJHHFMJEJBDFAI

Verified by decrypting a captured server message:

{"data":{"money":"","successUrl":"","currencySymbol":"","products":[]},"event":"userSiteConfig"}
Enter fullscreen mode Exit fullscreen mode

And a captured client message:

{"event":"changleField","data":{"router":"首页"}}
Enter fullscreen mode Exit fullscreen mode

That typo — changleField instead of changeField — is a known Lighthouse kit fingerprint. It's in every deployment. Somewhere, a developer fat-fingered it once, and now it's a forensic signature stamped across 194,000 domains.

Also: 首页 is Mandarin for "home page." The Chinese-language strings are everywhere in the source: 手机验证页 (phone verification page), 运通CVV验证页 (Amex CVV verification page), 加密异常! (encryption exception!). For a kit that goes to great lengths to look like the California DMV, it sure does think in Mandarin.


The Weapon

With the encryption cracked and the protocol reverse-engineered, it was time to build.

Not a Python script. Not a Node.js hack. Rust. Specifically: an async, multi-session, zero-copy WebSocket flood engine using Tokio, with native AES-128-CBC encryption, realistic fake data generation, and the exact Socket.IO protocol the kit expects.

Each session:

  1. Opens a WebSocket to /console/ with a mobile User-Agent
  2. Completes the Engine.IO handshake
  3. Sends the Socket.IO connect packet
  4. Responds to server heartbeats (ping 2 → pong 3)
  5. Encrypts and sends 12 events mimicking a complete victim session:
    • Router navigation (changleField — yes, with the typo)
    • Full personal info (name, address, city, state, zip, phone, email)
    • Full credit card data (Luhn-valid card number, holder name, expiry, CVV)
    • Phone verification code
    • Email verification code
    • PIN code
    • Express CVV re-verification
    • Custom verification code
  6. Closes gracefully

Every piece of fake data is realistic:

  • Names drawn from US census frequency tables
  • Addresses with real California street patterns and cities
  • ZIP codes matching California postal zones
  • Phone numbers with correct California area codes
  • Credit cards that pass Luhn validation (Visa, Mastercard, Amex, Discover prefixes)
  • Email addresses with realistic username patterns at common providers

From the server's perspective, each session is indistinguishable from a real victim clicking through the phishing flow.


The Flood

╔══════════════════════════════════════════════════════════╗
║       LIGHTHOUSE FLOOD — Pure Rust WebSocket Engine     ║
║       AES-128-CBC | Direct Socket.IO | Max Throughput   ║
╚══════════════════════════════════════════════════════════╝
Target:       https://ca.gov-axb.cfd
WS Path:      /console/
Concurrency:  100
Count:        ∞
Enter fullscreen mode Exit fullscreen mode

First test: 5 sessions, 3 concurrent. 60 events, 0 errors. Proof of concept.

Second test: 200 sessions, 30 concurrent. 2,400 events, 0 errors, 28 seconds. Warming up.

Third test: 1,000 sessions, 100 concurrent. 12,000 events, 0 errors, 42 seconds. Now we're talking. ~24 complete fake victims per second.

Then we let it rip.

╔══════════════════════════════════════════════════════════╗
║                     FLOOD COMPLETE                      ║
╠══════════════════════════════════════════════════════════╣
║  Submitted: 100700  |  Events: 1208984  |  Errors:    0 ║
╚══════════════════════════════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

One hundred thousand fake victim sessions. 1.2 million encrypted events. Zero errors.

One hour. One machine. One Rust binary. Their operator's dashboard — the same one they use to monitor real victims in real time — is now a firehose of:

  • Jennifer Wilson from San Jose, CA 95132, card ending in 8388
  • Kevin Sanchez from Chula Vista, CA 92101, card ending in 6501
  • Laura Martin from Santa Ana, CA 92701, card ending in 4787
  • ... times one hundred thousand.

Every single entry looks real. Luhn-valid card numbers that'll fail at the processor. California addresses that go to actual streets. Phone numbers that ring actual area codes. The operators can't tell which data is real and which is garbage. Their entire database is poisoned.

For every real victim they managed to phish today, there are now thousands of fake records burying them. Good luck finding the needle in that haystack.


The Takeaway

This particular phishing operation is part of a massive, well-funded, commercially operated cybercrime ecosystem. The Smishing Triad runs Lighthouse as a business — subscription model, customer support, Telegram channels, the works. Google sued them. The FBI has received thousands of complaints. They're still operating.

Individual takedowns are whack-a-mole. The domain gov-axb.cfd will die, and tomorrow there'll be gov-xyz.cfd and gov-abc.win and a hundred more. The kit itself rotates, the infrastructure shifts, the TLDs change.

But today? Today, one specific operator's database is garbage. One specific campaign's ROI just cratered. One specific Lighthouse instance's real-time dashboard is scrolling fake Californians faster than any human could possibly triage.

They set up an encrypted, obfuscated, anti-debugging, mobile-gated phishing operation.

We reverse-engineered the encryption in an afternoon and flooded them with a million fake victims before dinner.

Fuck around. Find out.


Technical Summary

Component Detail
Target ca.gov-axb.cfd (California DMV phishing)
Threat Actor Smishing Triad / Lighthouse PhaaS
Kit Stack Vue.js 3 + Vite + Socket.IO + AES-128-CBC
Socket.IO Path /console/ (non-standard)
Encryption Key KIKOCCJCFILDLDND (UTF-8)
Encryption IV OJGJHHFMJEJBDFAI (UTF-8)
Kit Fingerprint changleField typo in all event names
Flood Tool Rust + Tokio + tungstenite (async WebSocket)
Sessions Completed 100,700+
Events Sent 1,208,984+
Error Rate 0.000%
Throughput ~24 complete victim sessions/second
Duration ~63 minutes

Filed under: threat intelligence, active defense, phishing disruption, and not taking shit from scammers.

Top comments (0)