Skip to content

Commit

Permalink
1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
iGio90 committed Jan 6, 2020
1 parent 2b8327c commit 5fb1904
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 99 deletions.
66 changes: 16 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,57 +26,23 @@ dependencies {

#### How to:

- create assets folder in your project
- put your updated frida injector binaries (I got further plans to kill this step and handle releases with binary updater inside the library) in the assets folder
-> You can safely push a new updated binary. The library will remove the old one and extract the binary updated only once
- at this point you will need a similar switch case to identify the right arch to use:

```java
String fridaInjectorBinaryAssetName = "";
switch (getArch()) {
case "arm":
fridaInjectorBinaryAssetName = "arm_frida_injector"
break;
case "arm64":
fridaInjectorBinaryAssetName = "arm64_frida_injector"
break;
case "x86":
fridaInjectorBinaryAssetName = "x86_frida_injector"
break;
case "x86_64":
fridaInjectorBinaryAssetName = "x86_64_frida_injector"
break;
default:
return;
try {
// build an instance of FridaInjector providing binaries for arm/arm64/x86/x86_64 as needed
// assets/frida-inject-12.8.2-android-arm64
FridaInjector fridaInjector = new FridaInjector.Builder(this)
.withArm64Injector("frida-inject-12.8.2-android-arm64")
.build();

// build an instance of Frida agent
FridaAgent fridaAgent = FridaAgent.fromAsset(this, "agent.js");

// inject systemUi
fridaInjector.inject(fridaAgent, "com.android.systemui", true);
} catch (IOException e) {
e.printStackTrace();
}
````

...


public static String getArch() {
for (String androidArch : Build.SUPPORTED_ABIS) {
switch (androidArch) {
case "arm64-v8a": return "arm64";
case "armeabi-v7a": return "arm";
case "x86_64": return "x86_64";
case "x86": return "x86";
}
}

throw new RuntimeException("Unable to determine arch from Build.SUPPORTED_ABIS = " +
Arrays.toString(Build.SUPPORTED_ABIS));
}
```

- add your agent.js in the assets folder as well and then just:

```java
try {
FridaInjector fridaInjector = new FridaInjector(this, "fridaInjectorBinaryAssetName");
fridaInjector.inject("com.android.systemui", "agent.js", true);
} catch (IOException e) {
e.printStackTrace();
}
```

The example apk [here](https://github.com/igio90/FridaAndroidInjector/tree/master/example.apk) will inject into the systemui and turn you clock black. Because black is black.
The example apk [here](https://github.com/igio90/FridaAndroidInjector/tree/master/example.apk) is this little example built and ready. You will see it works! (only arm64).
Binary file modified example.apk
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.igio90.fridainjector;

import android.content.Context;

import java.io.File;
import java.io.IOException;

public class FridaAgent {

private final File mAgent;

public static FridaAgent fromAsset(Context context, String assetPath) throws IOException {
FridaAgent fridaAgent = new FridaAgent(context);
Utils.extractAsset(context, assetPath, fridaAgent.getAgent());
return fridaAgent;
}

private FridaAgent(Context context) {
mAgent = new File(context.getFilesDir(), "agent.js");
}

File getAgent() {
return mAgent;
}
}
142 changes: 106 additions & 36 deletions fridainjector/src/main/java/com/igio90/fridainjector/FridaInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Build;

import com.chrisplus.rootmanager.RootManager;

Expand All @@ -11,34 +12,26 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class FridaInjector {
private final Context mContext;

private File mInjector;
private final File mInjector;

public FridaInjector(Context context, String injectorBinaryAssetPath) throws IOException {
mContext = context;

if (!RootManager.getInstance().hasRooted()) {
throw new RuntimeException("must run on a rooted device");
}
if (!RootManager.getInstance().obtainPermission()) {
throw new RuntimeException("failed to obtain root permissions");
}

extractInjectorIfNeeded(injectorBinaryAssetPath);
private FridaInjector(FridaInjector.Builder builder) {
mContext = builder.mContext;
mInjector = builder.getInjector();
}

public void inject(final String packageName, String agentAssetPath, boolean spawn) throws IOException {
public void inject(FridaAgent fridaAgent, String packageName, boolean spawn) {
if (mInjector == null) {
throw new RuntimeException("did you forget to call init()?");
}

final File agent = new File(mContext.getFilesDir(), "agent.js");
extractAsset(agentAssetPath, agent);
RootManager.getInstance().runCommand("chmod 777 " + agent.getPath());
String agentPath = fridaAgent.getAgent().getPath();
RootManager.getInstance().runCommand("chmod 777 " + agentPath);

if (!RootManager.getInstance().isProcessRunning(packageName)) {
spawn = true;
Expand All @@ -61,7 +54,7 @@ public void inject(final String packageName, String agentAssetPath, boolean spaw
e.printStackTrace();
}
}
inject(packageName, agent.getPath());
inject(packageName, agentPath);
}).start();

if (launchIntent != null) {
Expand All @@ -72,46 +65,123 @@ public void inject(final String packageName, String agentAssetPath, boolean spaw
// todo: handle cases here
}
} else {
inject(packageName, agent.getPath());
inject(packageName, agentPath);
}
}

private void inject(String packageName, String agentPath) {
RootManager.getInstance().runCommand(mInjector.getPath() + " -n " + packageName +
" -s " + agentPath + " -e");
" -s " + agentPath + " --runtime=v8 -e");
}

public static class Builder {
private final Context mContext;
private String mArmBinaryPath;
private String mArm64BinaryPath;
private String mX86BinaryPath;
private String mX86_64BinaryPath;

private File mInjector;

public Builder(Context context) {
if (!RootManager.getInstance().hasRooted()) {
throw new RuntimeException("must run on a rooted device");
}
if (!RootManager.getInstance().obtainPermission()) {
throw new RuntimeException("failed to obtain root permissions");
}

mContext = context;
}

public Builder withArmInjector(String armInjectorBinaryAssetName) {
mArmBinaryPath = armInjectorBinaryAssetName;
return this;
}

public Builder withArm64Injector(String arm64InjectorBinaryAssetName) {
mArm64BinaryPath = arm64InjectorBinaryAssetName;
return this;
}

public Builder withX86Injector(String x86InjectorBinaryAssetName) {
mX86BinaryPath = x86InjectorBinaryAssetName;
return this;
}

public Builder withX86_64Injector(String x86_64InjectorBinaryAssetName) {
mX86_64BinaryPath = x86_64InjectorBinaryAssetName;
return this;
}

public FridaInjector build() throws IOException {
if (mArmBinaryPath == null && mArm64BinaryPath == null &&
mX86BinaryPath == null && mX86_64BinaryPath == null) {
throw new RuntimeException("injector asset file name not provided");
}

String arch = getArch();
String injectorName = null;
switch (arch) {
case "arm":
injectorName = mArmBinaryPath;
break;
case "arm64":
injectorName = mArm64BinaryPath;
break;
case "x86":
injectorName = mX86BinaryPath;
break;
case "x86_64":
injectorName = mX86_64BinaryPath;
break;
}

if (injectorName == null) {
throw new RuntimeException("injector binary not provided for arch: " + arch);
}

mInjector = extractInjectorIfNeeded(mContext, injectorName);
return new FridaInjector(this);
}

private File getInjector() {
return mInjector;
}
}

private void extractInjectorIfNeeded(String name) throws IOException {
File injectorPath = new File(mContext.getFilesDir(), "injector");
mInjector = new File(injectorPath, name);
private static File extractInjectorIfNeeded(Context context, String name) throws IOException {
File injectorPath = new File(context.getFilesDir(), "injector");
File injector = new File(injectorPath, name);

if (!injectorPath.exists()) {
injectorPath.mkdir();
} else {
File[] files = injectorPath.listFiles();
if (files != null && files.length > 0) {
if (files[0].getName().equals(name)) {
return;
return injector;
}
files[0].delete();
}
}

extractAsset(name, mInjector);
RootManager.getInstance().runCommand("chmod 777 " + mInjector.getPath());
Utils.extractAsset(context, name, injector);
RootManager.getInstance().runCommand("chmod 777 " + injector.getPath());
return injector;
}

private void extractAsset(String assetName, File dest) throws IOException {
AssetManager assetManager = mContext.getAssets();
InputStream in = assetManager.open(assetName);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
private static String getArch() {
for (String androidArch : Build.SUPPORTED_ABIS) {
switch (androidArch) {
case "arm64-v8a": return "arm64";
case "armeabi-v7a": return "arm";
case "x86_64": return "x86_64";
case "x86": return "x86";
}
}
in.close();
out.flush();
out.close();

throw new RuntimeException("Unable to determine arch from Build.SUPPORTED_ABIS = " +
Arrays.toString(Build.SUPPORTED_ABIS));
}
}
25 changes: 23 additions & 2 deletions fridainjector/src/main/java/com/igio90/fridainjector/Utils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
package com.igio90.fridainjector;

public class Utils {
import android.content.Context;
import android.content.res.AssetManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

}
public class Utils {
static void extractAsset(Context context, String assetName, File dest) throws IOException {
AssetManager assetManager = context.getAssets();
InputStream in = assetManager.open(assetName);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
}
}
14 changes: 5 additions & 9 deletions fridainjectorexample/src/main/assets/agent.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
function log(what) {
Java.performNow(function() {
Java.use('android.util.Log').e("tweakerinj", what.toString());
Java.use('android.util.Log').e("FridaAndroidInject", what.toString());
})
}

Java.performNow(function() {
var TextClock = Java.use("com.android.systemui.statusbar.policy.Clock");
var Color = Java.use("android.graphics.Color");

TextClock.setTextColor.overloads[0].implementation = function() {
if (this.$className === 'com.android.systemui.statusbar.policy.Clock') {
arguments[0] = Color.BLACK.value;
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);
}
return this.setTextColor.apply(this, arguments);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import android.os.Bundle;

import com.igio90.fridainjector.FridaAgent;
import com.igio90.fridainjector.FridaInjector;

import java.io.IOException;
Expand All @@ -15,8 +16,17 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);

try {
FridaInjector fridaInjector = new FridaInjector(this, "frida-inject-12.8.2-android-arm64");
fridaInjector.inject("com.android.systemui", "agent.js", true);
// build an instance of FridaInjector providing binaries for arm/arm64/x86/x86_64 as needed
// assets/frida-inject-12.8.2-android-arm64
FridaInjector fridaInjector = new FridaInjector.Builder(this)
.withArm64Injector("frida-inject-12.8.2-android-arm64")
.build();

// build an instance of Frida agent
FridaAgent fridaAgent = FridaAgent.fromAsset(this, "agent.js");

// inject systemUi
fridaInjector.inject(fridaAgent, "com.android.systemui", true);
} catch (IOException e) {
e.printStackTrace();
}
Expand Down

0 comments on commit 5fb1904

Please sign in to comment.