Skip to content

Commit

Permalink
Read PCAPdroid extensions metadata from Pcapng
Browse files Browse the repository at this point in the history
A PCAP/Pcapng reader has been implemented to support parsing the
PCAPdroid extensions metadata. This allows displaying a number of
information in the UI when loading from a Pcapng file, in particular:

- when the dump was generated with root, show the capture interface
  name
- show the UID (app) related to a given connection
- if the dump contains UIDs of uninstalled apps, show the
  original package name and app name

Closes #479
  • Loading branch information
emanuele-f committed Jan 11, 2025
1 parent e5259ad commit 0f47d37
Show file tree
Hide file tree
Showing 21 changed files with 899 additions and 199 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local.properties
.DS_Store
build/
captures/
pcap/
.externalNativeBuild
.cxx
app/release/
Expand Down
36 changes: 36 additions & 0 deletions app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.util.ArrayMap;
import android.util.SparseArray;

import com.emanuelef.remote_capture.interfaces.DrawableLoader;
Expand All @@ -37,6 +38,8 @@

public class AppsResolver {
private static final String TAG = "AppsResolver";
private static final SparseArray<AppDescriptor> mMappedUids = new SparseArray<>();
private static final ArrayMap<String, AppDescriptor> mMappedPackages = new ArrayMap<>();
private final SparseArray<AppDescriptor> mApps;
private final PackageManager mPm;
private final Context mContext;
Expand Down Expand Up @@ -90,10 +93,35 @@ private void initVirtualApps() {
virtualIconLoader,"nobody", 9999, true));
}

public synchronized static void clearMappedApps() {
mMappedUids.clear();
mMappedPackages.clear();
}

// Map the uid to the given package_name and app_name
// This is need for apps which are not installed in this device
public synchronized static void addMappedApp(int uid, String packageName, String appName) {
AppDescriptor dsc = new AppDescriptor(appName, null, packageName, uid, false);
mMappedUids.put(uid, dsc);
mMappedPackages.put(packageName, dsc);
}

private synchronized static AppDescriptor getMappedApp(int uid) {
return mMappedUids.get(uid);
}

private synchronized static AppDescriptor getMappedApp(String packageName) {
return mMappedPackages.get(packageName);
}

// Get the AppDescriptor corresponding to the given package name
// No caching occurs. Virtual apps cannot be used.
// This is public to provide a fast resolution alternative to getAppByPackage
public static AppDescriptor resolveInstalledApp(PackageManager pm, String packageName, int pm_flags, boolean warn_not_found) {
AppDescriptor dsc = getMappedApp(packageName);
if (dsc != null)
return dsc;

PackageInfo pinfo;

try {
Expand All @@ -113,6 +141,10 @@ public static AppDescriptor resolveInstalledApp(PackageManager pm, String packag

@SuppressLint("DiscouragedPrivateApi")
public @Nullable AppDescriptor getAppByUid(int uid, int pm_flags) {
AppDescriptor dsc = getMappedApp(uid);
if (dsc != null)
return dsc;

AppDescriptor app = mApps.get(uid);
if(app != null)
return app;
Expand Down Expand Up @@ -180,6 +212,10 @@ public static AppDescriptor resolveInstalledApp(PackageManager pm, String packag
/* Lookup a UID by package name (including virtual apps).
* UID_NO_FILTER is returned if no match is found. */
public int getUid(String package_name) {
AppDescriptor dsc = getMappedApp(package_name);
if (dsc != null)
return dsc.getUid();

if(!package_name.contains(".")) {
// This is a virtual app
for(int i=0; i<mApps.size(); i++) {
Expand Down
22 changes: 19 additions & 3 deletions app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ protected void attachBaseContext(Context base) {
@Override
public void onCreate() {
Log.d(CaptureService.TAG, "onCreate");
AppsResolver.clearMappedApps();
nativeAppsResolver = new AppsResolver(this);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mSettings = new CaptureSettings(this, mPrefs); // initialize to prevent NULL pointer exceptions in methods (e.g. isRootCapture)
Expand Down Expand Up @@ -1484,6 +1485,18 @@ public String getPackageNameByUid(int uid) {
return dsc.getPackageName();
}

public void loadUidMapping(int uid, String package_name, String app_name) {
if (uid < 0)
return;

AppDescriptor dsc = nativeAppsResolver.getAppByUid(uid, 0);

if ((dsc == null) || !dsc.getPackageName().equals(package_name)) {
// This uid corresponds to a different app than the one on the Pcapng
AppsResolver.addMappedApp(uid, package_name, app_name);
}
}

/* Exports a PCAP data chunk */
public void dumpPcapData(byte[] data) {
if((mDumper != null) && (data.length > 0)) {
Expand Down Expand Up @@ -1513,7 +1526,10 @@ public void reportError(String msg) {

// Try to get a translated string (see errors.h)
switch (msg) {
case "Invalid PCAP file":
case "Unsupported PCAP/Pcapng file":
err = getString(R.string.unsupported_pcap_file);
break;
case "Invalid PCAP/Pcapng file":
err = getString(R.string.invalid_pcap_file);
break;
case "Could not open the capture interface":
Expand All @@ -1522,7 +1538,7 @@ public void reportError(String msg) {
case "Unsupported datalink":
err = getString(R.string.unsupported_pcap_datalink);
break;
case "The specified PCAP file does not exist":
case "The specified PCAP/Pcapng file does not exist":
err = getString(R.string.pcap_file_not_exists);
break;
case "pcapd daemon start failure":
Expand All @@ -1533,7 +1549,7 @@ public void reportError(String msg) {
if(mSettings.root_capture)
err = getString(R.string.root_capture_start_failed);
break;
case "PCAP read error":
case "PCAP/Pcapng read error":
err = getString(R.string.pcap_read_error);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public AppsStatsAdapter(Context context) {
mContext = context;
mApps = new AppsResolver(context);
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mUnknownIcon = ContextCompat.getDrawable(mContext, android.R.drawable.ic_menu_help);
mUnknownIcon = ContextCompat.getDrawable(mContext, R.drawable.ic_image);
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mBlocklist = PCAPdroid.getInstance().getBlocklist();
mWhitelist = PCAPdroid.getInstance().getFirewallWhitelist();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
Expand All @@ -41,6 +42,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.MenuProvider;
import androidx.core.view.ViewCompat;
Expand Down Expand Up @@ -116,7 +118,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat

((TextView)view.findViewById(R.id.uid)).setText(Utils.formatInteger(ctx, dsc.getUid()));
((TextView)view.findViewById(R.id.name)).setText(dsc.getName());
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(dsc.getIcon());
Drawable icon = dsc.getIcon();
if (icon == null)
icon = ContextCompat.getDrawable(ctx, R.drawable.ic_image);
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(icon);

mPinfo = dsc.getPackageInfo();

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/jni/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ project(core)
add_library(capture SHARED
pcapdroid.c
capture_vpn.c
capture_libpcap.c
capture_pcap.c
ip_lru.c
ndpi_config.c
crc32.c
blacklist.c
pcap_dump.c
pcap_reader.c
log_writer.c
port_map.c
jni_impl.c)
Expand Down
Loading

0 comments on commit 0f47d37

Please sign in to comment.