The Free Movie App That Was Robbing You Blind
The App That Looked Too Good to Be True
The Free Movie App That Was Robbing You Blind
The App That Looked Too Good to Be True
I saw most of my friends watch pirated movies through this APK called as Netmirror. The app was called NetMirror. Clean icon, smooth UI, actually played content. On the surface, nothing obviously wrong.

But something felt off. A streaming app that’s not on the Play Store. A link shared without any developer information. No website, no company name, no privacy policy. Just an APK file and a promise.
So instead of installing it on a real phone, I threw it into a Kali Linux analysis environment and started pulling it apart.
What I found over the next few hours was not just adware. It was a carefully engineered piece of spyware with multiple layers of deception — one that was specifically designed to fool the very tools most people trust to keep them safe.
This is the full story of how we found it, what we found, and why it matters.
Setting Up: How We Analyzed This
Before getting into the findings, a quick note on methodology. Everything here was done using static analysis only — meaning we never ran the app on a real device. All work was done inside an isolated Kali Linux virtual machine.
Tools used:
apktool— to decompile the APK and extract the raw filesjadx— to convert the compiled Java bytecode back into readable source codegrep— to search through thousands of source files for specific patternsstrings— to extract readable text from compiled native libraries- Base64 decoder — to crack open the obfuscated C2 URLs
- VirusTotal / URLScan — to check domain reputation
If you want to follow along or try this yourself, everything here was done on free, open-source tools on a standard Kali install. No special equipment. No paid subscriptions.
Step 1: The Manifest — Where the First Red Flags Live
Every Android app comes with a file called AndroidManifest.xml. Think of it as the app's passport — it declares who the app is, what it's allowed to do, and how it interacts with the Android operating system. It's the first thing any malware analyst looks at.
For a movie streaming app, you’d expect to see permissions like INTERNET (to load videos) and maybe READ_EXTERNAL_STORAGE (to cache files). What you would not expect to see is this:

grep output from AndroidManifest.xml. Four permissions — three of which have no legitimate place in a streaming app.
Let’s break down why each of these is suspicious:
WRITE_SETTINGS is the biggest immediate red flag. This is a system-level permission that lets an app modify your phone’s global settings — things like screen timeout, brightness, and ringtone. A legitimate streaming app adjusts brightness within its own screen. It does not need to touch system settings. In the malware world, this permission is used for one main thing: keeping the screen active while running background tasks the user isn’t supposed to see. Like clicking invisible ads. Like sending your data out while you think the phone is idle.
ACCESS_WIFI_STATE lets the app see your network connection details. For a streaming app, this makes superficial sense — check if you’re on Wi-Fi before loading HD content. But paired with the other permissions, it’s also a network fingerprinting tool. Your Wi-Fi state, combined with your device ID and carrier info, helps build a persistent profile of who and where you are.
BIND_GET_INSTALL_REFERRER_SERVICE is the one most people miss. It lets the app know which link or advertisement led to its installation. In legitimate marketing, this is used for campaign tracking. In the malware ecosystem, it tells the attacker which fake ad or Telegram post was responsible for getting you to install the app — so they can pay whoever tricked you and run more of the same campaign.
And then there’s usesCleartextTraffic="true" buried in the application tag. This single line tells Android: "this app is allowed to send data over unencrypted HTTP." For any app that values user privacy, this would never be acceptable. It means everything this app transmits can be intercepted and read in plaintext by anyone on the same network.
First red flags confirmed. But this was just the beginning.
Step 2: The Architecture Twist That Fooled Every Antivirus
Here’s where things get interesting — and where we start to understand why this app was able to fool automated security tools.
When you decompile an Android APK, most analysts and most automated scanners look at the Java source code. That’s where Android apps traditionally store their logic. So we did the same — and found something immediately telling.
NetMirror is built on React Native, Facebook’s framework for building mobile apps using JavaScript. You can identify this from the package references in the Manifest: com.facebook.soloader, com.reactnativecommunity.webview, app.netmirror.netmirrornew.MainApplication.
This matters enormously for analysis. In a React Native app, the Java code is mostly just scaffolding — a shell that boots the app and connects it to the Android operating system. The actual application logic, the real “brain” of the app, lives in a single file:
assets/index.android.bundle
This file is the entire JavaScript application, compiled into Hermes bytecode — a binary format optimised for performance on mobile devices. It is not human-readable. It is not Java. And critically: most automated APK scanners do not inspect it.
When Hybrid Analysis scanned this APK and returned a “Safe” verdict, this is why. The scanner looked at the Java code, saw standard React Native libraries, and found nothing alarming. The malicious logic was sitting untouched in the binary bundle, completely invisible to a Java-focused scanner.
This was a deliberate architectural choice by whoever built this app. React Native was not chosen because it’s a good framework for streaming apps. It was chosen because it creates a blind spot in the security tooling that most people rely on.
To get past this, we had to extract strings directly from the binary bundle and filter through the noise manually. That’s where things got very interesting very quickly.
Step 3: The Emulator Check — It Knew We Were Watching
One of the first meaningful hits from our code search was inside RNDeviceModule.java — part of the RNDeviceInfo library bundled into the app. What we found was not device info collection. It was a comprehensive check to detect whether the app was being analyzed.

The app’s anti-analysis logic. Before doing anything suspicious, it checks whether it’s running in a research environment.
- Am I running on an emulator? (checks for
goldfish,ranchu— the kernel names used by Android's standard emulator) - Is this Genymotion? (
Build.MANUFACTURER.contains("Genymotion")) - Is this Nox Player? (
Build.BOARD.contains("nox"),Build.BOOTLOADER.contains("nox")) - Is this Droid4x? (
str2.contains("droid4x")) - Is this VirtualBox? (
str3.contains("vbox86")) - Is this BlueStacks? (
hasKeyboard("memuime")) - Is this a generic/debug build? (
Build.BRAND.startsWith("generic"))
If any of these checks return true, the malicious routines stay dormant. The app behaves like a perfectly normal streaming service. Users see movies. Sandboxes see nothing suspicious. Antivirus gives it a clean bill of health.
This is why the Hybrid Analysis “Safe” verdict is not just wrong — it’s predictably wrong. Automated sandboxes run in exactly the environments this code is designed to detect. The malware authors knew this. They built the evasion specifically to target the tools that security researchers rely on.
The fact that this code exists at all is itself damning. Ask yourself: why does a movie streaming app need to check if it’s running on Genymotion? Why does it care about VirtualBox? There is no legitimate answer to that question.
The Sandbox Problem
When we submitted this APK to Hybrid Analysis, it came back clean. Safe. No threats detected ( False Negitive ).
This is not a failure of the tool in isolation. It is a systematic problem that this specific malware was engineered to exploit.
Three things caused the false negative:
First, the emulator detection. Hybrid Analysis runs apps in a virtual environment. This app detects virtual environments and shuts down all malicious behavior when it finds one. The sandbox saw a polite streaming app because that’s all the app allowed it to see.
Second, the Hermes bundle blind spot. The scanner analyzed Java bytecode. The malicious logic was in binary JavaScript. Those are different things and many scanners don’t bridge that gap.
Third, the dormant payload design. Even if the sandbox had bypassed the emulator detection, the app likely waits hours or days after installation before activating. A standard 3-minute sandbox run would never see the behavior begin.
The takeaway is not that automated tools are useless. They catch a huge amount of malware quickly and cheaply. The takeaway is that sophisticated, targeted threats are specifically built to exploit the assumptions those tools make. Manual analysis exists for exactly this reason.
Step 4: The Hidden C2 — Decoded
The next major discovery came from the JavaScript bundle. After extracting strings from the binary file, we found a series of Base64-encoded strings that didn’t look like UI code or React Native internals. We decoded them.


The decoded URLs:
aHR0cHM6Ly9tb2JpZGV0ZWN0cy5saXZl→ **https://mobidetects.live**aHR0cHM6Ly9tb2JpZGV0ZWN0cy5zdG9yZQ==→ **https://mobidetects.store**aHR0cHM6Ly9tb2JpZGV0ZWN0cy5wcm8=→ **https://mobidetects.pro**aHR0cHM6Ly9tb2JpbGVkZXRlY3QuYXBw→ **https://mobidetect.app**aHR0cHM6Ly9tb2JpZGV0ZWN0LmFydA==→ **https://mobidetect.art**
Five domains. All registered on the same day in 2025 through NameCheap. All using Sedo domain parking as a cover — making them appear to be inactive, “for sale” domains to web reputation scanners.
Now here’s the important question: why would a legitimate app encode its server addresses in Base64?
It wouldn’t. There is no performance benefit. There is no technical reason. The only reason to encode your server URLs in Base64 inside a binary file is to hide them from security tools that scan for suspicious domains. This is not a gray area. This is deliberate concealment.
The name itself — MobiDetect — became the thread that connected everything. The same strings appeared not just in the JavaScript bundle but hardcoded inside libappmodules.so, the app's custom native C++ library. That means even if someone patched the JavaScript, the tracking module would keep running from the compiled native layer.
Step 5: The Permissions It Never Asked For (But Was Ready To Use)
Back in the JavaScript bundle, another grep sweep revealed something that should not be in any streaming app under any circumstances.

Three highly sensitive permissions found inside the app’s JavaScript bundle — none of which appear in the AndroidManifest.xml
READ_CALL_LOG. READ_SMS. CALL_PHONE.
These permissions were not declared in the AndroidManifest.xml. If they were, the app would never pass even the most basic Play Store review, and any security-conscious user would see them during installation. Instead, they’re sitting in the JavaScript bundle — ready to be requested dynamically at runtime, after the app has already been installed and is running.
This is the staged approach. The first version of the app profiles your device, establishes a connection to the C2 infrastructure, and determines whether your phone is “worth” deeper access. If it is, the hidden permission requests activate. You might see a pop-up asking for SMS access, framed as something necessary for “verification” or “account security.” By the time that happens, the app has already been on your device long enough to fingerprint you permanently.
Step 6: The Permission Handler — Ready to Escalate
The code to handle what happens after permissions are granted was also right there in the source.

Multiple implementations of onRequestPermissionsResult across different modules — the infrastructure for handling dynamically requested permissions.
onRequestPermissionsResult is the Android callback that fires when a user responds to a permission request — when they tap "Allow" or "Deny." Finding this across multiple modules in the app's code confirms that the permission request system is fully wired up and ready to handle responses. The app isn't just carrying dead code — it's built to receive and act on permission grants at runtime.
Combined with the presence of READ_SMS and READ_CALL_LOG in the bundle, this tells us the escalation path is complete: the app can request sensitive permissions at the right moment and immediately begin using them once granted.
Step 7: Putting It All Together — What This App Actually Does
By this point we had confirmed multiple independent behaviors across the manifest, the Java source, the JavaScript bundle, and the native libraries. Let’s put them together and look at the complete picture.
The domains, the native library strings, and the JavaScript bundle all share one naming pattern: “mobidetect.” Whether this represents a commercial tracking SDK, a custom-built framework, or part of a broader campaign is something that would require dynamic analysis and further threat intelligence research to confirm with certainty. What we can confirm with evidence is exactly what the code does — and the code tells a clear story.
Device Fingerprinting (Permanent Identity Theft) Using the RNDeviceInfo library, the app collects your IMEI, SIM serial number, Android ID, carrier information, battery level, charging status, and headphone connection state. This combination creates a permanent shadow profile of your device. Uninstalling the app doesn't erase this profile — if the same infrastructure gets another app onto your device, your phone is immediately recognized again. This kind of persistent hardware-level identifier data is the currency of the device fingerprinting industry.
Credential Scraping (WebView Interception) The app injects JavaScript into its built-in browser via evaluateJavascript, specifically executing window.getSelection().toString(). Any text you select inside the app's browser — a password, a private message, a credit card number — is programmatically captured and passed back to native code. On top of that, libappmodules.so contains native C++ hooks referencing RNCWebViewBasicAuthCredentialStruct, giving the app the ability to intercept usernames and passwords entered into any site using Basic Authentication inside the app's browser. This is in-app credential theft, not a theoretical risk.
Ad Fraud (Synthetic Clicks) The code contains MotionEvent.obtain and dispatchTouchEvent logic — the building blocks for fabricating touch events and dispatching them to UI elements programmatically. In practice this is the technical foundation for clicking invisible advertisements in a hidden WebView without any user interaction, generating fraudulent ad revenue for whoever controls the C2 infrastructure, at the direct cost of your battery life and mobile data.
Dropper (Second Stage Delivery) The string “Please visit our Website to Download New App” found in the bundle is not a leftover UI artifact. It is a social engineering trigger. When activated, it directs users toward downloading a secondary APK from an unverified external source — specifically the mobidetect.art domain identified in our C2 infrastructure analysis. This is the classic first-stage dropper pattern: get a semi-functional app onto the device, profile the victim, then use that foothold to deliver something far more capable.
Taken individually, any one of these behaviors could be argued away. Taken together — with the sandbox evasion, the Base64-encoded C2 domains, the anti-forensics manifest flags, and the native library confirmation — there is no innocent explanation for what this app was built to do.
MITRE ATT&CK Table

What This Means for Regular Users
If you have NetMirror installed right now:
- Uninstall it immediately
- Clear your browser history and app cache from your phone’s settings
- Revoke any permissions the app was granted (go to Settings → Apps → NetMirror → Permissions)
For your accounts:
- Change your Google account password
- Change passwords for any streaming service (Netflix, Prime, etc.) you opened inside the app’s built-in browser
- If you typed anything financial inside the app, change those passwords too and check for unusual activity
For your network:
- If you’re on a home router you control, block these domains: mobidetects.live, mobidetect.art, mobidetects.store
- On Android you can use a DNS blocker app like Blokada or NextDNS to block these without needing router access
Going forward:
- Only install apps from the Google Play Store
- If someone shares an APK link on Telegram or WhatsApp, don’t install it regardless of what it promises
- Before installing any sideloaded APK, run it through VirusTotal first — upload the file and check the results before opening it
Thank You
Vishwas S Adhikari Espress0
메타데이터
- post_id
- eeefe9c5e65c
- slug
- the-free-movie-app-that-was-robbing-you-blind-eeefe9c5e65c
- url
- https://medium.com/@Espress0/the-free-movie-app-that-was-robbing-you-blind-eeefe9c5e65c
- canonical_url
- https://medium.com/@Espress0/the-free-movie-app-that-was-robbing-you-blind-eeefe9c5e65c
- author_url
- https://medium.com/@Espress0
- status
- ok
- fetched_at
- 2026-06-24 11:06:28