Mobile
Dynamic analysis (Frida) and emulator protection: what RASP is
Frida can change an app's functions while it runs. Security reviews rate this as high risk on both Android and iOS. What RASP is and how to implement it.
· 7 min read

In the review of our own app, one finding appeared twice: on both Android and iOS, "no protection against dynamic analysis tools", high severity both times. On top of that, Android had "emulator detection not implemented" (medium severity). These findings are connected and are closed with one approach — RASP. In this article we look at what Frida is, what a reviewer does with it, and how an app can protect itself.
Static and dynamic analysis
A reviewer studies an app in two ways:
- Static analysis — the APK or IPA is unpacked and the code, resources and configuration are read without running anything. Obfuscation is the counter to this.
- Dynamic analysis — the app is run and observed at runtime: which functions are called, which values are returned, what is in memory.
The main tool for dynamic analysis is Frida. It injects its own code into the app process and can hook any function, reading or changing its inputs and outputs.
What Frida can do
Practical examples — exactly what a reviewer tests:
- Disable root detection — make
isRooted()always returnfalse. - Bypass SSL pinning — make the certificate check always report success, exposing the traffic.
- Change business logic — for example, skip a check inside the app.
- Read data from memory — see plain data before encryption or after decryption.
That is why protection against dynamic analysis protects every other protection. Root detection or pinning that a hook can switch off is not enough for a review.
This falls under the RESILIENCE group of MASVS and category M7 (Insufficient Binary Protections) of the OWASP Mobile Top 10 2024.
Why emulators are a separate issue
Analysing an app on an emulator is much more convenient: snapshots, network control, root access and Frida are all easy. Emulators also let the app be launched many times automatically, which suits fake accounts and automated attacks. So reviews expect a release app to detect emulators.
What RASP is
RASP (Runtime Application Self-Protection) is a protection layer built into the app that watches its environment at runtime. It usually detects:
- root and jailbreak;
- emulators and simulators;
- hooking tools (Frida, Xposed, Substrate and similar);
- an attached debugger;
- broken app integrity (a rebuilt APK or IPA, or one signed with a different signature);
- installation from a source other than the official store.
When a threat is detected, RASP signals the app, and the app responds according to its policy: blocks, disables critical features or notifies the server.
How we implemented it
Our Flutter app uses the freeRASP library. In outline (the exact API may differ between library versions, check the official documentation):
final config = TalsecConfig(
androidConfig: AndroidConfig(
packageName: 'uz.example.app',
signingCertHashes: ['<release signing certificate hash>'],
),
iosConfig: IOSConfig(
bundleIds: ['uz.example.app'],
teamId: '<TEAM_ID>',
),
watcherMail: 'security@example.uz',
isProd: true,
);
final callback = ThreatCallback(
onHooks: () => showThreatScreen(),
onPrivilegedAccess: () => showThreatScreen(),
onSimulator: () => showThreatScreen(),
onDebug: () => showThreatScreen(),
onAppIntegrity: () => showThreatScreen(),
);
Talsec.instance.attachListener(callback);
await Talsec.instance.start(config);
What we paid attention to:
- The signature hash comes from the release certificate. The integrity check depends on it: if the APK is signed with a different key,
onAppIntegrityfires. If you use Google Play App Signing, use the hash of the app signing key from Play Console, not the upload key. - The blocking screen is calm and clear. It tells the user that the app cannot run in an insecure environment and what they can do.
isProdis enabled only in the release build. Development needs emulators and debuggers.- The check starts before login and continues at runtime.
RASP does not work alone
RASP is strong, but a specialist with enough time and knowledge can bypass it too. The goal is to raise the cost of an attack and meet the review's requirements. So it is combined with other layers:
- Obfuscation. R8 minify for Android, and for the Dart code:
flutter build apk --release --obfuscate --split-debug-info=build/symbols
Keep the split-debug-info folder — without it you cannot read crash reports.
- Fewer plain strings in the code. API endpoints and other important values should not sit in the code as plain strings, or they are easy to find with the
stringscommand. - Server-side checks. Important decisions (payments, permissions) should be made only on the server. Any check in the app is a supporting layer, not the last line of defence.
Test it
- Start
frida-serveron a rooted device and try to attach to the app — the app should detect it. - Run the release build on an Android emulator and an iOS simulator.
- Unpack the APK with
apktool, rebuild it and sign it with a different key — the app should notice the broken integrity. - Try attaching a debugger.
- Confirm there are no false positives on a normal device.
Conclusion
Protection against dynamic analysis is one of the most common high-severity findings in mobile reviews, because it is rarely planned in a normal development process. RASP, obfuscation and server-side checks together close this finding and make the app's other protections reliable.
If you want to know how your app responds to Frida and emulators, request a security scan. The Claude AI agent and our specialist will check the app and help you prepare it for the review.


