Reverse-Engineering Dossier · Anonymous Messaging

Manufactured Longing

Inside NGL's fake-message engine — how a "who likes you?" app generates the very messages it then charges you to unmask.

64.2 MBAPK analysed
0Native libraries
59.3 MBDecompiled JS
24Scheduled firing slots
$5MFTC settlement, 2024

NGL is an anonymous-question app built for Instagram. You post a link, friends send you anonymous questions, and a paid tier — NGL Pro — promises to reveal who sent them. A user came to a simple suspicion: messages were arriving in the inbox when no link had ever been shared. This report documents a full static reverse-engineering of the Android client, and the suspicion is confirmed by the app's own code. NGL contains a purpose-built engine that generates messages attributed to no real person, schedules them to land when the inbox is quiet, and funnels the resulting curiosity into a weekly subscription.

IThe chain of custody

Every claim below is traceable to a specific artefact and a reproducible step. The client was acquired as a standalone Android package, fingerprinted, unpacked, and decompiled through two independent pipelines — one for the native DEX code, one for the JavaScript bytecode that carries virtually all of NGL's logic.

Artefact : ngl.apk
Size     : 64,215,002 bytes
SHA-256  : a9a2da21f19a89a49c3060e11152e5dd4bb8b8cced45f087c2722927672e9fc4

Pipeline 1 (DEX)      : jadx  →  Java sources for the Android/React-Native shell
Pipeline 2 (bytecode) : hermes-dec  →  assets/index.android.bundle
                        magic  c61f bc03   ·   Hermes bytecode version 98
                        output hbc-out.js  ·  59,337,247 bytes of reconstructed JS
Fig. 1 — Provenance. The bundle is Hermes bytecode, not plain JavaScript, so a standard JS decompiler is insufficient; hermes-dec reconstructs readable source from the compiled bytecode.

IIThe fake-message endpoint

The single most direct piece of evidence is a hard-coded Firebase URL that asks NGL's backend to manufacture engagement messages for the authenticated user's own account. The name is self-describing: generate-additional-ems — "EMS" for engagement messages.

Function block · reconstructed call site (hbc-out.js)
r8 = global;
r8 = r8.HermesInternal;
r9 = r8.concat;
r8 = 'https://ask-fun-d10f0.firebaseapp.com/api/generate-additional-ems?uid=';
r9 = r9.bind(r8)(r10);          // r10 = Firebase auth UID of the logged-in user
r7 = _closure1_slot3;
r8 = r7.default;
r7 = r8.get;
r7 = r7.bind(r8)(r9);           // HTTP GET, triggered from the client

The app takes your own Firebase uid, concatenates it onto this endpoint, and issues a GET. The backend then writes engagement messages into your account. This is not a message from another human; it is a request to NGL's servers to produce one on your behalf.

Your device Firebase auth uid GET generate-additional-ems?uid= ask-fun-d10f0.firebaseapp.com NGL backend writes fake messages Firestore users/{uid} .reengagementMessages Inbox feed fake ∪ real, merged “Who sent this? 👀” → NGL Pro, renews /wk
Fig. 2 — The manufacture loop, reconstructed from the client. The app requests engagement messages for its own user's account; the backend writes them into that user's document; the feed renders them next to genuine ones; and every manufactured item terminates at the subscription funnel.

IIIThe message factory

The client-side generator that shapes these messages is named, without any euphemism, generateFakeQuestion. The object it builds is the decisive artefact — read the flags closely:

Function block · generateFakeQuestion (hbc-out.js)
r7 = {
  'uid': null,                  // no sender — nobody sent this
  'text': null,                 // empty body
  'game': 'default',
  'prompt': 'send me anonymous messages…',
  'is_reported': false,
  'is_open': false,             // lands UNREAD
  'is_replied': false,          // lands UNANSWERED
  'timestamp': null,
  'isUserGenerated': true,      // ← tagged as if a person made it
  'textTranslationKey': null
};
The damning field is isUserGenerated: true. A message with a null uid, a null text and a null timestamp cannot have come from a person. Yet it is stamped as user-generated at the moment of creation — it enters your inbox wearing the flag that asserts a human made it, indistinguishable from the real thing in the feed. is_open: false and is_replied: false guarantee it arrives as a fresh, unread, unanswered item, maximising the pull to open it.
NEW · UNREAD “send me anonymous messages…” sender: anonymous · just now uid: null no sender exists — nobody sent this is_open: false · is_replied: false guaranteed to arrive fresh, unread isUserGenerated: true forged: stamped as human at creation
Fig. 3 — Anatomy of a manufactured inbox item. Every field that could identify a sender is null, yet the message carries the flag asserting a person made it.

IVThe reengagement timer

Faking a message is only half the system. The other half decides when to deploy it. The bundle carries a scheduling library keyed by day-of-week and hour, named REENGAGEMENT.*. The keys are literal time slots, and the copy is engineered to imply activity that did not happen.

14h16h17h 18h19h20h21h MondayTuesdayWednesday ThursdayFridaySaturdaySunday 1 1 1 1 2 1 1 2 1 1 1 1 2 1 1 2 1 1 3 4 1 1 4 1
Fig. 4 — All 24 reengagement firing slots, mapped by day and hour (base keys; seasonal variants such as SATURDAY20_EASTER and VALENTINES.* fire on top of these). Shading = number of distinct notification strings scheduled for that slot. Friday late afternoon through Saturday night is densest; Saturday 20h alone carries four copy variants.
Slot keyPush copy (English)Implied event
FRIDAY14"Someone typed a message…then left 🤫"Typing that never became a message
SATURDAY18"Typing…"A person at their keyboard
TUESDAY20"Someone viewed you 👀"A profile view
SUNDAY20"You have a new message 💌"An arriving message
THURSDAY18"New messages 💌"Plural arriving messages
WEDNESDAY18"Someone keeps coming back👀"Repeat visitor
FRIDAY21"Who sent this? 👀"Curiosity hook → paywall
MONDAY17"See sender hints 🕵️‍♂️"Direct Pro upsell
Fig. 5 — Eight of the 24 day/hour slots extracted from the bundle. The full set spans MONDAY17 through SUNDAY20, plus seasonal VALENTINES.* and WORLDCUP1/2 variants. Subtexts include "Tap here!", "Tap to reveal!" and "Drop your link and find out".

These are not generic reminders. They are manufactured impressions of human attention — "typing", "viewed you", "keeps coming back" — fired at chosen hours to maximise the chance you open the app to an empty or near-empty inbox, then encounter the prompt to post your link or pay to see who's interested.

VHow the fake is laundered into the real

The engineered messages are not quarantined. They are merged into the same feed as genuine ones. The Redux store holds loveMessages, boostedMessages and reengagementMessages alongside newMessages, and the Firestore document for your account (users/{uid}) carries reengagementMessages next to newMessages as a peer field.

Function block · useTopicNotifications — inbox assembly (hbc-out.js)
r1 = function(a0) {   // Original name: useTopicNotifications
  r12 = r2.reengagementMessages;   // ← read from user doc, merged into feed
  ...
  r10 = r2.userCountryCode;
  r9  = r2.userLanguage;
  r8  = r2.userDisablesLoveMessages;   // the "Team NGL messages" toggle
  ...
}

Because the fake and the real share the same collection and the same rendering path, the user has no in-product way to tell them apart. The only visible tell NGL provides is a small "sent with ❤️ from team NGL" label — and even that is what the FTC order took aim at.

VIThe paywall it feeds

Every manufactured message terminates in the same funnel. The user is invited to find out who is interested, then charged weekly for the answer:

Reengagement push or fake message lands in inbox — unread “Who sent this? 👀” · QUESTION.PAYWALL_BUTTON “Get a hint 🎬” — watch an ad, or pay Reveal Sender Info location · device · carrier · “suspects” NGL Pro renews weekly · /wk
Fig. 6 — The conversion loop. The "hints" sold are the sender's location, device, carrier/ISP and a list of "suspects" — metadata, and a guess at a name.

VIIThe regulatory record

This analysis was cross-checked against the public enforcement record, and it is important to state that record precisely rather than repeat loose versions of it.

Verified — FTC and California, July 9 2024. The FTC's case names plaintiffs the Federal Trade Commission and the People of the State of California, and defendants NGL Labs, LLC and officers Raj Vir and Joao Figueiredo. The defendants agreed to $5 million — $4.5M in consumer redress and a $500,000 civil penalty to the Los Angeles District Attorney's Office. The order bars offering the app to under-18s and prohibits misrepresenting the source of messages. The FTC alleged NGL generated fake computer messages that appeared to be from real people and used them to drive Pro subscriptions by suggesting Pro would reveal senders' identities.

Verified — TechCrunch, June 29 and July 11 2022. Sarah Perez reported that NGL sent automated questions even after the shared Instagram Story link was taken down — proving the messages were not from friends — and that NGL charged about $9.99/week for "hints".

Corrected — two circulating claims could not be verified. I could find no authoritative source for (a) a separate 2023 Los Angeles City Attorney lawsuit against NGL, or (b) a 2023 Meta lawsuit against NGL. The 2024 matter involved the LA District Attorney's Office as part of the FTC action, not a distinct 2023 City Attorney case. Meta's documented 2023 scraping suit was against Voyager Labs, not NGL. These claims are dropped from this report rather than repeated unverified.
Jun 29, 2022 TechCrunch: automated questions with no link Jul 9, 2024 FTC + California: $5M · under-18 ban Jul 11, 2022 15M installs · users report being scammed Oct 2026 This analysis
Fig. 7 — The public record, from first expose to enforcement.

VIIIWhat this actually means

Strip the mechanics back and NGL's core loop is this: manufacture the evidence of interest, then sell the resolution. The app's value proposition is that people are curious about you. The fake-message engine supplies that evidence when the real world doesn't provide it, and the reengagement timer ensures it arrives precisely when you're most likely to be alone with an empty inbox. The subscription is the only way out of the anxiety the app itself creates.

reinvested into manufacturing more messages Fake messagemanufactured Push arrivesat a quiet hour Curiosity:“who sent it?” Pay tounmask Weeklyrevenue
Fig. 8 — The loop, end to end. Each turn of the wheel is funded by the anxiety the previous turn created.

Two details elevate this from "dark pattern" to something worse. First, the isUserGenerated: true stamp means a machine-authored message is labelled, at creation, as human — this is not a neutral "sample" message, it is a forgery of a person. Second, the product's audience skews young, and the FTC order had to explicitly bar NGL from offering the app to under-18s — a restriction you do not impose on a company that was acting responsibly toward children.

For the user who started this: messages arriving with no shared link are, on this evidence, almost certainly NGL's own. The "Team NGL messages" setting (backed by the disablesLoveMessages flag) may mute the labelled ones, but it does not disable the reengagement timer or the server-side generate-additional-ems endpoint. The only reliable way to stop the manufactured attention is to stop using the app.

What you can do

References

  1. Federal Trade Commission — FTC Order Will Ban NGL Labs and Its Founders From Offering Anonymous Messaging Apps to Kids Under 18, July 9 2024. ftc.gov press release
  2. Federal Trade Commission — case record, NGL Labs, LLC. ftc.gov legal library
  3. Sarah Perez, TechCrunch — Anonymous social apps shift their attention to Instagram…, June 29 2022. techcrunch.com
  4. Sarah Perez, TechCrunch — Anonymous social NGL tops 15M installs… as users complain about being scammed, July 11 2022. techcrunch.com
  5. Meta Newsroom — Leading the Fight Against Scraping-for-Hire (Voyager Labs, Jan 12 2023; cited here only to correct the misattributed "Meta v. NGL" claim). about.fb.com

Primary technical evidence is from the analysed artefact ngl.apk (SHA-256 above) and its reconstructed Hermes bundle hbc-out.js. Code blocks are transcribed from that decompilation. Legal references were verified against the linked official sources in October 2026; two widely-repeated but unverifiable claims were removed (see §VII).