SDK Spoofing Detection: A 2026 Technical Mobile Fraud Guide
SDK spoofing forges install events to steal attribution. The 5 attack vectors, hashed signature validation, and server-side detection patterns.
SDK spoofing is the deliberate forging of mobile install or in-app events to claim attribution credit for installs that never happened. The attacker either captures a legitimate signal and replays it, or reverse-engineers the SDK’s signature scheme and constructs valid-looking payloads from scratch. The target is the cryptographic chain between a click and its install, the same chain Mobile Measurement Partners (MMPs) use to decide which ad network gets paid. AppsFlyer’s State of Mobile App Fraud and Adjust’s fraud reports have consistently placed mobile install-fraud exposure in the tens of billions of dollars annually. [1]
This guide is for mobile developers, ad-ops engineers, and growth teams who need to understand SDK spoofing past the marketing description. We cover the attack model (replay vs forge), how MMPs sign and validate signals, the five active attack vectors, the detection techniques that work, a working server-side validation pattern, and what MMPs systematically miss.
- SDK spoofing forges fake installs, it does not manipulate real ones. The attacker bypasses the device entirely by constructing or replaying signed payloads to the MMP’s attribution endpoint.
- Two attack models dominate. Replay captures a legitimate signal and re-sends it within the signature validity window. Forge reverse-engineers the SDK to construct valid HMAC signatures using extracted salts.
- Hashed signature attribution with rotating salts is the primary MMP defense. Typical rotation is every 24 hours with a 60-120 minute overlap window. Salt rotation makes extracted secrets worthless within one cycle.
- CTIT distribution analysis catches what signatures miss. Real installs cluster around 30-90 seconds with a smooth tail. Spoofed installs cluster at suspiciously precise intervals or arrive before the click timestamp.
- Multi-signal validation beats single-MMP detection. Cross-MMP correlation, device fingerprint integrity, ASN classification, and downstream conversion drop-off catch the share single-vendor detection misses.
What is SDK spoofing, exactly?
SDK spoofing is a server-to-server forgery attack on mobile attribution, where an attacker submits crafted install payloads directly to an MMP’s attribution endpoint without a real install ever occurring on a real device. AppsFlyer documents this category under its Protect360 fraud taxonomy as one of the highest-payout mobile fraud types, with attempted-spoof rates in high-risk networks regularly hitting double-digit percentages. [1]
The attack targets the trust boundary between the MMP server and the SDK. When a real install occurs, the MMP SDK on the device collects install parameters (timestamp, click ID, device parameters, advertiser ID) and posts them to the MMP’s attribution endpoint with an attached HMAC signature. The MMP server validates the signature, looks up the matching click, and attributes the install to whichever network’s click matched.
SDK spoofing skips the device entirely. The attacker generates the payload server-side, signs it (if they can), and posts directly to the same attribution endpoint the SDK would. If the signature validates, the MMP attributes the “install” exactly as if a real user had downloaded the app. The advertiser pays for an install that never happened.
[click injection vs click flooding](/blog/en/click-injection-vs-click-flooding/ for the on-device mobile fraud counterparts that target the click side of the chain)
Replay attacks (capture and resend)
The simpler attack vector. The attacker observes legitimate install traffic, either by running the MMP SDK in a controlled environment, sniffing traffic from a compromised device, or intercepting man-in-the-middle on a rooted handset. They capture a valid install payload with its signature, modify the install timestamp or device identifier just enough to look fresh, and resend it within the signature’s validity window.
Replay attacks work because most MMP signatures are bound to the click ID and a limited set of payload fields, not to every parameter. If the signature is computed over fields the attacker does not need to change (e.g., advertiser ID, network ID, click timestamp), the captured signature remains valid as long as the salt has not rotated.
Forge attacks (reverse engineer the signature scheme)
The harder, higher-payoff attack. The attacker decompiles the MMP SDK, reverse-engineers the HMAC scheme, and extracts the signing inputs and any embedded salt fragments. They then construct valid signatures programmatically and inject arbitrary fake installs into the attribution graph, with no need to wait for legitimate traffic to capture.
Forge attacks scale; replay attacks do not. A replay attack requires fresh legitimate traffic to copy. A successful forge attack lets the attacker mint installs on demand, limited only by the salt rotation cadence and any volume-based anomaly detection downstream.
How do MMPs sign and validate SDK signals?
Mobile Measurement Partners protect the click-to-install chain with HMAC-signed payloads using rotating server-side salts. Both AppsFlyer (via Protect360 / Secure Click) and Adjust (via SDK Signature) document HMAC-based schemes that bind clicks to installs through cryptographic signatures only the MMP server can validate. [2] The signature is the integrity check that makes forgery expensive.
The HMAC signature chain
The canonical flow:
- A user clicks an ad. The ad network calls the MMP’s click endpoint with click parameters.
- The MMP server records the click and computes an HMAC over a canonical set of fields (click ID, network ID, advertiser ID, click timestamp, device parameters where available) using a server-side salt the MMP rotates.
- The MMP returns a signed click ID or signed redirect URL. The signature travels with the user to the app store or app open event.
- When the install completes and the MMP SDK fires, the SDK includes the signature in its install payload alongside the original click parameters.
- The MMP server recomputes the HMAC using the canonical fields plus its current salt set. If the signature matches, the install is attributed. If not, it is rejected as spoofed.
Salt rotation policy
The salt is what keeps the scheme alive against reverse engineering. Industry practice typically rotates the signing salt every 24 hours with a short overlap window (often 60-120 minutes) where both the previous and current salt are accepted. The overlap accommodates clicks that converted late.
| Parameter | Typical value | Why it matters |
|---|---|---|
| Salt rotation period | 24 hours | Limits useful lifetime of any extracted secret |
| Overlap window | 60-120 minutes | Avoids dropping legitimate late-converting clicks |
| Signature validity window | 7-30 days | Hard cutoff after which clicks can no longer attribute |
| HMAC algorithm | HMAC-SHA256 (typical) | Industry-standard cryptographic primitive |
| Salt distribution | Server-side only, never embedded in SDK | Prevents extraction from decompiled APK / IPA |
The critical design point: the salt never ships to the device. Only the MMP server holds it. The SDK ships only the inputs to the HMAC and the resulting signature it receives from the click side of the flow. This prevents trivial extraction by decompiling the published SDK binary.
Server-side timestamp validation
Independent of the signature itself, MMPs validate the install timestamp against several constraints:
- The install timestamp must be after the click timestamp (an install before a click is impossible)
- The install must fall within the signature validity window (typically 7-30 days post-click)
- The CTIT must fall within plausible bounds, with anomalous values flagged for review
- The install timestamp must be reasonably close to server receipt time, accounting for clock drift
Timestamp validation alone catches the laziest replay attacks where the attacker forgets to update the click timestamp or sends installs with future-dated install times.
[types of ad fraud](/blog/en/types-of-ad-fraud/ for the broader fraud taxonomy including SDK spoofing’s place among mobile attribution attacks)
What are the 5 SDK spoofing attack vectors?
Across the mobile fraud cases we see in production, five attack vectors account for almost all SDK spoofing activity. They are ordered by frequency, not by sophistication.
1. Click signature replay within validity window
The most common attack. The attacker captures one or more valid signed click payloads (from compromised devices, sniffed traffic, or controlled test installations) and replays them with mutated install parameters as fast as the salt overlap permits.
Tell: identical click signatures attributing to multiple distinct device fingerprints within the same validity window. The same click cannot legitimately produce two installs on two different devices.
2. SDK reverse-engineered and signal forged
The high-value attack. An attacker decompiles the MMP SDK (publicly distributed in every published app’s APK or IPA), maps the HMAC inputs, and identifies any embedded constants. If the SDK contains a per-app key or a derived salt fragment, the attacker extracts it and generates valid signatures on demand.
Modern MMP SDKs are heavily obfuscated specifically to raise the cost of this attack. The defense is salt rotation: even a successful extraction has a useful life measured in hours, not weeks.
Tell: spikes of installs from a single network with perfect signatures but implausible device or network characteristics (mismatched IDFA pools, impossible OS / carrier combinations).
3. Time-shifted clicks exploiting anti-fraud time window
Some MMPs apply lenient CTIT bounds to avoid false positives on legitimate slow-converting users. Attackers exploit this by injecting clicks with backdated timestamps that fall within the lenient window, then submitting installs that land in the “plausible” CTIT range.
Tell: CTIT distributions for a network that cluster at suspiciously precise intervals (e.g., exactly 7 minutes, exactly 30 minutes) rather than following the smooth bimodal distribution of real human installs.
4. Cross-attribution claim hijacking
A subtle attack. The attacker observes (through cross-MMP visibility or compromised tracking links) that a user is about to install organically or via a competing network. They inject a click and a fake install signal into the targeted MMP for that device in time to win last-click attribution, hijacking credit for the install.
This vector blurs the line between SDK spoofing and click injection. The forgery here is the install signal claiming the install was driven by the attacker’s network, when the real driver was elsewhere.
Tell: high-payout installs where the device shows organic install signals (direct app-store open, no prior click record in cross-MMP correlation) but a single network claims attribution at the last moment.
5. Test-mode signals leaked to production
The accidental attack. MMP SDKs ship with test or sandbox modes that bypass full signature validation to support development. If a test API key, test endpoint, or test signing salt leaks (committed to a public GitHub repo, extracted from a debug build, or shared in a Slack screenshot), attackers can submit installs against the test path that bypass normal validation.
Tell: clusters of installs attributed via test or sandbox app keys, or installs originating from build IDs that match internal QA builds.
[app-ads.txt for mobile](/blog/en/app-ads-txt-mobile/ for the supply-side authorization layer that catches related domain and seller spoofing in mobile programmatic)
How do you detect SDK spoofing?
Server-side signature validation is the first line, but it never stands alone. AppsFlyer’s Protect360 and Adjust’s fraud prevention suite both document multi-layer detection combining cryptographic validation, time-distribution analysis, and behavioral signals. [2] The combination matters because each layer catches attacks the others miss.
Hashed signature validation (server-side recomputation)
The non-negotiable baseline. Every install payload must arrive with a valid HMAC signature computed server-side over the canonical input set using a current or recent-overlap salt. Signatures that do not validate are rejected silently and logged for analysis. Silent rejection is important: returning an error to the caller tells the attacker their signature failed and helps them iterate.
Time-window enforcement (7-15 minutes typical)
Hard bounds on the click-to-install delta. Installs that arrive faster than the minimum (typically 7-15 seconds) are flagged as click-injection candidates. Installs that arrive after the signature validity window (typically 7-30 days) are rejected outright. The middle range is scored against the CTIT distribution.
Cross-MMP correlation
A single MMP sees only the installs attributed to its own SDK. A user who installs an app typically generates signals across multiple measurement systems (Apple’s SKAdNetwork, Google Play Install Referrer, the MMP, the publisher’s own analytics). When one MMP claims an install but no other measurement system saw the click that drove it, the install is statistically anomalous.
Cross-MMP correlation is the single highest-leverage signal we see catching sophisticated forge attacks. A perfectly signed install with no corresponding SKAdNetwork postback, no Install Referrer, and no advertiser-side server analytics record is almost certainly forged. The forger built a valid signature; they could not also forge Apple’s SKAdNetwork chain.
Click-to-install time distribution analysis (CTIT)
The behavioral check that survives signature compromise. Real human installs follow a recognizable CTIT distribution: a sharp peak around 30-90 seconds (immediate downloads), a smooth log-normal tail out to several hours, and a long tail of users who install days later after seeing the ad. Spoofed installs frequently show:
- Clustering at unnatural intervals (every install at exactly 7 minutes 12 seconds)
- Unrealistically smooth or perfectly uniform distributions
- Bimodal distributions that match attacker scripts more than human behavior
- Impossible values (installs before the click, installs more than 30 days after a click)
Device fingerprint and network plausibility
Each install payload includes device parameters (model, OS version, locale, carrier, IDFV or Android ID where available). Forged payloads frequently leak forger fingerprints:
| Signal | Spoofing tell |
|---|---|
| IDFA / IDFV pool | Fresh IDFA on every install, IDFV missing entirely, IDFA values from known emulator pools |
| OS / model combination | iOS 18 on iPhone 6, Android 15 on impossible hardware |
| Carrier / IP geolocation | ”T-Mobile US” carrier with a Vietnamese data-center IP |
| ASN | Data-center ASN (DigitalOcean, AWS, OVH) claiming a mobile install |
| Locale | Locale that doesn’t match plausible carrier or IP geography |
| Battery level / orientation | Fixed values across thousands of installs (common simulator default) |
Downstream conversion drop-off
The last-mile check. Spoofed installs almost never produce real in-app behavior. A network with a 0% day-1 retention rate, no in-app purchases, no level completions, and no session activity is showing classic spoofing signatures even when individual installs validate cryptographically.
Working code: server-side signature validation pattern
The below is a reference pattern for the server-side signature validation flow an MMP or an advertiser-side validation layer would run. It is illustrative, not a drop-in implementation; production code requires the actual MMP’s canonical input ordering, salt distribution mechanism, and overlap-window policy.
// Server-side HMAC validation pattern for MMP install postbacks
// Pair with CTIT analysis, ASN classification, and cross-MMP correlation
// for production-grade SDK spoofing detection.
const crypto = require('crypto');
// Salt store: holds current and previous salts during overlap window
const saltStore = {
current: process.env.MMP_SALT_CURRENT,
previous: process.env.MMP_SALT_PREVIOUS,
rotatedAt: Date.parse(process.env.MMP_SALT_ROTATED_AT),
overlapWindowMs: 90 * 60 * 1000, // 90 minutes
};
// Canonical input ordering MUST match the SDK side exactly.
// Any drift here invalidates every legitimate signature.
function canonicalInput(payload) {
return [
payload.click_id,
payload.network_id,
payload.advertiser_id,
payload.click_ts,
payload.install_ts,
payload.device_id || '',
payload.bundle_id,
].join('|');
}
function hmac(input, salt) {
return crypto.createHmac('sha256', salt).update(input).digest('hex');
}
function validSignature(payload, signature) {
const input = canonicalInput(payload);
const expectedCurrent = hmac(input, saltStore.current);
// Constant-time comparison to avoid timing oracles
if (crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedCurrent, 'hex'))) {
return { valid: true, salt: 'current' };
}
// Overlap window: previous salt also accepted briefly
const inOverlap = (Date.now() - saltStore.rotatedAt) < saltStore.overlapWindowMs;
if (inOverlap && saltStore.previous) {
const expectedPrev = hmac(input, saltStore.previous);
if (crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedPrev, 'hex'))) {
return { valid: true, salt: 'previous' };
}
}
return { valid: false };
}
// CTIT plausibility check: rejects sub-second installs and stale clicks
function ctitPlausible(clickTs, installTs) {
const ctit = installTs - clickTs;
if (ctit < 7000) return { ok: false, reason: 'sub-7s-ctit' }; // click injection floor
if (ctit > 30 * 24 * 60 * 60 * 1000) return { ok: false, reason: 'stale-click' };
// Tighter ranges are scored, not gated; feed to distribution analysis.
return { ok: true, ctit };
}
// Top-level validator. Returns reject reasons separately so downstream
// systems can score rather than gate on individual signals.
function validateInstallPostback(req) {
const { payload, signature } = req.body;
const reasons = [];
const sig = validSignature(payload, signature);
if (!sig.valid) reasons.push('bad-signature');
const ctit = ctitPlausible(payload.click_ts, payload.install_ts);
if (!ctit.ok) reasons.push(`ctit:${ctit.reason}`);
// Stub: ASN classification, fingerprint plausibility, cross-MMP lookup
// would attach further reasons here.
if (looksLikeDataCenter(req.ip)) reasons.push('datacenter-ip');
if (impossibleDeviceCombo(payload)) reasons.push('device-impossible');
return {
accepted: reasons.length === 0,
reasons,
silentReject: reasons.includes('bad-signature'), // never tell attacker why
};
}
Two practical notes on shipping this:
- Silent rejection on signature failure. Never return a descriptive error to the caller on a signature mismatch. A loud 403 with “invalid signature” is a signal the attacker uses to iterate. A silent 200 with the install quietly discarded is much harder to attack.
- Score, do not gate, on soft signals. Signature failure is a hard reject. CTIT anomalies, ASN mismatches, and impossible device combos are scored, fed into a multi-signal model, and flagged for downstream attribution decisions. Hard-blocking on a single soft signal causes too many false positives.
What do MMPs catch versus miss with SDK spoofing?
In the mobile fraud cases we work through with advertisers, MMP-side detection is consistently strong on the cryptographic layer and consistently weak on the cross-system correlation layer. The asymmetry shapes where third-party validation pays back.
What MMPs catch reliably
- Signature failures and replay outside the validity window. Every legitimate MMP rejects bad signatures and stale clicks at the door.
- Trivial CTIT anomalies. Installs before clicks, installs days after the validity window, sub-second CTIT values.
- Known fraud-network IP ranges and device fingerprint pools. MMPs maintain shared blocklists and emulator fingerprint databases.
- Volume-based anomalies inside their own attribution graph. A network suddenly claiming 100x more installs than its historical baseline gets flagged.
What MMPs systematically miss
- Cross-MMP collusion. When the same install is claimed by two different MMPs (each running on a different SDK in the app), neither MMP sees the duplicate. Only the advertiser, who runs both, can correlate.
- Sophisticated CTIT modeling. Attackers who study the published CTIT distribution and inject installs that fit the curve evade simple bound checks.
- Replay inside the validity window. Until the salt rotates, a valid captured signature remains valid. Detection here depends on noticing the same signature attributing across multiple devices.
- Forge attacks with extracted salts. During the hours between extraction and rotation, forged signatures validate cleanly. MMP detection here depends on volume anomalies and downstream conversion drop-off, which lag the fraud.
- Test-mode leaks and sandbox key abuse. Many MMPs allow test traffic at scale during development, and abuse via leaked test keys often goes undetected until manual audit.
| Detection layer | MMP coverage | Third-party validation coverage |
|---|---|---|
| Signature validation | Strong | Redundant |
| CTIT bound checks | Strong | Strong |
| Sophisticated CTIT distribution modeling | Variable | Strong |
| Cross-MMP correlation | Weak (single-vendor blindspot) | Strong |
| Downstream conversion drop-off | Weak (no in-app visibility) | Strong |
| Device fingerprint cross-referencing | Strong (MMP-specific pools) | Strong (broader pools) |
| Test-mode and sandbox key abuse | Weak | Variable |
Where Adsafee fits
Adsafee provides a server-side validation layer that sits between MMP postbacks and the advertiser’s attribution decisions. The layer recomputes signature validity where the MMP exposes the canonical input set, models CTIT distributions per network and per campaign, runs cross-MMP correlation when multiple measurement systems are deployed in the same app, and applies downstream conversion drop-off scoring to flag networks whose installs never produce day-1 retention or in-app events. The verdict returns in under 100 ms via REST API or S2S postback and ships with per-install evidence for refund disputes against the offending network.
If you want to see whether your mobile attribution is being spoofed at the network level, start a free trial. Setup takes about 10 minutes and the first audit returns same-day.
FAQ
The frontmatter faq block contains the structured Q&A this page exposes to search engines. The questions cover SDK spoofing fundamentals, how it differs from click injection and click flooding, hashed signature attribution, salt rotation cadence, CTIT analysis, MMP coverage gaps, fraud market sizing, and the multi-signal cross-checks that survive signature compromise.
Sources
AppsFlyer, “State of Mobile App Fraud” annual reports and Protect360 fraud taxonomy documentation, covering SDK spoofing, install fraud rates, and signature-based protection. Visit: appsflyer.com/resources/reports/mobile-app-fraud/. ↩
Adjust, SDK Signature and Fraud Prevention Suite documentation, covering HMAC-based click-to-install signing, salt rotation, and the fraud filters Adjust applies to install postbacks. Visit: adjust.com/glossary/sdk-spoofing/. ↩
IAB Tech Lab, Mobile Programmatic and OpenRTB specifications, including SKAdNetwork and Install Referrer integration guidance, the open-standards layer underneath cross-MMP correlation. Visit: iabtechlab.com. ↩
Frequently asked questions
What is SDK spoofing?
SDK spoofing is a mobile attribution fraud technique where an attacker forges fake install or in-app events that appear to originate from a legitimate Mobile Measurement Partner (MMP) SDK. The goal is to claim attribution credit, and the payout, for installs that never happened or that were driven by organic traffic. Two main flavors exist: replay attacks (capturing a real install signal and replaying it) and forge attacks (reverse-engineering the SDK's signature scheme and constructing valid-looking payloads). Both target the integrity of the click-to-install chain that MMPs use to assign credit.
How is SDK spoofing different from click injection or click flooding?
Click injection and click flooding manipulate the click side of the attribution chain. Click injection fires a fake click moments before a legitimate install completes, on-device, to steal last-click credit. Click flooding fires huge volumes of low-quality clicks hoping to win attribution by chance. SDK spoofing skips clicks entirely. It manufactures fake installs and in-app events server-side, bypassing the device altogether. SDK spoofing is more lucrative per fraudulent install, harder to detect from device telemetry, and requires reverse-engineering the MMP signature scheme.
What is hashed signature attribution?
Hashed signature attribution is the cryptographic mechanism MMPs use to bind a click to its subsequent install. When a click fires, the MMP server signs a payload (timestamp, click ID, network ID, advertiser ID, device parameters) with HMAC using a rotating salt only the MMP server knows. The SDK on the user's device reports the install with that signature attached. The MMP server recomputes the HMAC using the original inputs plus its current salt set, and rejects any payload whose signature does not validate. If the salt rotates and the attacker does not know the salt, forged signatures fail.
How often do MMPs rotate the signature salt?
Industry practice typically rotates the signing salt every 24 hours, with a short overlap window (often 60-120 minutes) where both the previous and current salt are valid to accommodate clicks that converted late. AppsFlyer's SRN protection and Adjust's signature-based fraud filters both use rotating-salt HMAC schemes. The rotation cadence is the primary defense against replay attacks beyond the validity window. If an attacker reverse-engineers the SDK and extracts a salt, that salt becomes worthless within one rotation period.
What is CTIT and why does it matter for SDK spoofing detection?
CTIT stands for Click-To-Install Time, the elapsed time between an ad click and the resulting install attribution. Real human installs follow a recognizable CTIT distribution: a sharp peak around 30-90 seconds (immediate downloads), a smooth tail out to several hours, and a long-tail of users who install days later. SDK-spoofed installs frequently show unnatural CTIT signatures: clustering at exactly 7-12 minutes (attackers waiting out a minimum window), unrealistically smooth distributions, or impossible patterns like installs occurring before the click timestamp. CTIT anomaly detection is one of the cheapest cross-checks an MMP runs.
Can MMPs catch SDK spoofing on their own?
MMPs catch a meaningful share of SDK spoofing through signature validation, salt rotation, and CTIT distribution analysis. Their detection focuses on signals visible inside their own attribution graph. What they systematically miss: cross-MMP collusion where the same install is claimed by multiple networks, sophisticated forgers who model the CTIT distribution before injecting payloads, and replay attacks executed inside the signature validity window. Server-side validation layers that correlate device fingerprint, network metadata, and back-end conversion signals catch a meaningful share of what single-MMP detection misses.
How big is the mobile attribution fraud problem?
AppsFlyer's State of Mobile App Fraud reports have consistently put mobile install fraud exposure in the tens of billions of dollars annually. Industry estimates have placed annual mobile-app advertiser losses around $35 billion at recent peaks. SDK spoofing specifically is harder to size because the fraud is invisible without active detection, but AppsFlyer and Adjust both report blocking double-digit percentages of attempted installs as fraudulent across high-risk networks. The exposure scales with payout-per-install: gaming, fintech, and gambling verticals see the highest spoofing rates.
What signals reveal SDK spoofing beyond MMP validation?
Five high-leverage cross-checks: (1) device fingerprint absence or impossibility (no IDFV, fresh IDFA on every install, simulator signatures); (2) IP / ASN mismatch (data-center ASN claiming a mobile install); (3) CTIT distribution anomalies (clustering, impossible deltas); (4) cross-MMP correlation (no other measurement system saw the click); (5) downstream conversion drop-off (installs that never open the app, never reach day-1 retention, never produce in-app events). No single signal is conclusive. Multi-signal scoring catches what individual checks miss.