McAfee’s mobile research team has uncovered a large-scale Android malware campaign we’re tracking as Operation NoVoice.
The campaign was distributed through more than 50 apps previously available on Google Play, disguised as everyday tools like cleaners, games, and photo utilities. Together, the apps were downloaded more than 2.3 million times, though it’s unclear how many devices may have been impacted.
If the attack succeeds, the malware can gain deep control of a device, allowing attackers to inject malicious code into apps as they are opened and access sensitive data.
However, the most serious impact depends on the device.
On older or unpatched Android devices, the malware can install a highly persistent form of infection that may survive a standard factory reset. Newer Android devices with up-to-date security protections are not vulnerable to the root exploit observed in this campaign, though they may still be exposed to other types of malicious activity from these apps.
In other words, on vulnerable devices, the malware can behave like a kind of digital “zombie,” continuing to operate in the background even after a reset.
Operation NoVoice is what security experts call a rootkit malware attack.
A rootkit is a type of malware designed to gain deep, privileged control of a device while hiding its presence from the user and the operating system’s normal security tools.
Breaking the term down:
“Root” refers to the highest level of access on a system (administrator-level control).
“Kit” refers to a collection of tools used by an attacker to maintain that control.
Put simply, a rootkit allows attackers to operate underneath the normal apps and security protections on a phone, giving them powerful control while staying difficult to detect.
In the case of Operation NoVoice, the attack unfolds in several steps.
1) A normal-looking app starts the attack
The campaign began with apps that appeared harmless on the Google Play Store. These apps advertised themselves as tools like phone cleaners, puzzle games, or gallery utilities.
When a user downloaded and opened one of these apps, it appeared to work normally. There are no obvious signs to the user that anything is wrong.
2) The malware quietly checks the device
Behind the scenes, the app contacts a remote server controlled by the attackers.
The server collects information about the device, things like its hardware, operating system version, and security patch level. Based on that information, the attackers send back custom exploit code designed for that specific device.
3) The attack gains deep system access
If the exploit succeeds, the malware gains root-level access to the device.
At that point, the attackers can install additional malicious components and modify parts of the Android operating system itself.
4) Every app on the phone can be affected
Once the rootkit is installed, it modifies a core Android system library that every app relies on.
This allows attacker-controlled code to run inside any app the user opens.
That means the attackers could potentially access data from messaging apps, financial apps, or social media apps without the user noticing.
5) The malware can remain even after a reset
Operation NoVoice also includes persistence mechanisms designed to keep the malware active.
In some cases, the infection could survive a standard factory reset, because the malicious components modify parts of the system software that resets typically do not replace.
Fully removing the infection may require reinstalling the device’s firmware, something most users cannot easily do themselves.
*To be clear, these apps have been removed from Google Play and are no longer available for download.
Why The Name “Operation NoVoice”
The name Operation NoVoice comes from a hidden component inside the malware itself.
Researchers discovered a resource labeled “novioce” embedded in one of the attack’s later stages. The file contains a silent audio track that plays at zero volume.
This may seem strange, but it serves a purpose.
By continuously playing silent audio in the background, the malware can keep a foreground service running without drawing attention. This allows the malicious code to remain active while appearing harmless to the operating system.
The researchers believe the name “novioce” is likely a misspelling of “no voice,” referring to the silent audio trick used to keep the malware running.
How To Stay Safe from Malware Disguised as Apps
Operation NoVoice highlights an important reality: even apps that appear legitimate can sometimes hide malicious behavior.
Fortunately, there are several steps users can take to reduce their risk.
Be cautious with unfamiliar apps
Even if an app appears on the Google Play Store, it’s still important to review:
the developer’s name
the number of downloads
recent user reviews (check for negative reviews)
Apps with very few reviews, vague descriptions, or suspicious developer accounts can sometimes be part of malware campaigns. And exercise even greater caution with apps promoted through advertisements or that create a a sense of urgency.
Keep your phone updated
Many attacks rely on exploiting known vulnerabilities in older versions of Android.
Installing system updates and security patches helps reduce the chance that these exploits will work.
Remove apps you don’t recognize
If you notice apps on your device that you don’t remember installing, review them carefully and remove anything suspicious.
Keeping your phone’s app list clean reduces the potential attack surface.
Use mobile security protection
Mobile security software can help detect suspicious behavior and block known malware.
What Operation NoVoice Tells Us About the Future of Mobile Threats
Operation NoVoice highlights how mobile malware is evolving. Instead of obvious malicious apps, attackers are increasingly hiding their operations inside ordinary-looking tools distributed through legitimate app stores.
What makes this campaign particularly concerning isn’t just the number of downloads or the technical complexity. It’s the way the malware combines several advanced techniques, device-specific exploits, modular plugins, and deep system persistence, into a single attack chain.
That approach allows attackers to quietly turn an everyday app download into long-term control of a device.
That’s why keeping devices updated, reviewing apps carefully, and using mobile security protection are becoming increasingly important. As Operation NoVoice shows, today’s malware isn’t just trying to get onto devices; it’s trying to stay there.
McAfee’s mobile research team identified and investigated an Android rootkit campaign tracked as Operation Novoice. The malware described in this blog relies on vulnerabilities Android made patches available for in 2016 – 2021. All Android devices with a security patch level of 2021-05-01 or higher are not susceptible to the exploits that we were able to obtain from the command-and-control server. However patched devices that downloaded these apps could have been exposed to unknown potential payloads outside of what we discovered. The attack begins with apps that were previously available on Google Play that appear to be simple tools such as cleaners, games, or gallery utilities. When a user downloaded and opened one of these apps, it appeared to behave as advertised, giving no obvious signs of malicious activity.
In the background, however, the app contacts a remote server, profiles the device, and downloads root exploits tailored to that device’s specific hardware and software. If the exploits succeed, the malware gains full control of the device. From that moment onward, every app that the user opens are injected with attacker‑controlled code.
This allows the operators to access any app data and exfiltrate it to their servers. One of the targeted apps is WhatsApp. We recovered a payload designed to execute when WhatsApp launches, gather all necessary data to clone the session, and send it to the attacker’s infrastructure.
On older, unsupported devices (Android 7 and lower) that no longer receive Android security updates as of September 2021, this rootkit is highly persistent; a standard factory reset will not remove it, and only reflashing the device with a clean firmware will fully restore the device.
In total, we identified more than 50 of these malicious apps on Google Play, with at least 2.3 million downloads.
McAfee identified the malicious apps, conducted the technical analysis, and reported its findings to Google through responsible disclosure channels. Following McAfee’s report, Google removed the identified apps from Google Play and banned the associated developer accounts. McAfee is a member of the App Defense Alliance, which supports collaboration across the mobile ecosystem to improve user protection. McAfee Mobile Security detects this malware as a High-Risk Threat. For more information, and to get fully protected, visit McAfee Mobile Security.
Background And Key Findings
Android malware has been moving toward modular frameworks that update themselves remotely and adapt to each device. Campaigns like Triada and Keenadu have shown that replacing system libraries gives attackers persistence to survive factory resets. BADBOX has shown that backdoors pre-installed through the supply chain can reach millions of devices. Recent research has confirmed links between several of these families, suggesting shared tooling rather than isolated efforts.
NoVoice fits both trends but does not rely on supply chain access. It reaches devices through Google Play and achieves the same level of persistence through exploitation. McAfee’s investigation revealed the following key findings:
All carrier apps were distributed through Google Play. No sideloading required, no user interaction beyond opening the app.
C2 infrastructure remains active at the time of publication.
The C2 server profiles each device and delivers root exploits matched to its hardware and software version.
The rootkit overwrites a core system library, causing every app on the device to run attacker code at launch.
The infection survives factory reset and can only be removed by reflashing the firmware.
The chain is fully plugin-based. Operators can push any payload to any app on the device at runtime.
The only task we recovered clones WhatsApp sessions, but the framework is designed to accept any objective.
Naming
The name comes from R.raw.novioce, a silent audio resource embedded in one of the later-stage payloads. It plays at zero volume to keep a foreground service alive, abusing Android’s media playback exemption. We believe it is a deliberate misspelling of “no voice.”
Distribution Method
All carrier apps were distributed through Google Play and request no unusual permissions. Their manifests include the same SDKs any legitimate app would (Firebase, Google Analytics, Facebook SDK, AndroidX). The malicious components are registered under tampered com.facebook.utils, blending in with the real Facebook SDK classes the apps already include.
Figure 1: One of the carrier apps on Google Play
The initial payload is embedded in the app’s asset directory as a polyglot image. This means the file displays and renders a normal image, but a deeper inspection reveals that the encrypted malicious payload is appended after the PNG IEND marker. Since that marker signals to image viewers that the image data ends there, the appended payload remains hidden during normal viewing.
Geographical Prevalence
The geographical prevalence map shows the highest infection rates in Nigeria, Ethiopia, Algeria, India, and Kenya, regions where budget devices and older Android versions that no longer receive security updates are common.
Figure 2: Affected users around the world
Malware Analysis
The following breakdown walks through each stage of the chain in order, from the moment a user opens the app to the moment stolen data leaves the device. No single file contains the full chain. Each stage decrypts and loads the next, most are delivered from the server at runtime.
Figure 3. The NoVoice rootkit payloads
Stage 1: The Delivery
The moment the app opens, code injected into the legitimate Facebook SDK initialization path runs automatically. No user interaction is needed. It first checks whether the device has already been processed and, in most samples, whether it is running Android 12L or below. A subset of the carrier apps skips the version check entirely. If either check fails, it stops and logs a message disguised as a Facebook SDK error: “FacebookSdk: Failed in initStore.”
If the device was already processed, the code cleans up files assumed to be left behind by previous runs, including paths that do not belong to any standard Android component. None of these are visible to the user.
If the checks pass, the app reads a polyglot image from its own assets’ directory, extracts the encrypted payload (enc.apk) hidden after the image data, decrypts it to produce h.apk, and loads it into memory. It then deletes all intermediate files, temporary directories.
Figure 4: Normal looking image with malicious payloadFigure 5: The malicious payload begins after the IEND marker, starting with the magic value CAFEBABE
Stage 2: The Gatekeeper
The decrypted payload (h.apk) loads a native library (libkwc.so) that controls the rest of this stage. It first verifies it is running inside the intended carrier app by checking the package name and signing certificate against hardcoded values. It also checks whether the app is running in a debug environment.
libkwc.so contains two encrypted embedded payloads. The first (sec.jar) is a gate designed to detect analysis environments. It runs 15 checks, including emulator detection, root indicators, debuggers, VPN and proxy connections, Xposed hooks, and GPS geofencing. If any check fails, the chain stops silently. The geofence compares the device’s location against bounding boxes for Beijing and Shenzhen hardcoded in the native library and excludes devices confirmed to be inside them. If the app does not have location permission, it cannot determine the device’s position and defaults to letting the chain continue. Two brands get special treatment: on Gionee devices, all checks except the geofence are skipped; on Meizu devices, the chain follows a separate code path entirely. Gionee devices have a documented history of shipping with pre-installed malware through supply chain compromise.
Only if all checks in sec.jar pass does libkwc.so decrypt and load the second payload (hex.jar), which begins contacting the C2 server. If the gate fails, it deletes the working directory and stops.
Figure 6: 15 validation checks before proceeding to the next stage
Stage 3: The Plugin
Once the gate passes, hex.jar sets up a plugin framework built on an internal codebase the authors refer to as “kuwo” in their package names. It checks in with a C2 server every 60 seconds. Updates are delivered the same way as the initial payload: as image files with encrypted data hidden after the image content. The server returns download URLs in a response field named warningIcon, disguising plugin downloads as icon fetches. A log-deletion routine runs alongside the framework to remove forensic traces from the device.
The first plugin delivered (rt) acts as an orchestrator. It manages sub-plugins and handles C2 communication. It checks in with the server, sending over 30 device identifiers including hardware model, kernel version, installed packages, and whether the device has already been rooted. The campaign’s name comes from this plugin: it embeds a silent audio resource named R.raw. novioce.
The checkin tells the server two things: who this device is and whether it has already been rooted. If it has not, rt_plugin downloads security.jar, moving the chain into root exploitation.
Figure 7: MediaPlayer initialized to load the embedded NoVoice audio
Stage 4: The Exploit
security.jar first checks whether the device is already rooted. If it has been, it stops. For unrooted devices, it sends the device’s chipset, kernel version, security patch date, and other identifiers to the C2. The server responds with a list of exploit binaries matched to that specific device.
Before running any exploit, the rootkit installer (CsKaitno.d) is decrypted from an embedded resource and written to disk. The rootkit is already in place before any exploit runs.
The exploits are downloaded one at a time from the C2’s CDN, each encrypted and verified before execution. We recovered 22 exploits in total. Our deep analysis of one revealed a three-stage kernel attack: an IPv6 use-after-free for kernel read, a Mali GPU driver vulnerability for kernel read/write, and finally credential patching and SELinux disablement.
The expected end result is the same across all exploits: a root shell with SELinux disabled. From that shell, the exploit loads CsKaitno.d. This is where exploitation ends and persistence begins.
Figure 8: SELinux enforcement disabled as part of the exploit chain
Stage 5: The Rootkit
CsKaitno.d carries four encrypted payloads: library hooks for ARM32 and ARM64 (asbymol and bdlomsd), a bytecode patcher (jkpatch), and a persistence daemon (watch_dog). It first removes files associated with possible competing rootkits, then decrypts and writes its own payloads to disk.
The installer backs up the original libandroid_runtime.so and replaces it with a hook binary matched to the device’s architecture. It also replaces libmedia_jni.so. The replacements are not copies of the original libraries. They are wrappers that intercept the system’s own functions. When any hooked function runs, it redirects to attacker code.
Figure 9: Rootkit copying and preparing modified system libraries before remounting the filesystem as writable
After replacing the libraries, jkpatch modifies pre-compiled framework bytecode on disk. This is a second layer of persistence: even if someone restores the original library, the framework’s own compiled code still contains the injected redirections
Stage 6: The Watchdog
To survive reboots, the installer replaces the system crash handler with a rootkit launcher, installs recovery scripts, and stores a fallback copy of the exploitation stage on the system partition. If any component is removed, the rootkit can reinstall itself.
It then deploys a watchdog daemon (watch_dog) that checks the installation every 60 seconds. If anything is missing, it reinstalls it. If that fails repeatedly, it forces a reboot, bringing the device back up with the rootkit intact.
After cleaning up all staging files, the installer marks the device as compromised. On the next boot, the system’s process launcher (zygote) loads the replaced library, and every app it starts inherits the attacker’s code.
Figure 10: Watchdog payload decrypted, written to disk, permissioned, and launched with a 60‑second restart interval
Stage 7: The Injection
On the next boot, every app on the device loads the replaced system library. The injected code decides what to do based on which app it is running inside. Two payloads activate depending on the app. The malware authors named them BufferA and BufferB in their own code. Both are embedded as fragments inside the replaced libandroid_runtime.so from Stage 5, assembled in memory at runtime, and deleted from disk immediately after loading, leaving no files behind. BufferA runs inside the system’s package installer and can silently install or uninstall apps. BufferB runs inside any app with internet access.
BufferB is the campaign’s primary post-exploitation tool. It operates two independent C2 channels with separate encryption keys and beacon intervals. Both channels send device fingerprints to the C2 and receive task instructions in return.
If all primary domains fail and three or more days pass without contact, a fallback routine activates between 1 and 4 AM, reaching out to api[.]googlserves[.]com for a fresh domain list. Because BufferB runs inside any app with internet access, it can be active in dozens of apps simultaneously on a single device.
Figure 11: Injection logic selecting BufferA for the package installer and BufferB for all other apps
Stage 8: The Theft
The only task payload we recovered is PtfLibc, delivered to BufferB from Alibaba Cloud OSS. Its target is WhatsApp.
PtfLibc copies WhatsApp’s encryption database, extracts the device’s Signal protocol identity keys and registration ID, and pulls the most recent signed prekey. It also reads 12 keys from WhatsApp’s local storage, including the phone number, push name, country code, and Google Drive backup account. For the client keypair, it tries multiple decryption methods depending on how the device stores the key.
It sends the stolen data to api[.]googlserves[.]com through multiple layers of encryption and deletes the temporary database copy when done.
With these keys and session data, an attacker can clone the victim’s WhatsApp session onto another device.
Figure 12: Code accessing and copying WhatsApp’s encrypted Signal protocol databases for exfiltration
Infrastructure
The campaign spreads its C2 communication across multiple domains, each serving a different function.
fcm[.]androidlogs[.]com handles initial device enrollment. Once the plugin framework activates, stat[.]upload-logs[.]com takes over as the primary C2 for plugin delivery, device checkin, exploit distribution, and result reporting. config[.]updatesdk[.]com serves as its fallback. Exploit binaries are hosted separately on download[.]androidlogs[.]com, with an S3-accelerated endpoint (logserves[.]s3-accelerate[.]amazonaws[.]com) as the primary CDN. This endpoint returned 403 errors during our analysis.
Task payloads for BufferB are hosted on Alibaba Cloud OSS (prod-log-oss-01[.]oss-ap-southeast-1[.]aliyuncs[.]com). PtfLibc beacons to api[.]googlserves[.]com, a domain designed to look like Google service traffic at a glance.
The domain separation is deliberate. Taking down one domain does not affect the others. The C2 can update BufferB’s domain lists at runtime, and a fallback routine fetches fresh domains from hardcoded backup endpoints if all configured domains go silent for three or more days.
Recommendations
Because the rootkit writes to the system partition, a factory reset does not remove it. A reset wipes user data but leaves system files intact. Compromised devices require a full firmware reflash to return to a clean state. Blocking the C2 domains and beacon patterns listed in this report at the network level can disrupt the chain at multiple stages.
Attribution
Several indicators link NoVoice to the Android.Triada family. The property (os.config.ppgl.status)NoVoice sets to mark a device as compromised is a known indicator of compromise for Android.Triada.231, a variant that uses the same property to track installation state. Both NoVoice and Triada.231 persist by replacing libandroid_runtime.so and hooking system functions so that every app runs attacker code at launch. Whether NoVoice is a direct evolution of Triada.231, a fork of its codebase, or a separate group reusing proven techniques, the shared approach suggests access to a common toolchain.
Conclusion
What makes NoVoice dangerous is not any single technique. It is the engineering effort behind the full chain: a self-healing pipeline that goes from a Play Store install to code execution inside every app on the device, survives factory reset, and monitors its own installation. The operators built a delivery system, an infrastructure.
We recovered one task. The framework is designed to accept any number of them, for any app, at any time. The C2 infrastructure remains active. We do not know what other objectives have been deployed before, during, or after our analysis. The WhatsApp session theft we observed may be the least of it.
The rootkit’s persistence model, overwriting a system library inherited by every process, patching pre-compiled framework bytecode, and monitoring its own installation with a watchdog, makes remediation difficult.
This research underscores McAfee’s ongoing role in identifying advanced mobile threats and working with platform partners to protect users before large‑scale harm occurs.