Introduction: The Cat-and-Mouse Game with Frida
Frida is an indispensable toolkit for dynamic instrumentation, allowing security researchers and penetration testers to inject scripts into running processes on Android, iOS, Windows, macOS, and Linux. Its power lies in its ability to hook into functions, modify runtime behavior, and inspect application logic without source code. However, as Frida’s capabilities have grown, so have the countermeasures developed by app developers to detect and thwart its presence – a constant cat-and-mouse game. This article focuses on a critical, often overlooked phase: bypassing anti-Frida detections during the initial setup of frida-server on a rooted Android device. Many apps employ clever techniques to detect Frida even before it hooks into their process, primarily by scanning for known indicators of the frida-server itself.
Understanding Early-Stage Anti-Frida Detections
Before Frida can even attach to a target process, the frida-server binary must be running on the device. This initial setup phase is a prime target for detection. Apps don’t necessarily need to detect Frida’s hooks; they just need to know frida-server is active. Common detection vectors at this stage include:
- Process Name Enumeration: Checking for a process named
frida-server. - Port Scanning: Attempting to connect to Frida’s default listening port (27042).
- File System Checks: Looking for the
frida-serverbinary in common locations like/data/local/tmp/. - Memory Artifacts: Less common during setup but possible, checking for known strings or patterns associated with Frida in process memory.
Our goal is to make frida-server less conspicuous to these early-stage scans.
Prerequisites for Stealth Frida Setup
- Rooted Android Device: Essential for pushing and executing
frida-serverwith necessary permissions. - ADB (Android Debug Bridge): Configured on your workstation.
- Frida-tools: Installed on your workstation (
pip install frida-tools). - Correct
frida-serverBinary: Downloaded from Frida’s GitHub releases, matching your device’s architecture (e.g.,arm64,x86_64).
Standard (and Detectable) Frida Setup
Let’s first review the typical, easily detectable setup process:
# 1. Push frida-server to /data/local/tmp
adb push frida-server /data/local/tmp/
# 2. Grant execute permissions
adb shell "chmod 755 /data/local/tmp/frida-server"
# 3. Execute frida-server
adb shell "/data/local/tmp/frida-server"
In this scenario, frida-server runs with its default name, in a well-known location, and on its default port. This is easily caught by simple anti-Frida checks.
Stealth Techniques for Frida Setup
1. Renaming the frida-server Binary
This is the most straightforward and often highly effective technique. By simply changing the binary’s name, you bypass checks looking for the literal string "frida-server" in process lists.
2. Choosing an Obscure Directory
Instead of /data/local/tmp/, which is a common location for exploit payloads and debugging tools, push frida-server to a less obvious temporary or user-specific directory. Ensure it’s writable and executable.
3. Changing the Default Listening Port
Frida-server listens on port 27042 by default. Many anti-Frida mechanisms scan for this specific port. Changing it makes it harder to detect via port scanning.
4. Obfuscating the Execution Command
When running frida-server, the command line arguments can sometimes be inspected. While simply renaming helps, further obfuscation might be possible (e.g., via a wrapper script).
Step-by-Step Stealth Frida Setup
Step 1: Download and Rename frida-server
First, identify your device’s architecture. Connect your device and run:
adb shell getprop ro.product.cpu.abi
Let’s assume the output is arm64-v8a. Download the corresponding frida-server-<version>-android-arm64 file. Rename it to something innocuous like agentd, sysd, or a random string. Avoid names that might conflict with actual system daemons.
# Download frida-server-<VERSION>-android-arm64
mv frida-server-<VERSION>-android-arm64 agentd
Step 2: Push to a Less Obvious Location
Instead of /data/local/tmp/, let’s use /data/user/0/com.android.shell/cache/ (assuming the shell user has write access and it’s a temp directory) or another user-specific writable temporary location.
adb push agentd /data/user/0/com.android.shell/cache/
adb shell
su
cd /data/user/0/com.android.shell/cache/
Step 3: Set Permissions
Grant execute permissions to your renamed binary.
chmod 700 agentd
Step 4: Execute with a Custom Port and Disguised Command
Run agentd on a non-standard port, for example, 1337.
./agentd -l 0.0.0.0:1337 &
The & puts it in the background. You can exit the adb shell session, and it should continue running. If the app you are testing has very aggressive detection logic, you might even consider running this via a simple shell script or `nohup` to further detach it.
Step 5: Verify the Stealth Setup
From your workstation, you can now connect to Frida using the specified port.
# Forward the custom port
adb forward tcp:1337 tcp:1337
# List processes using the custom port
frida-ps -H 127.0.0.1:1337
# Or attach to an application
frida -H 127.0.0.1:1337 -n com.target.app
When inspecting the process list on the Android device (e.g., via ps -ef | grep agentd or top), you should see agentd running, not frida-server.
Example: Dummy Anti-Frida Check (Java Code Snippet)
Imagine an Android application performs a check like this:
public boolean isFridaDetected() {
try {
// Check for common frida-server process name
Process p = Runtime.getRuntime().exec("ps");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
if (s.contains("frida-server")) {
Log.w("AntiFrida", "Frida server process detected!");
return true;
}
}
// Check for default Frida port
Socket socket = new Socket();
socket.connect(new InetSocketAddress("127.0.0.1", 27042), 100);
socket.close();
Log.w("AntiFrida", "Frida default port detected!");
return true;
} catch (IOException e) {
// Port not open or process not found - good sign (for us)
} catch (Exception e) {
Log.e("AntiFrida", "Error during Frida detection: " + e.getMessage());
}
return false;
}
By renaming frida-server to agentd and changing the port from 27042 to 1337, our stealth setup would bypass both checks in this simplified example.
Advanced Considerations and Persistence
- Memory Scanning: More sophisticated anti-Frida solutions might scan process memory for known Frida strings or patterns. Bypassing this typically requires patching the
frida-serverbinary itself, which is a more advanced topic involving binary modification tools. - Frida Gadget: For some scenarios, embedding Frida Gadget directly into the target application might be an alternative to running
frida-server. However, this often requires re-packaging the APK and is more about post-setup evasion. - Magisk Module for Persistence: For long-term or automated testing, you could create a Magisk module to launch your renamed
frida-serveron boot, ensuring it runs with appropriate permissions and in a stealthy manner. - Custom Init Script: On some rooted devices, you can leverage
init.dscripts or similar boot-time execution mechanisms to launchfrida-serverwith custom parameters before the target application even starts.
Conclusion
The arms race between security tools and detection mechanisms is ongoing. By understanding how anti-Frida checks operate, especially during the initial setup phase, we can employ simple yet effective techniques to maintain stealth. Renaming the frida-server binary, using non-standard directories, and changing the default listening port are fundamental steps to bypass many common anti-Frida implementations. While advanced detection methods exist, these basic stealth techniques provide a solid foundation for most Android application penetration testing scenarios, allowing you to focus on the application’s logic rather than being blocked at the door.