Closed sushi2k closed 5 years ago
I think we can do:
As an app will not have access to this information (pid would need to be known to access /proc//self/maps where the frida-gadget can be found.
Has there been a change to the behaviour of Android in this regard? I can't immediately see something in https://developer.android.com/about/versions/pie/android-9.0-changes-all or https://developer.android.com/about/versions/oreo/android-8.0-changes and it works on Android 7.
Could you clarify the problem a little bit more?
Thanks @TheDauntless. If the app is running as gadget you can access /proc/process_id/maps.
public boolean checkMemory() {
boolean returnValue = false;
// get Process ID of the running app
int pid = android.os.Process.myPid();
// check if Frida is running as gadget as part of the app
try {
Process process = Runtime.getRuntime().exec("cat /proc/" +pid+ "/self/maps");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
Log.d("fridamemory PID: ", Integer.toString(pid));
Log.d("fridamemory: ", output.toString());
if(output.toString().contains("frida-gadget")) {
Log.d("fridaserver","Frida Server process found!" );
returnValue = true;
}
} catch (IOException e) {
} catch (InterruptedException e) {
}
return returnValue;
}
Can of course be bypassed by renaming the frida gadget. This works on Android 7, just tested it.
If you want to go through /proc/self/maps it should work according to the POC from Bernhard: https://github.com/b-mueller/frida-detection-demo/. But I cannot run the app properly, https://github.com/b-mueller/frida-detection-demo/issues/5
I think we can do:
- integrity protection verification (can help, as gadget needs to be in app)
- check if our app starts consuming more memory / less memory (kinda useless),
- We can create sockets to see if there are ports open in our own app ^^ and we assume there should not be... Maybe try that path? (could help)
- What we should investigate is what we can do with the NDK in terms of checking for certain symbols to be there (long run, could help)
Thanks Jeroen. I have now a very basic portscan within a demo app
public boolean PortScanFrida(String ipAddress) throws UnknownHostException {
final boolean[] fridaDetected = {false};
// Perform synchronous port scan
Log.d("portscan","PortScan started");
Log.d("portscan","PortScanning IP: " + ipAddress);
final long startTimeMillis = System.currentTimeMillis();
ArrayList<Integer> openPorts = PortScan.onAddress(ipAddress).setPort(27042).setMethodTCP().doScan();
Log.d("portscan","Open Ports: " + openPorts.size());
Log.d("portscan","Time taken: " + ((System.currentTimeMillis() - startTimeMillis)/1000.0f));
if (openPorts.size() > 0) {
fridaDetected[0] = true;
} else {
fridaDetected[0] = false;
}
return fridaDetected[0];
Can of course be easily bypassed by changing the port.
Bernhard has implemented the port scan more sophisticated with the NDK https://github.com/b-mueller/frida-detection-demo/
@sushi2k you wrote:
it seems /proc/self/maps should be removed as a method for frida detection (at least when running as gadget).
Thanks @TheDauntless. If the app is running as gadget you can access /proc/process_id/maps.
Either I'm still not getting it, or you agree that it shouldn't be removed and it's still a possible way to detect it?
Or is there actually a difference between self and PID ?
An App doesn't have access anymore to /proc/self/maps since Android 7.0, but it can still access /proc/
@sushi2k @TheDauntless do we have a conclusion here?
As Sven also demonstrated, an app can obtain its own PID by using android.os.Process.myPid()
, then use this to read 'cat /proc/' + pid + '/maps'
via Runtime.getRuntime().exec
. That way it's possible to detect Frida (as discussed, not very effective actually).
Tested on Android 8 rooted phone using Frida (to detect Frida, yes :P) and via CLI (Termux). Also tested simply via CLI (Termux) on Android 9 non-rooted (the app can retrieve its own PID and use it to read maps).
When I read the content of proc/pid/maps, it shows the path to frida agent which is possibly being used to check frida. Is there any way to bypass this? I have tried creating the fake maps file with below lines removed and pointing the function to fake file but it didn't work.
Just for future reference:
It seems that on Android 12 it is possible for an application to read /proc/self/maps
on a non-rooted device, unlike on Android 7.
I don't know however since when it is again possible.
Describe the issue it seems /proc/self/maps should be removed as a method for frida detection (at least when running as gadget). As an app will not have access to this information (pid would need to be known to access /proc//self/maps where the frida-gadget can be found.
Need to be investigated further if detection in memory can be executed on recent android versions and if frida can be found.
Optional: Testcase or section https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05j-Testing-Resiliency-Against-Reverse-Engineering.md#testing-the-detection-of-reverse-engineering-tools