diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java index b5dcb59d..919fa40a 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java @@ -32,6 +32,7 @@ import android.util.Patterns; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; @@ -136,6 +137,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment private SwitchPreference mMalwareDetectionEnabled; private Billing mIab; private boolean mHasStartedMitmWizard; + private boolean mRootDecryptionNoticeShown = false; private final ActivityResultLauncher requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> @@ -292,6 +294,8 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment return false; } + checkDecrpytionWithRoot(rootCaptureEnabled(), (boolean) newValue); + fullPayloadHideShow((boolean) newValue); mBlockQuic.setVisible((boolean) newValue); socks5ProxyHideShow((boolean) newValue, mSocks5Enabled.isChecked(), rootCaptureEnabled()); @@ -371,6 +375,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment if(Utils.isRootAvailable()) { mRootCaptureEnabled.setOnPreferenceChangeListener((preference, newValue) -> { rootCaptureHideShow((Boolean) newValue); + checkDecrpytionWithRoot((Boolean) newValue, mTlsDecryption.isChecked()); return true; }); } else @@ -408,5 +413,17 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment mCapInterface.setVisible(enabled); mVpnExceptions.setVisible(!enabled); } + + private void checkDecrpytionWithRoot(boolean rootEnabled, boolean tlsDecryption) { + if(mRootDecryptionNoticeShown || !rootEnabled || !tlsDecryption) + return; + + new AlertDialog.Builder(requireContext()) + .setMessage(R.string.tls_decryption_with_root_msg) + .setNeutralButton(R.string.ok, (dialog, whichButton) -> {}) + .show(); + + mRootDecryptionNoticeShown = true; + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aabc7654..8cbb7aac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -393,4 +393,11 @@ Warning Paid features unlocked. Restart the capture if running Build info + The ability to run TLS decryption with root is an experimental feature. This is a list of known bugs:\n\n +- in PCAPdroid you will see the traffic as it was generated from the mitm-addon app in place of the original app\n +- when an app filter is set, decryption will only occur for the target app, but PCAPdroid will still show the other apps traffic\n +- if the capture fails to start, ensure that you can actually run the iptables command as root (e.g. via termux)\n +- this may not work on Android 12 and later\n +- if a VPN app is running, you should either target a specific app for decryption or exclude the PCAPdroid mitm addon from the VPN, otherwise traffic will go in a loop +