Skip to content

Commit

Permalink
Merge branch 'master' into playstore
Browse files Browse the repository at this point in the history
  • Loading branch information
emanuele-f committed Feb 8, 2024
2 parents 41c0af8 + fd2148f commit f102a2d
Show file tree
Hide file tree
Showing 64 changed files with 1,439 additions and 388 deletions.
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: gradle
directory: "/"
schedule:
interval: daily
target-branch: "master"
open-pull-requests-limit: 0

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
target-branch: "master"
open-pull-requests-limit: 0
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@
<activity
android:name=".activities.MitmSetupWizard"
android:launchMode="singleTop" />
<activity
android:name=".activities.AppFilterActivity"
android:launchMode="singleTop"
android:parentActivityName=".activities.MainActivity" />

<service
android:name=".CaptureService"
Expand Down
41 changes: 29 additions & 12 deletions app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
Expand Down Expand Up @@ -127,7 +128,7 @@ public class CaptureService extends VpnService implements Runnable {
private String dns_server;
private long last_bytes;
private int last_connections;
private int app_filter_uid;
private int[] mAppFilterUids;
private PcapDumper mDumper;
private ConnectionsRegister conn_reg;
private Uri mPcapUri;
Expand Down Expand Up @@ -269,7 +270,7 @@ public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
if(mSettings.readFromPcap()) {
// Disable incompatible settings
mSettings.dump_mode = Prefs.DumpMode.NONE;
mSettings.app_filter = "";
mSettings.app_filter.clear();
mSettings.socks5_enabled = false;
mSettings.tls_decryption = false;
mSettings.root_capture = false;
Expand Down Expand Up @@ -406,14 +407,29 @@ else if(mSettings.dump_mode == Prefs.DumpMode.PCAP_FILE) {
mDecryptionList = null;

if ((mSettings.app_filter != null) && (!mSettings.app_filter.isEmpty())) {
try {
app_filter_uid = Utils.getPackageUid(getPackageManager(), mSettings.app_filter, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
app_filter_uid = -1;
ArrayList<Integer> uids = new ArrayList<>();

for (String package_name: mSettings.app_filter) {
int uid;

try {
uid = Utils.getPackageUid(getPackageManager(), package_name, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
continue;
}

uids.add(uid);
}

// populate the array only with resolved UIDs
mAppFilterUids = new int[uids.size()];

int i = 0;
for (Integer uid: uids)
mAppFilterUids[i++] = uid;
} else
app_filter_uid = -1;
mAppFilterUids = new int[0];

mMalwareDetectionEnabled = Prefs.isMalwareDetectionEnabled(this, mPrefs);
mFirewallEnabled = Prefs.isFirewallEnabled(this, mPrefs);
Expand Down Expand Up @@ -458,7 +474,8 @@ else if(mSettings.dump_mode == Prefs.DumpMode.PCAP_FILE) {
// NOTE: the API requires a package name, however it is converted to a UID
// (see Vpn.java addUserToRanges). This means that vpn routing happens on a UID basis,
// not on a package-name basis!
builder.addAllowedApplication(mSettings.app_filter);
for (String package_name: mSettings.app_filter)
builder.addAllowedApplication(package_name);
} catch (PackageManager.NameNotFoundException e) {
String msg = String.format(getResources().getString(R.string.app_not_found), mSettings.app_filter);
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
Expand Down Expand Up @@ -958,7 +975,7 @@ private String getIfname(int ifidx) {
return rv;
}

public static String getAppFilter() {
public static Set<String> getAppFilter() {
return((INSTANCE != null) ? INSTANCE.mSettings.app_filter : null);
}

Expand Down Expand Up @@ -1291,7 +1308,7 @@ public String getDnsServer() {

public int isPcapngEnabled() { return(mSettings.pcapng_format ? 1 : 0); }

public int getAppFilterUid() { return(app_filter_uid); }
public int[] getAppFilterUids() { return(mAppFilterUids); }

public int getMitmAddonUid() {
return MitmAddon.getUid(this);
Expand All @@ -1309,7 +1326,7 @@ public int getMitmAddonUid() {

public int getVpnMTU() { return VPN_MTU; }

public int blockQuick() { return(mSettings.block_quic ? 1 : 0); }
public int getBlockQuickMode() { return mSettings.block_quic_mode.ordinal(); }

// returns 1 if dumpPcapData should be called
public int pcapDumpEnabled() {
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/java/com/emanuelef/remote_capture/HTTPReassembly.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class HTTPReassembly {
private boolean mChunkedEncoding;
private ContentEncoding mContentEncoding;
private String mContentType;
private String mPath;
private int mContentLength;
private int mHeadersSize;
private final ArrayList<PayloadChunk> mHeaders = new ArrayList<>();
Expand Down Expand Up @@ -68,6 +69,7 @@ private void reset() {
mChunkedEncoding = false;
mContentLength = -1;
mContentType = null;
mPath = null;
mHeadersSize = 0;
mHeaders.clear();
mBody.clear();
Expand Down Expand Up @@ -100,10 +102,30 @@ public void handleChunk(PayloadChunk chunk) {
// Reading the HTTP headers
int headers_end = Utils.getEndOfHTTPHeaders(payload);
int headers_size = (headers_end == 0) ? payload.length : headers_end;
boolean is_first_line = (mHeadersSize == 0);
mHeadersSize += headers_size;

try(BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(payload, 0, headers_size)))) {
String line = reader.readLine();

if (is_first_line && (line != null)) {
if (line.startsWith("GET ") || line.startsWith("POST ")
|| line.startsWith("HEAD ") || line.startsWith("PUT ")) {
int first_space = line.indexOf(' ');
int second_space = line.indexOf(' ', first_space + 1);

if ((first_space > 0) && (second_space > 0)) {
mPath = line.substring(first_space + 1, second_space);

int query_start = mPath.indexOf('?');
if (query_start >= 0)
mPath = mPath.substring(0, query_start);

log_d("Path: " + mPath);
}
}
}

while((line != null) && (line.length() > 0)) {
line = line.toLowerCase();
//log_d("[HEADER] " + line);
Expand Down Expand Up @@ -256,6 +278,7 @@ public void handleChunk(PayloadChunk chunk) {
to_add.type = PayloadChunk.ChunkType.RAW;

to_add.contentType = mContentType;
to_add.path = mPath;
mListener.onChunkReassembled(to_add);
reset(); // mReadingHeaders = true
}
Expand Down
34 changes: 30 additions & 4 deletions app/src/main/java/com/emanuelef/remote_capture/MitmAddon.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2022 - Emanuele Faranda
* Copyright 2022-24 - Emanuele Faranda
*/

package com.emanuelef.remote_capture;
Expand All @@ -34,6 +34,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.RemoteException;

import androidx.annotation.NonNull;
Expand All @@ -48,8 +49,8 @@
import java.lang.ref.WeakReference;

public class MitmAddon {
public static final long PACKAGE_VERSION_CODE = 16;
public static final String PACKAGE_VERSION_NAME = "v0.16";
public static final long PACKAGE_VERSION_CODE = 18;
public static final String PACKAGE_VERSION_NAME = "v1.1";
public static final String REPOSITORY = "https://github.com/emanuele-f/PCAPdroid-mitm";
private static final String TAG = "MitmAddon";
private final Context mContext;
Expand Down Expand Up @@ -193,7 +194,8 @@ public boolean connect(int extra_flags) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(MitmAPI.PACKAGE_NAME, MitmAPI.MITM_SERVICE));

if(!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE | extra_flags)) {
if(!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE |
Context.BIND_ALLOW_ACTIVITY_STARTS | extra_flags)) {
try {
mContext.unbindService(mConnection);
} catch (IllegalArgumentException ignored) {
Expand Down Expand Up @@ -295,4 +297,28 @@ public boolean stopProxy() {
return false;
}
}

// NOTE: doze could be disabled by PCAPdroid itself, however this is moved to the addon to avoid
// any issues with the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Google Play policies
public boolean disableDoze() {
if(mService == null)
return false;

Log.i(TAG, "Send disable doze");
Message msg = Message.obtain(null, MitmAPI.MSG_DISABLE_DOZE);
try {
mService.send(msg);
return true;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}

public static boolean isDozeEnabled(Context context) {
final PowerManager manager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) && (manager != null)
&& !manager.isIgnoringBatteryOptimizations(MitmAPI.PACKAGE_NAME);
}
}
11 changes: 8 additions & 3 deletions app/src/main/java/com/emanuelef/remote_capture/MitmReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2022 - Emanuele Faranda
* Copyright 2022-24 - Emanuele Faranda
*/

package com.emanuelef.remote_capture;
Expand Down Expand Up @@ -109,7 +109,7 @@ private static class PendingMessage {
type = _type;
msg = _msg;
port = _port;
pendingSince = SystemClock.uptimeMillis();
pendingSince = SystemClock.elapsedRealtime();
when = _now;
}
}
Expand Down Expand Up @@ -331,7 +331,7 @@ private void handleMessage(ConnectionDescriptor conn, MsgType type, byte[] messa
private synchronized void addPendingMessage(PendingMessage pending) {
// Purge unresolved connections (should not happen, just in case)
if(mPendingMessages.size() > 32) {
long now = SystemClock.uptimeMillis();
long now = SystemClock.elapsedRealtime();

for(int i = mPendingMessages.size()-1; i>=0; i--) {
ArrayList<PendingMessage> pp = mPendingMessages.valueAt(i);
Expand Down Expand Up @@ -483,6 +483,11 @@ public void onMitmGetCaCertificateResult(@Nullable String ca_pem) {
return;
}

if (MitmAddon.isDozeEnabled(mContext)) {
Utils.showToastLong(mContext, R.string.mitm_doze_notice);
mAddon.disableDoze();
}

if(mThread != null)
mThread.interrupt();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with PCAPdroid. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2020-21 - Emanuele Faranda
* Copyright 2020-24 - Emanuele Faranda
*/

package com.emanuelef.remote_capture.activities;
Expand Down Expand Up @@ -55,6 +55,7 @@
import com.emanuelef.remote_capture.Billing;
import com.emanuelef.remote_capture.CaptureService;
import com.emanuelef.remote_capture.Log;
import com.emanuelef.remote_capture.MitmAddon;
import com.emanuelef.remote_capture.R;
import com.emanuelef.remote_capture.Utils;
import com.emanuelef.remote_capture.model.Prefs;
Expand Down Expand Up @@ -147,6 +148,7 @@ public boolean onMenuItemSelected(MenuItem item) {
String deviceInfo = Utils.getBuildInfo(this) + "\n\n" +
Prefs.asString(this);

// Private DNS
Utils.PrivateDnsMode dns_mode = CaptureService.getPrivateDnsMode();
if(dns_mode == null) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Expand All @@ -164,6 +166,9 @@ public boolean onMenuItemSelected(MenuItem item) {
if(dns_mode != null)
deviceInfo += "\n" + "PrivateDnsMode: " + dns_mode;

// Mitm doze
deviceInfo += "\n" + "MitmBatteryOptimized: " + ((MitmAddon.isInstalled(this) && MitmAddon.isDozeEnabled(this)) ? "true" : "false");

LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.scrollable_dialog, null);
((TextView)view.findViewById(R.id.text)).setText(deviceInfo);
Expand Down Expand Up @@ -285,7 +290,7 @@ private void showQrCode(View dialog, String instId) {
return;
}
int timeout_ms = Integer.parseInt(timeout_s) * 1000;
long deadline = SystemClock.uptimeMillis() + timeout_ms;
long deadline = SystemClock.elapsedRealtime() + timeout_ms;
Log.d(TAG, "QR request_id=" + qr_req_id + ", timeout=" + timeout_ms + " ms");

// Step 2: generate QR code
Expand Down Expand Up @@ -353,7 +358,7 @@ private void onQrRequestReady(View dialog, Bitmap qrcode, long deadline) {
View qrLoading = dialog.findViewById(R.id.qr_code_loading);
View qrInfo = dialog.findViewById(R.id.qr_info_text);

mQrStartTime = SystemClock.uptimeMillis();
mQrStartTime = SystemClock.elapsedRealtime();
mQrDeadline = deadline;
updateQrProgress(dialog);

Expand All @@ -369,7 +374,7 @@ private void updateQrProgress(View dialog) {
return;

long interval = mQrDeadline - mQrStartTime;
int progress = Math.min((int)((SystemClock.uptimeMillis() - mQrStartTime) * 100 / interval), 100);
int progress = Math.min((int)((SystemClock.elapsedRealtime() - mQrStartTime) * 100 / interval), 100);
qrProgress.setProgress(100 - progress);

mHandler.postDelayed(() -> updateQrProgress(dialog), 1000);
Expand Down
Loading

0 comments on commit f102a2d

Please sign in to comment.