Full technical analysis of an Android remote-access trojan distributed through an Instagram sponsored ad, disguised as "TikTok Pro".
Researched, documented and published by Furjack (Eliza Pears — @ArchLinuxAddict, FG_Teams).
TL;DR — A sponsored Instagram ad pushed a fake "TikTok Pro" APK. It is a commercial Android RAT kit called 杀猪刀 ("Pig-Killer Knife"), sold under the 朱雀 (Zhuque) brand on the vendor site
www.nnnva.top. Once installed with accessibility + "install unknown apps" permissions, it takes full remote control of the device: screen streaming (minicap/WebRTC), simulated taps, lock-screen PIN phishing, SMS/contacts/gallery theft, payment-input scraping, web injection, call/SMS interception, camera/mic access, and aggressive anti-uninstall self-defense. This repository documents the kit, its infrastructure, IOCs, detection rules and a removal runbook.
- The incident
- Why does Instagram allow this?
- Samples
- Kill chain
- Technical analysis
- Indicators of compromise
- Detection
- Removal runbook
- Reporting & takedown
- FAQ
- Repository layout
- Legal & ethics
A victim downloaded an APK named "TikTok Pro" after tapping an Instagram sponsored ad. The ad pointed
to an off-platform download page (not the Google Play Store), which delivered a 19 MB stager dropper
(TikTok.apk). The dropper installed the 31.5 MB payload APK (com.wave.zero.flow, label
"TikTok Pro", hidden launcher icon).
After the victim granted accessibility service access and "install unknown apps" (both heavily walked-through by in-app lure screens), the device was effectively remote-controlled: the operators could see the screen in real time, simulate taps, phish the lock-screen PIN, and silently read SMS, contacts, gallery, camera, microphone and files.
The victim recovered the phone over USB/ADB (see removal runbook) and preserved both
APKs (an MT Manager backup copy existed in /sdcard/mt2/apks/). This repository is the resulting analysis.
Do not install "TikTok Pro" — TikTok has no such official app. Any TikTok APK outside the Play Store claiming to be "Pro", "premium", "modded" or "unlocked" is malware.
- Sponsored ads are allowed to link off-platform. Once the user leaves Instagram, the install happens via a sideloaded APK — outside Play Store review and outside Google Play Protect's pre-install scanning.
- These campaigns frequently run through compromised or rented ad accounts, so they look legitimate until Meta's reactive enforcement catches up, after which the same crew spins up new accounts.
- Instagram/Meta policy prohibits malware distribution; enforcement is reactive and abuse-driven — which is why reporting the specific ad matters.
- How to report: tap the
⋯on the ad → Report ad → Scam/Fraud (also screenshot the ad, its advertiser name, and the landing page before reporting). Report the sideloaded app to Google Play Protect if prompted.
| Role | File | SHA-256 | Size |
|---|---|---|---|
| Payload | TikTok Pro_9.4.29.apk (com.wave.zero.flow) |
fd4ebf6049985fbc2590198d908265fe96337334958dd314b2b61220c71bf412 |
31,559,431 B |
| Dropper/stager | TikTok.apk |
3d73c7179b8debc48ea50c035e05db2fb0ca46a6b5f5a90618ed787c7475f19f |
19,076,509 B |
| Decrypted dex | d0.dex (main, XOR part 0) |
5f6a79079dc3cacf5b048c4e9e678e9fdb76a488bfca5639b6f9cdc617ecc262 |
11,236,592 B |
| Decrypted dex | d1.dex (part 1) |
262ce8c9b9e8269c715d6d9746f2286b5bb69cfa1147c79e9f3be39847d3d521 |
716,064 B |
| Decrypted dex | d2.dex (stub, part 2) |
45b6d94b81a498ff626152716c43fa3f37ae84cb347808954cdc11f2f6db5b7a |
140 B |
Both APKs are signed with the same v2/v3 certificate (no v1/JAR signature):
signing cert SHA-256: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc
Samples are not hosted in this repository. Search the hashes on VirusTotal / MalwareBazaar; if you obtain the payload APK,
tools/decrypt_payload.pyfully reproduces the decrypted dexes.
flowchart TD
A["Instagram sponsored ad<br/>'TikTok Pro' (off-platform link)"] --> B["Stager dropper<br/>TikTok.apk<br/>3d73c717…"]
B -->|downloads + installs| C["Payload APK<br/>com.wave.zero.flow v9.4.29<br/>fd4ebf60…"]
C --> D["libsa.so 'V8 shell'<br/>XOR-decrypts assets/wagueercfbvw<br/>→ 3 dex via DexClassLoader"]
C --> E["nmmp VM protection<br/>libnmmp.so / libnmmvm.so<br/>com.nmmedit.protect"]
C --> F["Go RAT engine<br/>libdxs.so"]
D --> G["App logic (decrypted dexes)<br/>credential phishing · payment scrape<br/>web injection · screen capture"]
F --> H["C2 + operator panel<br/>mzl88.yyydv.top<br/>31.58.136.66 (Latitude.sh, SG)"]
C --> I["Firebase FCM wake<br/>project xiongy-2ee6e"]
F --> J["WebRTC streaming<br/>turn:www.nnnva.top:3478"]
D --> K["Device control<br/>a11y automation · ADB wireless<br/>device-admin keepalive"]
| Property | Value |
|---|---|
| Package | com.wave.zero.flow |
| Label (icon) | TikTok Pro — no LAUNCHER activity (hidden icon; showAppIcon: false in config) |
| Version | 9.4.29 (versionCode 90429) |
| SDK | minSdk 24, targetSdk 34 |
| Signing | v2/v3 only, cert a40da80a…f5dc, identical to the dropper |
High-risk permissions include: READ_SMS, RECEIVE_SMS, SEND_SMS, READ_CONTACTS,
MANAGE_EXTERNAL_STORAGE, CAMERA, RECORD_AUDIO, ACCESS_FINE_LOCATION, READ_PHONE_STATE,
WRITE_SECURE_SETTINGS (declared), USE_FULL_SCREEN_INTENT, REQUEST_DELETE_PACKAGES,
QUERY_ALL_PACKAGES, boot/foreground-service permissions.
Key components (all visible in the manifest):
service.PlatformAssistDaemon— the accessibility service (registered withBIND_ACCESSIBILITY_SERVICE, foregroundServiceTypespecialUse|dataSync)activity.CredentialPromptActivity— exported, translucent, empty task affinity — lock-screen credential phishing windowinject.WebPayloadPage— WebView injection page (task affinitycom.wave.zero.flow.inject)activity.AccGuideActivity,activity.GrantRequestPage— onboarding lures to enable accessibility/other permissionskeepalive.*— self-defense persistence: QS tile (ACTIVE_TILE),MediaRouteProviderService,MediaBrowserService, app widget, exact alarms,RecoveryJobService,FcmWakeServicekeepalive.AdminEventReceiver— device-admin receiver handlingDEVICE_ADMIN_DISABLE_REQUESTED(intercepts/obstructs the standard "deactivate admin" flow)receiver.BootReceiver—BOOT_COMPLETED,LOCKED_BOOT_COMPLETED,USER_PRESENT,SCREEN_ON(direct-boot)receiver.PackageEventReceiver— watches package add/remove/change events (self-defense / monitoring)features.screen.ScreenCastService—mediaProjectionforeground service
The installed classes.dex is a tiny loader (5,676 bytes). Flow:
Applicationclasscom.wave.zero.flow.Sa(attachBaseContext) →System.loadLibrary("sa");nativeInit(context)JNI call.JNI_OnLoadinlibsa.so:- resolves its own class name from the Java stack trace (frames ending in
.Sa) andRegisterNatives-bindsnativeInit(no staticJava_*symbols), - spawns a watchdog thread that parses
/proc/self/statusfor theTracerPid:field and calls_exit(0)silently if a debugger is attached.
- resolves its own class name from the Java stack trace (frames ending in
nativeInit:- reads the static byte array
AKfrom the Java class (32-byte key), - reads the asset
assets/wagueercfbvw(name is randomized per build), plain[i] = asset[i] ^ AK[i % 32]— a repeating-key XOR (the whole cipher),- parses the container:
[u32 count][u32 size_0][dex_0][u32 size_1][dex_1]… - writes the dexes to
<cache>/.payload_%d_%u.dexand loads them withDexClassLoader, - reflectively swaps the running
Applicationwithcom.wave.zero.flow.Appfrom the decrypted dex (viaActivityThread.mBoundApplication/mInitialApplicationfield rewriting).
- reads the static byte array
XOR key (hex):
9c6f30e3af1b34904e8eb4d393216449d1ce2d2402fc513014b549bbcf27d621
The full decryptor is tools/decrypt_payload.py — verified against the
sha256 hashes above.
The real app logic is protected with the nmmp DEX-to-native virtual machine protector
(package com.nmmedit.protect.NativeUtil present in all app classes):
libnmmp.so(887 KB) — 476 distinctcom.wave.zero.flowclass references (the compiled method bodies)libnmmvm.so(302 KB) — the VM interpreterlibmedia_codec.so(4.2 MB) /libhidden_api_bypass.so— masqueraded support libraries- Example damage:
PlatformAssistDaemonalone has 266 native methods in the decompiled source
jadx decompilation recovers class/field structure and strings, but method bodies execute in the VM.
libdxs.so (8.6 MB) is a stripped, statically-linked Go binary (Go runtime/Prometheus metric strings
present) that acts as the device-side control plane:
- Localhost HTTP control API —
http://127.0.0.1:7400/api/status,/api/reloaddpm, plus action templates:accessibilityStateApp,stopAdminActive,resetrecovery,<x>proxy,Terminal— a local bridge the operators drive (often via ADB port-forwarding). - Screen streaming: minicap/minitouch tooling — fetches binaries from the C2
(
/s/bn/native,/s/bn/noarch/minicap.apk,/s/bn/<abi>/lib/android-<ver>/minicap.so) and drivesminicap/minitouchfor live screen + synthetic touch. - ADB wireless-debug takeover:
openWifiDebug,closeADBDebug,scanDebugPort,connectBridge,syncADBConfig,restartBridge,requestLocalAdbPair,localAdbShell— the RAT hunts for open debug ports, enables wireless debugging (with the accessibility service auto-tapping the "Allow" dialog), and can escalate to full ADB shell on the device. - Policy abuse:
forceSetDeviceOwner,writeSecureSettings/writeGlobalSettings/writeSystemSettings,applySecureSettings,enableAccessibility,resumeAccessibility,mainUninstallPolicy,mainActiveAdminPolicy,silenceNotification. - Sensors & files:
takePhoto,startGetevent,getScreenInfo,installRatHat,asyncDownload. - On-device artifacts in
/data/local/tmp/(acc_paused,adb_debug_port,app_setup_done_*,download_*) — the accessibility service writes there once the ADB bridge is up.
From the decrypted dexes (decomp_payload/ structure):
| Module | Classes | Purpose |
|---|---|---|
| Credential | features.credential.CredentialPromptActivity (+ obfuscated helpers) |
Fake system/lock-screen dialogs: "Privacy protection — enter your screen lock", "Verification required to complete system update" — PIN/pattern theft; 24 languages in assets/app_config.json |
| Payment | features.payment.InputExtractEngine, PaymentDataStore |
Scrapes card/banking input fields via accessibility |
| Injection | inject.WebPayloadPage |
Overlays/injects web content into banking apps (config pushed from panel) |
| Screen | features.screen.ScreenCastService, ScreenModule |
MediaProjection screen capture |
| Overlay | features.overlay.*, HiddenApiBridge |
Fake windows over apps, hidden-API bypass |
| DXS | features.dxs.DxsSetupFlow |
Sets up the Go engine / ADB bridge |
| Keepalive | keepalive.* (12 classes) |
Device-admin, QS tile, media services, widget, jobs, alarms, FCM — unkillable-by-design |
| Security | security.AssetKeyDeriver, CryptoAssetReader, Ed25519Auth, NativeAuth |
Decryption + Ed25519 device authentication to the C2 |
| Lures | activity.AccGuideActivity, GrantRequestPage, WakeScreenPage |
Accessibility/other-permission onboarding, screen wake for remote ops |
Anti-removal automation — assets/locateValues.json (Chinese-authored, 911 KB) contains UI
automation keyword tables used by the accessibility service to fight the user and the system:
UNINSTALL_KEYWORDS(134),FORCE_STOP_KEYWORDS(89),CLEAR_DATA_KEYWORDS(89),FACTORY_RESET_KEYWORDS(42),DEVELOPER_OPTIONS_KEYWORDS(88),ACCESSIBILITY_KEYWORDS(89),ALLOW_WIRELESS_DEBUG_KEYWORDS(153),PLAY_PROTECT_TURN_OFF_TEXTS(55),CANCEL_BUTTON_TEXTS(190),ALLOW_BUTTON_TEXTS(240) — in 111 languages- Per-OEM hooks: Xiaomi (
SECURITY_CENTER_PACKAGE,ADB_INPUT_ACTIVITY), vivo (VIVO_PIN_CONFIRM_CLASS), Oppo (PIN_KEY_CLASS), Samsung (PATTERN_STYLE), Huawei/Honor, realme, OnePlus, Motorola, Tecno, itel, Infinix — i.e. it can machine-enter confirm dialogs and PIN prompts on all major brands
Embedded config (assets/server_config.json, verbatim excerpts):
{
"serverUrl": "https://mzl88.yyydv.top",
"webUrl": "https://stripchat.com",
"deviceKeySalt": "0e39fa20882909055d6d2f20ee7d987c",
"permissionConfig": {
"enableWriteSettings": true, "enableAllFilesAccess": true, "enableDeviceAdmin": true,
"enablePlayProtect": true, "enableSms": true, "enableContacts": true, "enableStorage": true,
"enableGallery": true, "enableCamera": true, "enableMicrophone": true
},
"fcm": {
"projectId": "xiongy-2ee6e",
"applicationId": "1:663040677529:android:9ad1769c3b21b91dd2ca08",
"apiKey": "AIzaSyB4I9FjX_7ieQXN0SDM6RbO-vGTjw2LEdw",
"senderId": "663040677529"
},
"enableConfigMask": true, "showAppIcon": false, "ownerUsername": "admin"
}enablePlayProtect: true means "walk the victim through turning Play Protect off" — the kit ships a
PLAY_PROTECT_TURN_OFF_TEXTS keyword list and opens play.google.com/protect/home.
- Primary C2:
https://mzl88.yyydv.top→31.58.136.66(AS396356 Latitude.sh, Singapore; abuse contactreport@abuseradar.com). Fresh Let's Encrypt cert (CN=mzl88.yyydv.top, issued 2026-10-09). - The panel root serves a React/Vite admin UI titled 「杀猪刀 · 安卓远控系统」 ("Pig-Killer Knife · Android Remote Control System"). A source comment in the bundle reads: "[2026-09-23] version check … too many customers to tell each one to refresh" — this is a product sold to scammers, not a one-off.
- Vendor storefront:
https://www.nnnva.top— 「朱雀安卓设备管理」("Zhuque Android Device Management"; faviconzhuque.png, asset tagszd3). Default Telegram contacts for the kit:zhuqueykk_botandzhuquerz_bot(also used for the panel's login QR). - Panel API surface (from the admin bundle) includes:
/api/apk/build,/api/apk/auto-build/targets,/api/apk/build-history,/api/apk/delete— the panel auto-builds trojanized APKs for customers;/api/injection/*(per-country web-injection configs),/api/card-info,/api/bio-takeover,/api/black-apps+/api/device-black-apps/push(push a blacklist to devices to hide/kill security apps),/api/device/*,/api/file/*,/api/auth/*(multi-tenant). - WebRTC live streaming: the client uses the vendor's TURN server
turn:www.nnnva.top:3478(usernamertc, credentialQDItfa1mG4rYJ_9GokGGDA4v) for real-time victim screen viewing through NAT. - Device auth uses Ed25519 (
security.Ed25519Auth) plusdeviceKeySaltfor per-device keys.
Full machine-readable list: iocs.csv.
| Type | Value |
|---|---|
| SHA-256 (payload APK) | fd4ebf6049985fbc2590198d908265fe96337334958dd314b2b61220c71bf412 |
| MD5 (payload APK) | 376ab194b9d857f0e94fd0bc8bdfb9df |
| SHA-256 (dropper) | 3d73c7179b8debc48ea50c035e05db2fb0ca46a6b5f5a90618ed787c7475f19f |
| Signing cert SHA-256 | a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc |
| Decrypted dexes | 5f6a7907…, 262ce8c9…, 45b6d94b… |
| Type | Value |
|---|---|
| C2 domain | mzl88.yyydv.top |
| C2 IP | 31.58.136.66 (AS396356 Latitude.sh, SG) |
| Root domains | yyydv.top (Gname, 2025-11-10), www.nnnva.top (vendor, 2025-10-24) |
| TURN | turn:www.nnnva.top:3478 (rtc / QDItfa1mG4rYJ_9GokGGDA4v) |
| Firebase | project xiongy-2ee6e, sender 663040677529, app 1:663040677529:android:9ad1769c3b21b91dd2ca08 |
| Telegram | zhuqueykk_bot, zhuquerz_bot |
| Config salt | 0e39fa20882909055d6d2f20ee7d987c |
| XOR key | 9c6f30e3af1b34904e8eb4d393216449d1ce2d2402fc513014b549bbcf27d621 |
- Package
com.wave.zero.flow; accessibility servicecom.wave.zero.flow/com.wave.zero.flow.service.PlatformAssistDaemon - Device admin
com.wave.zero.flow/.keepalive.AdminEventReceiver <app_cache>/.payload_%d_%u.dex(decrypted dexes)/data/local/tmp/{acc_paused,adb_debug_port,app_setup_done_*,download_*}markers- Stray copies of
TikTok.apk/TikTok Pro_9.4.29.apk(e.g. Downloads,/sdcard/mt2/apks/— MT Manager backups)
yara/shazhudao_rat.yar contains three validated rules:
| Rule | Target | Notes |
|---|---|---|
APK_Shazhudao_RAT |
raw APK/ZIP | matches the ZIP entry names (assets/wagueercfbvw, assets/acc_guide*, lib/arm64-v8a/libsa.so, libdxs.so, …) — validated against the payload APK |
Shazhudao_RAT_Artifacts |
unpacked dex / .so / dumps | package + shell + engine strings — validated on d0.dex and libdxs.so |
Shazhudao_Panel |
operator panel HTML/JS | 杀猪刀/zhuque/bot names — validated on the live panel page and bundle |
yara -r yara/shazhudao_rat.yar /path/to/scan/adb shell pm list packages | grep -i "com.wave.zero.flow"
adb shell settings get secure enabled_accessibility_services
adb shell dumpsys device_policy | grep -i "com.wave.zero.flow"
adb shell ls /data/local/tmp/ 2>/dev/null | grep -E "acc_paused|adb_debug_port|app_setup_done"
adb shell dumpsys package com.wave.zero.flow | grep -E "versionName|firstInstallTime"- VirusTotal: search the hashes above; pivot on the signing certificate and package name.
- Look for the same infrastructure:
host:mzl88.yyydv.top, domain siblings underyyydv.top, and certs issued for*.yyydv.top. - The kit is modular: expect different C2 subdomains per campaign (
mzl*, other.topdomains), same panel look-and-feel, same Telegram bots.
Tested recovery path (Samsung device, Android 15):
- Kill the accessibility service first (this is what makes the phone unusable and fights back):
Settings → Accessibility → turn everything off for the app. You can also do it over ADB:
adb shell settings put secure enabled_accessibility_services ""andadb shell settings put secure accessibility_enabled 0.Note: if the malware is watching, it may relaunch its "enable accessibility" onboarding screen the moment it detects this. Keep ADB ready and
adb shell am force-stop com.wave.zero.flowafter each step. - Deactivate the device admin: Settings → Security and privacy → More security settings →
Device admin apps → the app (shown under its display name, e.g. "TikTok Pro") → Deactivate → confirm.
(On Samsung,
adb shell dpm remove-active-adminfails for non-test admins — the UI is the way.) - Uninstall the app:
adb uninstall com.wave.zero.flow(or Settings → Apps → Uninstall). If uninstall is blocked withDELETE_FAILED_DEVICE_POLICY_MANAGER, go back to step 2. - Delete the droppers from storage (
Download/TikTok.apk,/sdcard/mt2/apks/*). - Reboot, then verify: no accessibility service, no device admin, package gone,
/data/local/tmpclean. - Run a Play Protect scan and re-enable Play Protect if it was turned off.
- Assume credential theft: change important passwords (email, banking, social) from a different, trusted device; check bank transactions; if banking apps were installed, contact the bank.
- If anything suspicious persists, factory reset is the reliable fallback (after backing up only photos/documents — never app data or APKs).
| Target | Where |
|---|---|
| The Instagram ad | ⋯ on the ad → Report ad → Scam/Fraud (screenshot first) |
| C2 hosting | abuse@latitude.sh (verified via ARIN), cc report@abuseradar.com (reseller abuse desk) |
| Domains | complaint@gname.com (Gname registrar abuse, via whois) — yyydv.top / nnnva.top |
| Firebase | Firebase report spam/malware/phishing — project xiongy-2ee6e |
| Phishing/malware URL | Google Safe Browsing report — submit mzl88.yyydv.top |
| Telegram bots | @notoscam or in-app report for zhuqueykk_bot / zhuquerz_bot |
| Samples | Upload hashes to MalwareBazaar / VirusTotal to protect others |
| Your region | Local cybercrime unit (e.g. cybercrime.gov.in, ic3.gov, actionfraud.police.uk) |
Is "TikTok Pro" real? No. There is no official TikTok Pro APK. Anything "Pro/premium/modded TikTok" outside the Play Store is malware.
I only granted accessibility, is that enough for full control? Yes — accessibility alone allows reading the screen, simulating taps, stealing typed input (including PINs), and driving the whole "self-defense" machinery.
Why didn't Play Protect stop it? The chain is: ad → off-platform APK sideload. Play Protect can warn on install but is often bypassed via the "install unknown apps" flow and the kit's Play-Protect-off lure. The RAT also blocks/kills security apps from its own blacklist.
Can the operators still access the device after uninstall? No binary remains after the runbook above; but any credentials typed while infected must be treated as compromised, and any accounts/2FA on the device should be reviewed.
.
├── README.md # this report
├── iocs.csv # machine-readable IOC list
├── yara/
│ └── shazhudao_rat.yar # validated detection rules
├── tools/
│ └── decrypt_payload.py # XOR container decryptor (reproduces decrypted dexes)
├── evidence/ # panel HTML/bundle captures (IOC citations)
├── samples/ # NOT PUBLISHED (gitignored) — samples kept locally only
└── decomp_main/, decomp_payload/ # NOT PUBLISHED (gitignored) — jadx output
.gitignore deliberately excludes samples/, decrypted artifacts and decompiled trees so this repo
stays analysis-only (no live malware hosting).
This research was performed defensively, on an owned device, using standard OS-level tooling. The operator panel was observed via single read-only GET requests (it is the same infrastructure the victim's phone was already beaconing to). No exploitation, DoS or unauthorized access of adversarial systems was performed — don't do that; report to the abuse channels above instead. Do not redistribute the malware binaries. All IOCs describe infrastructure, not persons; do not use them to harass anyone.
Analysis: Furjack / Eliza Pears (@ArchLinuxAddict) — jadx 1.5.6, LLVM objdump, YARA 4.5.4, custom Python tooling.