First commit
14
build.gradle
@ -33,17 +33,17 @@ android {
|
||||
|
||||
task downloadAarch(type: Download) {
|
||||
src 'https://jenkins.awain.net/job/Frida-android-binaries/lastSuccessfulBuild/artifact/jniLibs/arm64-v8a/frida.so'
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/arm64-v8a/frida.so')
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/arm64-v8a/libfrida.so')
|
||||
}
|
||||
|
||||
task downloadArmeabi(type: Download) {
|
||||
src 'https://jenkins.awain.net/job/Frida-android-binaries/lastSuccessfulBuild/artifact/jniLibs/armeabi-v7a/frida.so'
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/armeabi-v7a/frida.so')
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/armeabi-v7a/libfrida.so')
|
||||
}
|
||||
|
||||
task downloadx86(type: Download, ) {
|
||||
src 'https://jenkins.awain.net/job/Frida-android-binaries/lastSuccessfulBuild/artifact/jniLibs/x86/frida.so'
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/x86/frida.so')
|
||||
dest layout.projectDirectory.file('src/main/jniLibs/x86/libfrida.so')
|
||||
}
|
||||
|
||||
task deleteLibs(type: Delete) {
|
||||
@ -52,19 +52,21 @@ task deleteLibs(type: Delete) {
|
||||
}
|
||||
}
|
||||
|
||||
preBuild.dependsOn deleteLibs
|
||||
preBuild.dependsOn downloadAarch
|
||||
//preBuild.dependsOn deleteLibs
|
||||
//preBuild.dependsOn downloadAarch
|
||||
/*preBuild.dependsOn downloadArmeabi
|
||||
preBuild.dependsOn downloadx86*/
|
||||
|
||||
dependencies {
|
||||
implementation libs.okhttp
|
||||
implementation libs.ground.crockford32
|
||||
implementation libs.commons.codec
|
||||
implementation libs.ktsh
|
||||
implementation libs.appcompat
|
||||
implementation libs.material
|
||||
implementation libs.activity
|
||||
implementation libs.constraintlayout
|
||||
implementation libs.room.runtime
|
||||
annotationProcessor libs.room.compiler
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.ext.junit
|
||||
androidTestImplementation libs.espresso.core
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="internalOnly"> <!-- android:installLocation="internalOnly" -->
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
|
||||
@ -9,19 +9,21 @@
|
||||
|
||||
|
||||
<application
|
||||
android:hardwareAccelerated="true"
|
||||
android:extractNativeLibs="true"
|
||||
android:allowBackup="false"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.FridaApp"
|
||||
tools:targetApi="34"
|
||||
tools:replace="android:allowBackup">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -1,4 +1,18 @@
|
||||
package com.alterdekim.frida;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class FridaLib {
|
||||
|
||||
static {
|
||||
System.loadLibrary("frida");
|
||||
}
|
||||
|
||||
public native int start(String config_b32, int tun_fd, boolean close_fd_on_drop);
|
||||
|
||||
public native int stop();
|
||||
|
||||
private static void traceFromNative(String text) {
|
||||
Log.i("FridaLib", text);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
package com.alterdekim.fridaapp;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnService;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
@ -13,18 +19,41 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.room.Room;
|
||||
|
||||
import com.alterdekim.fridaapp.room.AppDatabase;
|
||||
import com.alterdekim.fridaapp.room.Config;
|
||||
import com.alterdekim.fridaapp.service.FridaService;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
import org.apache.commons.codec.binary.Base32;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {
|
||||
private static final String TAG = MainActivity.class.getSimpleName();
|
||||
private AppDatabase db;
|
||||
|
||||
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() != Activity.RESULT_OK) return;
|
||||
Intent data = result.getData();
|
||||
try {
|
||||
String raw_data = Util.readTextFromUri(this, data.getData());
|
||||
String name = Util.getFilenameFromUri(this, data.getData());
|
||||
String b32 = Base32.builder().get().encodeToString(raw_data.getBytes(StandardCharsets.UTF_8));
|
||||
db.userDao().insertAll(new Config(name, b32));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
private final ActivityResultLauncher<Intent> launcher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == RESULT_OK) {
|
||||
startService(new Intent(this, FridaService.class));
|
||||
}
|
||||
if (result.getResultCode() != RESULT_OK) return;
|
||||
startService(new Intent(this, FridaService.class));
|
||||
}
|
||||
);
|
||||
|
||||
@ -33,23 +62,54 @@ public class MainActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
this.db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "def-db").build();
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
findViewById(R.id.addConfig).setOnClickListener(v -> {
|
||||
PopupMenu popup = new PopupMenu(this, v);
|
||||
popup.setOnMenuItemClickListener(MainActivity.this);
|
||||
popup.getMenuInflater().inflate(R.menu.mm, popup.getMenu());
|
||||
popup.show();
|
||||
});
|
||||
|
||||
findViewById(R.id.start_btn).setOnClickListener(view -> startVpn());
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
for( Config config : db.userDao().getAll() ) {
|
||||
|
||||
View myLayout = inflater.inflate(R.layout.single_config, mainLayout, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if( item.getItemId() == R.id.new_config ) {
|
||||
newConfig();
|
||||
return true;
|
||||
} else if( item.getItemId() == R.id.import_from_file ) {
|
||||
importConfigFromFile();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void newConfig() {
|
||||
Toast.makeText(this, "newConfig", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void importConfigFromFile() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("application/*");
|
||||
someActivityResultLauncher.launch(intent);
|
||||
}
|
||||
|
||||
private void startVpn() {
|
||||
Intent intent = VpnService.prepare(MainActivity.this);
|
||||
if (intent != null) {
|
||||
Log.i("ASD", "!= null");
|
||||
launcher.launch(intent);
|
||||
} else {
|
||||
Log.i("ASD", "== null");
|
||||
startService(new Intent(this, FridaService.class));
|
||||
return;
|
||||
}
|
||||
startService(new Intent(this, FridaService.class));
|
||||
}
|
||||
}
|
37
src/main/java/com/alterdekim/fridaapp/Util.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.alterdekim.fridaapp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.OpenableColumns;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Util {
|
||||
public static String readTextFromUri(Context context, Uri uri) throws IOException {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
try (InputStream inputStream =
|
||||
context.getContentResolver().openInputStream(uri);
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(Objects.requireNonNull(inputStream)))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public static String getFilenameFromUri(Context context, Uri uri) {
|
||||
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst() && cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) >= 0) {
|
||||
return cursor.getString(Math.abs(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)));
|
||||
}
|
||||
}
|
||||
return "default";
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.alterdekim.fridaapp.room;
|
||||
|
||||
import androidx.room.Database;
|
||||
import androidx.room.RoomDatabase;
|
||||
|
||||
@Database(entities = {Config.class}, version = 1)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
public abstract ConfigDAO userDao();
|
||||
}
|
22
src/main/java/com/alterdekim/fridaapp/room/Config.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.alterdekim.fridaapp.room;
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
@Entity
|
||||
public class Config {
|
||||
@PrimaryKey
|
||||
public int uid;
|
||||
|
||||
@ColumnInfo(name = "title")
|
||||
public String title;
|
||||
|
||||
@ColumnInfo(name = "data_b32")
|
||||
public String data_b32;
|
||||
|
||||
public Config(String title, String data_b32) {
|
||||
this.title = title;
|
||||
this.data_b32 = data_b32;
|
||||
}
|
||||
}
|
27
src/main/java/com/alterdekim/fridaapp/room/ConfigDAO.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.alterdekim.fridaapp.room;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Delete;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Dao
|
||||
public interface ConfigDAO {
|
||||
@Query("SELECT * FROM config")
|
||||
List<Config> getAll();
|
||||
|
||||
@Query("SELECT * FROM config WHERE uid IN (:cfgIds)")
|
||||
List<Config> loadAllByIds(int[] cfgIds);
|
||||
|
||||
@Query("SELECT * FROM config WHERE uid = :cfgId")
|
||||
Optional<Config> loadById(int cfgId);
|
||||
|
||||
@Insert
|
||||
void insertAll(Config... users);
|
||||
|
||||
@Delete
|
||||
void delete(Config user);
|
||||
}
|
@ -6,6 +6,7 @@ import android.net.VpnService;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import com.alterdekim.frida.FridaLib;
|
||||
import com.alterdekim.fridaapp.R;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -23,14 +24,13 @@ public class FridaService extends VpnService {
|
||||
private ParcelFileDescriptor vpnInterface = null;
|
||||
private PendingIntent pendingIntent;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
setupVPN();
|
||||
Log.i(TAG, "Started");
|
||||
// .detachFd()
|
||||
try {
|
||||
Thread t = new Thread(new NativeBinaryConnection(vpnInterface.dup().getFd(), getApplicationContext().getApplicationInfo().nativeLibraryDir));
|
||||
Thread t = new Thread(new NativeBinaryConnection(vpnInterface.dup().detachFd(), getApplicationContext().getApplicationInfo().nativeLibraryDir));
|
||||
t.start();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
@ -47,11 +47,11 @@ public class FridaService extends VpnService {
|
||||
.build();
|
||||
try {
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
Log.i(TAG, "Response code: " + response.code());
|
||||
// Log.i(TAG, "Response code: " + response.code());
|
||||
if (response.body() != null) {
|
||||
Log.i(TAG, "Response body: " + response.body().string());
|
||||
// Log.i(TAG, "Response body: " + response.body().string());
|
||||
} else {
|
||||
Log.i(TAG, "Response body: null");
|
||||
// Log.i(TAG, "Response body: null");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@ -65,14 +65,15 @@ public class FridaService extends VpnService {
|
||||
try {
|
||||
//if (vpnInterface == null) {
|
||||
Builder builder = new Builder();
|
||||
builder.addAddress(VPN_ADDRESS, 32);
|
||||
builder.setMtu(1400);
|
||||
builder.addAddress(VPN_ADDRESS, 24);
|
||||
builder.addRoute(VPN_ROUTE, 0);
|
||||
//builder.addDnsServer("1.1.1.1");
|
||||
//builder.setMtu(1400);
|
||||
builder.addDnsServer("8.8.8.8");
|
||||
//builder.addAllowedApplication();
|
||||
//builder.addDisallowedApplication();
|
||||
|
||||
vpnInterface = builder.setSession(getString(R.string.app_name)).setConfigureIntent(pendingIntent).establish();
|
||||
builder.addDisallowedApplication("com.alterdekim.fridaapp");
|
||||
// .setSession(getString(R.string.app_name))
|
||||
// .setConfigureIntent(pendingIntent)
|
||||
vpnInterface = builder.establish();
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error", e);
|
||||
|
@ -2,6 +2,7 @@ package com.alterdekim.fridaapp.service;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.alterdekim.frida.FridaLib;
|
||||
import com.jaredrummler.ktsh.Shell;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -23,23 +24,10 @@ public class NativeBinaryConnection implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
Log.i(TAG, "FD: " + this.fd);
|
||||
/* Shell shell = new Shell("sh");
|
||||
Shell.Command.Result result = shell.run(command);
|
||||
Log.i(TAG, result.stdout());
|
||||
Log.i(TAG, result.stderr());*/
|
||||
ProcessBuilder p = new ProcessBuilder("./frida.so", "--fd", fd+"", "--config", "MNWGSZLOOQ5A2CRAEBYHE2LWMF2GKX3LMV4TUIDPMIYTKOBRNFVTMNZSGNTU6ZTKJ4XXS3DIO44WIVZLNRLTE2LCI5ZXISDVIJKVG42MK5MT2DIKEAQHA5LCNRUWGX3LMV4TUIDEMRBWGSSYIFIVS4SRHFWVIRTJOB2HOK3OK5WXOUJXG5IESSSQOAYEU3SLJ5GU6NCLIMYD2DIKEAQGCZDEOJSXG4Z2EAYTALRWGYXDMNROGYGQU43FOJ3GK4R2BUFCAIDQOVRGY2LDL5VWK6J2EBCUUTSROIZVUNKKJBWC65CDLFNC6UDDJZGGWTLTKMYGCS3OMZVGINCKMJ3DMVDVHE3EKTJ5BUFCAIDFNZSHA33JNZ2DUIBRGU4S4MJQGAXDCOBOHA4DUOBXHEZQ2CRAEBVWKZLQMFWGS5TFHIQDEMANBI======").directory(new File(baseDir));
|
||||
p.redirectErrorStream(true);
|
||||
|
||||
Process pr = p.start();
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
Log.i(TAG, line);
|
||||
}
|
||||
pr.waitFor();
|
||||
Log.i(TAG, "ok!");
|
||||
in.close();
|
||||
FridaLib lib = new FridaLib();
|
||||
Log.i(TAG, "Starting Frida client");
|
||||
int r = lib.start("<data>", this.fd, false);
|
||||
Log.i(TAG, "Exit code: " + r);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
5
src/main/res/drawable/baseline_add_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
|
||||
</vector>
|
5
src/main/res/drawable/baseline_create_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
||||
|
||||
</vector>
|
5
src/main/res/drawable/baseline_file_open_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M14,2H6C4.9,2 4,2.9 4,4v16c0,1.1 0.89,2 1.99,2H15v-8h5V8L14,2zM13,9V3.5L18.5,9H13zM17,21.66V16h5.66v2h-2.24l2.95,2.95l-1.41,1.41L19,19.41l0,2.24H17z"/>
|
||||
|
||||
</vector>
|
@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
@ -7,13 +7,28 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<Button
|
||||
android:id="@+id/start_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Start VPN"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/addConfig"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:clickable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/baseline_add_24"
|
||||
android:focusable="true" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/config_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
22
src/main/res/layout/single_config.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:longClickable="true"
|
||||
android:paddingVertical="5dp">
|
||||
<TextView
|
||||
android:id="@+id/config_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/config_switch"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="48dp" />
|
||||
</LinearLayout>
|
9
src/main/res/layout/single_divider.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
</LinearLayout>
|
11
src/main/res/menu/mm.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/new_config"
|
||||
android:icon="@drawable/baseline_create_24"
|
||||
android:iconTint="@color/black"
|
||||
android:title="@string/create_config" />
|
||||
<item android:id="@+id/import_from_file"
|
||||
android:icon="@drawable/baseline_file_open_24"
|
||||
android:iconTint="@color/black"
|
||||
android:title="@string/import_config" />
|
||||
</menu>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
BIN
src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
BIN
src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 982 B |
Before Width: | Height: | Size: 1.7 KiB |
BIN
src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.8 KiB |
BIN
src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.8 KiB |
BIN
src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.6 KiB |
@ -1,7 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.FridaApp" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<style name="Base.Theme.FridaApp" parent="Theme.Material3.DayNight">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
</style>
|
||||
</resources>
|
@ -2,4 +2,5 @@
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="colorPrimary">#731DD8</color>
|
||||
</resources>
|
@ -1,3 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Frida</string>
|
||||
<string name="create_config">Create from scratch</string>
|
||||
<string name="import_config">Import from file</string>
|
||||
</resources>
|
@ -1,8 +1,8 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.FridaApp" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<style name="Base.Theme.FridaApp" parent="Theme.Material3.DayNight">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.FridaApp" parent="Base.Theme.FridaApp" />
|
||||
|