Skip to content

Commit

Permalink
implementing sync interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
iGio90 committed Jan 14, 2020
1 parent 3b61d6c commit 3d844f2
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 19 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,33 @@ and from your agent
Java.send({'pid': Process.id});
```

#### Implementing sync interfaces

this allows to play with target objects in runtime

```java
public class Interfaces {
static final class ActivityInterface implements FridaInterface {
@Override
public Object call(Object[] args) {
Log.e("FridaAndroidInject", Arrays.toString(args));
return null;
}
}
}
```
```java
// register a custom interface
fridaAgent.registerInterface("activityInterface", Interfaces.ActivityInterface.class);
```

and from your agent

```javascript
var app = Java.use("android.app.Activity");
app.onResume.overloads[0].implementation = function() {
this.onResume.apply(this, arguments);
Java.activityInterface(Java.cast(this, app), "otherArg1", "otherArg2");
};
```
The example apk [here](https://github.com/igio90/FridaAndroidInjector/tree/master/example.apk) is built and ready to try. You will see it works! (only arm64).
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;

public class FridaAgent {

Expand All @@ -33,20 +35,60 @@ public class FridaAgent {
"}" +
"\n";

private final File mWrappedAgent;
static final String sRegisterClassLoaderAgent = "" +
"Java.performNow(function() {" +
" var app = Java.use('android.app.ActivityThread').currentApplication();" +
" var context = app.getApplicationContext();" +
" var pm = context.getPackageManager();" +
" var ai = pm.getApplicationInfo(context.getPackageName(), 0);" +
" var apkPath = ai.publicSourceDir.value;" +
" apkPath = apkPath.substring(0, apkPath.lastIndexOf('/')) + '/xd.apk';" +
" var cl = Java.use('dalvik.system.DexClassLoader').$new(" +
" apkPath, context.getCacheDir().getAbsolutePath(), null," +
" context.getClass().getClassLoader());" +
" Java.classFactory['xd_loader'] = cl;" +
"});" +
"\n";

private final Context mContext;
private final String mWrappedAgent;
private final LinkedHashMap<String, Class<? extends FridaInterface>> mInterfaces =
new LinkedHashMap<>();

private FridaAgent(Builder builder) {
mContext = builder.getContext();
mWrappedAgent = builder.getWrappedAgent();
}

File getWrappedAgent() {
String getWrappedAgent() {
return mWrappedAgent;
}

LinkedHashMap<String, Class<? extends FridaInterface>> getInterfaces() {
return mInterfaces;
}


PackageManager getPackageManager() {
return mContext.getPackageManager();
}

String getPackageName() {
return mContext.getPackageName();
}

File getFilesDir() {
return mContext.getFilesDir();
}

public void registerInterface(String cmd, Class<? extends FridaInterface> fridaInterface) {
mInterfaces.put(cmd, fridaInterface);
}

public static class Builder {
private final Context mContext;

private File mWrappedAgent;
private String mWrappedAgent;
private OnMessage mOnMessage;

public Builder(Context context) {
Expand All @@ -59,9 +101,7 @@ public Builder withAgentFromAssets(String agentPath) throws IOException {
}

public Builder withAgentFromString(String agent) {
mWrappedAgent = new File(mContext.getFilesDir(), "wrapped_agent.js");
String wrappedAgent = sWrapper + agent;
Utils.writeToFile(mWrappedAgent, wrappedAgent);
mWrappedAgent = sWrapper + agent;
return this;
}

Expand All @@ -83,9 +123,13 @@ public FridaAgent build() {
return new FridaAgent(this);
}

File getWrappedAgent() {
String getWrappedAgent() {
return mWrappedAgent;
}

Context getContext() {
return mContext;
}
}

private static class DataBroadcast extends BroadcastReceiver {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;

import com.chrisplus.rootmanager.RootManager;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.concurrent.TimeUnit;

public class FridaInjector {
Expand All @@ -26,13 +29,62 @@ public void inject(FridaAgent fridaAgent, String packageName, boolean spawn) {
throw new RuntimeException("did you forget to call init()?");
}

String agentPath = fridaAgent.getWrappedAgent().getPath();
RootManager.getInstance().runCommand("chmod 777 " + agentPath);

if (!RootManager.getInstance().isProcessRunning(packageName)) {
spawn = true;
}

StringBuilder agent = new StringBuilder(fridaAgent.getWrappedAgent());

if (!fridaAgent.getInterfaces().isEmpty()) {
try {
ApplicationInfo ownAi = fridaAgent.getPackageManager().getApplicationInfo(
fridaAgent.getPackageName(), 0);
String ownApk = ownAi.publicSourceDir;
ApplicationInfo targetAi = fridaAgent.getPackageManager().getApplicationInfo(packageName, 0);
String targetPath = new File(targetAi.publicSourceDir).getPath().substring(0,
targetAi.publicSourceDir.lastIndexOf("/"));
if (targetPath.startsWith("/system/")) {
RootManager.getInstance().remount("/system", "rw");
}
RootManager.getInstance().runCommand("cp " + ownApk + " " + targetPath + "/xd.apk");
RootManager.getInstance().runCommand("chmod 644 " + targetPath + "/xd.apk");
if (targetPath.startsWith("/system/")) {
RootManager.getInstance().runCommand("chown root:root " + targetPath + "/xd.apk");
RootManager.getInstance().remount("/system", "ro");
} else {
RootManager.getInstance().runCommand("chown system:system " + targetPath + "/xd.apk");
}

agent.append(FridaAgent.sRegisterClassLoaderAgent);

for (LinkedHashMap.Entry<String, Class<? extends FridaInterface>> entry :
fridaAgent.getInterfaces().entrySet()) {
agent.append("Java['")
.append(entry.getKey())
.append("'] = function() {")
.append("var defaultClassLoader = Java.classFactory.loader;")
.append("Java.classFactory.loader = Java.classFactory['xd_loader'];")
.append("var clazz = Java.use('")
.append(entry.getValue().getName())
.append("').$new();")
.append("var args = [];")
.append("for (var i=0;i<arguments.length;i++) {")
.append("args[i] = arguments[i]")
.append("}")
.append("clazz.call(Java.array('java.lang.Object', args));")
.append("Java.classFactory.loader = defaultClassLoader;")
.append("};")
.append("\n");
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}

File fridaAgentFile = new File(fridaAgent.getFilesDir(), "wrapped_agent.js");
Utils.writeToFile(fridaAgentFile, agent.toString());
RootManager.getInstance().runCommand("chmod 777 " + fridaAgentFile.getPath());

if (spawn) {
Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
RootManager.getInstance().killProcessByName(packageName);
Expand All @@ -50,7 +102,7 @@ public void inject(FridaAgent fridaAgent, String packageName, boolean spawn) {
e.printStackTrace();
}
}
inject(packageName, agentPath);
inject(packageName, fridaAgentFile.getPath());
}).start();

if (launchIntent != null) {
Expand All @@ -61,7 +113,7 @@ public void inject(FridaAgent fridaAgent, String packageName, boolean spawn) {
// todo: handle cases here
}
} else {
inject(packageName, agentPath);
inject(packageName, fridaAgentFile.getPath());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.igio90.fridainjector;

public interface FridaInterface {
public Object call(Object[] args);
}
18 changes: 14 additions & 4 deletions fridainjectorexample/src/main/assets/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@ function log(what) {

Java.performNow(function() {
var TextView = Java.use("android.widget.TextView");
TextView.setText.overloads[0].implementation = function() {
arguments[0] = Java.use("java.lang.String").$new("It works!");
return this.setText.apply(this, arguments);
}
TextView.setText.overloads[0].implementation = function() {
arguments[0] = Java.use("java.lang.String").$new("It works!");
return this.setText.apply(this, arguments);
}
});

setTimeout(function() {
Java.perform(function() {
var app = Java.use("android.app.Activity");
app.onResume.overloads[0].implementation = function() {
this.onResume.apply(this, arguments);
Java.activityInterface(Java.cast(this, app), "otherArg1", "otherArg2");
};
});
}, 2000);

setTimeout(function() {
Java.send({'pid': Process.id});
}, 5 * 1000);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.igio90.fridainjectorexample;

import android.util.Log;

import com.igio90.fridainjector.FridaInterface;

import java.util.Arrays;

public class Interfaces {
static final class ActivityInterface implements FridaInterface {
@Override
public Object call(Object[] args) {
Log.e("FridaAndroidInject", Arrays.toString(args));
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ protected void onCreate(Bundle savedInstanceState) {
.withAgentFromAssets("agent.js")
.withOnMessage(this)
.build();
// inject systemUi
fridaInjector.inject(fridaAgent, "com.android.systemui", true);

// register a custom interface
fridaAgent.registerInterface("activityInterface", Interfaces.ActivityInterface.class);

// inject whatsapp
fridaInjector.inject(fridaAgent, "com.whatsapp", true);
} catch (IOException e) {
e.printStackTrace();
}
Expand All @@ -43,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) {
public void onMessage(String data) {
try {
JSONObject object = new JSONObject(data);
Log.e("FridaInjector", "SystemUI pid: " + object.getString("pid"));
Log.e("FridaAndroidInject", "whatsapp pid: " + object.getString("pid"));
} catch (JSONException e) {
e.printStackTrace();
}
Expand Down

0 comments on commit 3d844f2

Please sign in to comment.