Fixing bugs, reducing hardcode blobs.

This commit is contained in:
Michael Wain 2025-01-20 23:17:07 +03:00
parent 12dfe42379
commit a6ab9fda8b
10 changed files with 131 additions and 19 deletions

View File

@ -67,6 +67,9 @@ dependencies {
implementation "androidx.room:room-rxjava3:2.6.1"
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
implementation 'com.fasterxml.jackson.jr:jackson-jr-objects:2.18.2'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2'
runtimeOnly 'com.fasterxml.jackson.jr:jackson-jr-annotation-support:2.18.2'
compileOnly 'org.projectlombok:lombok:1.18.34'
annotationProcessor 'org.projectlombok:lombok:1.18.34'
implementation libs.androidx.coordinatorlayout

View File

@ -0,0 +1,31 @@
package com.alterdekim.frida.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.jetbrains.annotations.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@ToString
@Getter
public class ClientConfig {
@NotNull
private String private_key;
@NotNull
private String public_key;
@NotNull
private String address;
@JsonCreator
public ClientConfig(@JsonProperty(required = true, value = "private_key") @NotNull String private_key,
@JsonProperty(required = true, value = "public_key") @NotNull String public_key,
@JsonProperty(required = true, value = "address") @NotNull String address) {
this.private_key = private_key;
this.public_key = public_key;
this.address = address;
}
}

View File

@ -0,0 +1,27 @@
package com.alterdekim.frida.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.jetbrains.annotations.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@ToString
@Getter
@NoArgsConstructor
public class Config {
@NotNull
@JsonProperty(required = true)
private ClientConfig client;
@NotNull
@JsonProperty(required = true)
private ServerConfig server;
public Config(@JsonProperty(required = true, value = "client") @NotNull ClientConfig client, @JsonProperty(required = true, value = "server") @NotNull ServerConfig server) {
this.client = client;
this.server = server;
}
}

View File

@ -0,0 +1,32 @@
package com.alterdekim.frida.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.jetbrains.annotations.NotNull;
import lombok.Getter;
import lombok.ToString;
@ToString
@Getter
public class ServerConfig {
@NotNull
private String public_key;
@NotNull
private String endpoint;
@NotNull
private String internal_gateway;
private byte keepalive;
@JsonCreator
public ServerConfig(@JsonProperty(required = true, value = "public_key") @NotNull String public_key,
@JsonProperty(required = true, value = "endpoint") @NotNull String endpoint,
@JsonProperty(required = true, value = "internal_gateway") @NotNull String internal_gateway,
@JsonProperty(required = true, value = "keepalive") byte keepalive) {
this.public_key = public_key;
this.endpoint = endpoint;
this.internal_gateway = internal_gateway;
this.keepalive = keepalive;
}
}

View File

@ -55,8 +55,8 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
try {
String raw_data = Util.readTextFromUri(this, data.getData());
String name = Util.getFilenameFromUri(this, data.getData());
String hex = Util.bytesToHex(raw_data.getBytes());
this.controller.insertNewConfig(name, hex);
byte[] config = raw_data.getBytes();
this.controller.insertNewConfig(name, config);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}

View File

@ -16,8 +16,12 @@ import com.alterdekim.fridaapp.activity.SingleConfigActivity;
import com.alterdekim.fridaapp.room.AppDatabase;
import com.alterdekim.fridaapp.room.Config;
import com.alterdekim.fridaapp.service.FridaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.android.material.switchmaterial.SwitchMaterial;
import java.io.IOException;
import java.util.Iterator;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
@ -59,8 +63,8 @@ public class MainActivityController implements IController {
Config config = iter.next();
View cfg_instance = inflater.inflate(R.layout.single_config, this.mainActivity.getCfg_list(), false);
this.mainActivity.getCfg_list().addView(cfg_instance);
TextView view_name = (TextView) cfg_instance.findViewById(R.id.config_name);
SwitchMaterial view_switch = (SwitchMaterial) cfg_instance.findViewById(R.id.config_switch);
TextView view_name = cfg_instance.findViewById(R.id.config_name);
SwitchMaterial view_switch = cfg_instance.findViewById(R.id.config_switch);
view_switch.setUseMaterialThemeColors(true);
view_switch.setOnCheckedChangeListener((compoundButton, b) -> toggleVpn(view_switch, config, b));
view_name.setText(config.getTitle());
@ -75,8 +79,17 @@ public class MainActivityController implements IController {
.subscribe();
}
public void insertNewConfig(String name, String hex) {
db.userDao().insertAll(new Config(name, hex))
public void insertNewConfig(String name, byte[] config) {
try {
com.alterdekim.frida.config.Config cfg = new ObjectMapper(new YAMLFactory()).setAnnotationIntrospector(new JacksonAnnotationIntrospector()).readValue(config, com.alterdekim.frida.config.Config.class);
Log.i(TAG, cfg.toString());
} catch (IOException e) {
Log.e(TAG, "Can't parse config");
e.printStackTrace();
Toast.makeText(this.mainActivity, R.string.config_adding_error, Toast.LENGTH_LONG).show();
return;
}
db.userDao().insertAll(new Config(name, config))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(throwable -> Toast.makeText(MainActivityController.this.mainActivity, R.string.config_adding_error, Toast.LENGTH_LONG).show())
@ -86,7 +99,7 @@ public class MainActivityController implements IController {
private void toggleVpn(SwitchMaterial view, Config config, boolean val) {
Intent intent = new Intent(this.mainActivity, FridaService.class);
intent.putExtra("vpn_hex", config.getData_hex());
intent.putExtra("vpn_data", config.getData_raw());
intent.putExtra("vpn_uid", config.getUid());
intent.putExtra("vpn_state", val);
this.mainActivity.startService(intent);

View File

@ -21,6 +21,6 @@ public class Config {
@ColumnInfo(name = "title")
private final String title;
@ColumnInfo(name = "data_hex")
private final String data_hex;
@ColumnInfo(name = "data_raw")
private final byte[] data_raw;
}

View File

@ -6,6 +6,10 @@ import android.os.ParcelFileDescriptor;
import android.util.Log;
import com.alterdekim.frida.FridaLib;
import com.alterdekim.frida.config.Config;
import com.alterdekim.fridaapp.util.Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.BufferedReader;
import java.io.File;
@ -20,7 +24,6 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
public class FridaService extends VpnService {
private static final String TAG = FridaService.class.getSimpleName();
private static final String VPN_ADDRESS = "10.66.66.6"; // Only IPv4 support for now
private static final String VPN_ROUTE = "0.0.0.0"; // Intercept everything
private ParcelFileDescriptor vpnInterface = null;
@ -36,8 +39,9 @@ public class FridaService extends VpnService {
Log.i(TAG, "Created");
}
private void setupVPN() {
private void setupVPN(byte[] cfg_raw) {
try {
Config config = new ObjectMapper(new YAMLFactory()).readValue(cfg_raw, Config.class);
File outputDir = this.getCacheDir(); // context being the Activity pointer
File outputFile = new File(outputDir, "fridalib.log");
if( outputFile.exists() ) { outputFile.delete(); }
@ -61,9 +65,9 @@ public class FridaService extends VpnService {
Builder builder = new Builder();
builder.setMtu(1400);
builder.addAddress(VPN_ADDRESS, 24);
builder.addAddress(config.getClient().getAddress(), 24);
builder.addRoute(VPN_ROUTE, 0);
builder.addDnsServer("8.8.8.8");
//builder.addDnsServer("8.8.8.8");
//builder.addAllowedApplication();
builder.addDisallowedApplication("com.alterdekim.fridaapp");
vpnInterface = builder.establish();
@ -95,16 +99,16 @@ public class FridaService extends VpnService {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if( intent.getExtras() == null ) return START_STICKY;
String hex = intent.getExtras().getString("vpn_hex");
byte[] config = intent.getExtras().getByteArray("vpn_data");
int uid = intent.getExtras().getInt("vpn_uid");
boolean state = intent.getExtras().getBoolean("vpn_state");
if(!state) {
this.lib.stop();
return START_STICKY;
}
setupVPN();
setupVPN(config);
// TODO: different configs
this.vpnProcess = Flowable.fromRunnable(new NativeBinaryConnection(vpnInterface.detachFd(), hex, lib, logPath))
this.vpnProcess = Flowable.fromRunnable(new NativeBinaryConnection(vpnInterface.detachFd(), Util.bytesToHex(config), lib, logPath))
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe();

View File

@ -4,6 +4,8 @@ import android.util.Log;
import com.alterdekim.frida.FridaLib;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@ -20,10 +22,10 @@ public class NativeBinaryConnection implements Runnable {
try {
Log.i(TAG, "FD: " + this.fd);
Log.i(TAG, "Starting Frida client");
int r = lib.start(this.hex.toLowerCase(), this.fd, false, this.tempFile);
int r = lib.start(this.hex, this.fd, false, this.tempFile);
Log.i(TAG, "Exit code: " + r);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
Log.e(TAG, Objects.requireNonNull(e.getMessage()));
}
}
}

View File

@ -34,7 +34,7 @@ public class Util {
return "default";
}
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {