├── .gitignore ├── .idea ├── encodings.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── mingxiangChen │ │ └── droidnet │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── litepal.xml │ ├── java │ │ └── com │ │ │ └── mingxiangChen │ │ │ └── droidnet │ │ │ ├── App.java │ │ │ ├── AppService.java │ │ │ ├── SwitcherListener.java │ │ │ ├── activity │ │ │ ├── MainActivity.java │ │ │ ├── PackageListActivity.java │ │ │ ├── PackageShowInfo.java │ │ │ ├── PackageShowInfoAdapter.java │ │ │ └── PacketDetailActivity.java │ │ │ ├── dialog │ │ │ ├── BaseDialog.java │ │ │ ├── EditRuleDialog.java │ │ │ ├── NewRuleDialog.java │ │ │ └── TableChanged.java │ │ │ ├── fragment │ │ │ ├── AddPacketHandler.java │ │ │ ├── BaseFragment.java │ │ │ ├── CaptureFragment.java │ │ │ ├── FirewallFragment.java │ │ │ ├── PacketCapturedListener.java │ │ │ ├── PacketShowInfo.java │ │ │ ├── PacketShowInfoAdapter.java │ │ │ └── ToastFirewallHandler.java │ │ │ ├── gateway │ │ │ ├── DroidNetVirtualGateway.java │ │ │ ├── DroidNetVirtualGatewayFactory.java │ │ │ ├── FirewallVirtualGateway.java │ │ │ ├── FirewallVirtualGatewayFactory.java │ │ │ ├── RawTcpVirtualGateway.java │ │ │ └── RawTcpVirtualGatewayFactory.java │ │ │ ├── interceptor │ │ │ ├── CaptureRawInterceptor.java │ │ │ ├── CaptureRawInterceptorFactory.java │ │ │ ├── FirewallInterceptor.java │ │ │ ├── FirewallInterceptorFactory.java │ │ │ ├── HttpUrlPrintInterceptor.java │ │ │ └── RawTcpPrintInterceptor.java │ │ │ ├── table │ │ │ └── InterceptRules.java │ │ │ └── util │ │ │ └── ThreadProxy.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── settings.jpg │ │ ├── start.png │ │ └── stop.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_package_list.xml │ │ ├── activity_packet_detail.xml │ │ ├── dialog_edit_rule.xml │ │ ├── dialog_new_rule.xml │ │ ├── fragment_capture.xml │ │ ├── fragment_firewall.xml │ │ ├── item_package.xml │ │ └── item_packet.xml │ │ ├── menu │ │ └── toolbar.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mingxiangChen │ └── droidnet │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── netbare-core ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── github │ │ └── megatronking │ │ └── netbare │ │ ├── NetBare.java │ │ ├── NetBareConfig.java │ │ ├── NetBareListener.java │ │ ├── NetBareLog.java │ │ ├── NetBareService.java │ │ ├── NetBareThread.java │ │ ├── NetBareUtils.java │ │ ├── NetBareVirtualGateway.java │ │ ├── NetBareXLog.java │ │ ├── gateway │ │ ├── AbstractRequestChain.java │ │ ├── AbstractResponseChain.java │ │ ├── DefaultVirtualGateway.java │ │ ├── DefaultVirtualGatewayFactory.java │ │ ├── IndexedInterceptor.java │ │ ├── Interceptor.java │ │ ├── InterceptorChain.java │ │ ├── InterceptorFactory.java │ │ ├── PendingIndexedInterceptor.java │ │ ├── Request.java │ │ ├── RequestChain.java │ │ ├── Response.java │ │ ├── ResponseChain.java │ │ ├── SSLCodecInterceptor.java │ │ ├── SSLRefluxInterceptor.java │ │ ├── SessionTunnelFlow.java │ │ ├── SpecVirtualGateway.java │ │ ├── TunnelFlow.java │ │ ├── VirtualGateway.java │ │ └── VirtualGatewayFactory.java │ │ ├── http │ │ ├── ContainerHttpInterceptor.java │ │ ├── Http2SniffInterceptor.java │ │ ├── HttpHeaderParseInterceptor.java │ │ ├── HttpHeaderSeparateInterceptor.java │ │ ├── HttpHeaderSniffInterceptor.java │ │ ├── HttpId.java │ │ ├── HttpIndexedInterceptor.java │ │ ├── HttpInterceptor.java │ │ ├── HttpInterceptorFactory.java │ │ ├── HttpInterceptorsFactory.java │ │ ├── HttpMethod.java │ │ ├── HttpMultiplexInterceptor.java │ │ ├── HttpPendingIndexedInterceptor.java │ │ ├── HttpProtocol.java │ │ ├── HttpRequest.java │ │ ├── HttpRequestChain.java │ │ ├── HttpResponse.java │ │ ├── HttpResponseChain.java │ │ ├── HttpSSLCodecInterceptor.java │ │ ├── HttpSSLRefluxInterceptor.java │ │ ├── HttpSSLRequestCodec.java │ │ ├── HttpSSLResponseCodec.java │ │ ├── HttpSession.java │ │ ├── HttpSessionFactory.java │ │ ├── HttpSniffInterceptor.java │ │ ├── HttpVirtualGateway.java │ │ ├── HttpVirtualGatewayFactory.java │ │ ├── HttpZygoteRequest.java │ │ └── HttpZygoteResponse.java │ │ ├── http2 │ │ ├── DecodeCallback.java │ │ ├── EncodeCallback.java │ │ ├── ErrorCode.java │ │ ├── FrameType.java │ │ ├── Hpack.java │ │ ├── Http2.java │ │ ├── Http2DecodeInterceptor.java │ │ ├── Http2EncodeInterceptor.java │ │ ├── Http2Settings.java │ │ ├── Http2Stream.java │ │ ├── Http2Updater.java │ │ └── Huffman.java │ │ ├── ip │ │ ├── Header.java │ │ ├── IcmpHeader.java │ │ ├── IpAddress.java │ │ ├── IpHeader.java │ │ ├── Protocol.java │ │ ├── TcpHeader.java │ │ └── UdpHeader.java │ │ ├── net │ │ ├── DumpCallback.java │ │ ├── Net.java │ │ ├── Session.java │ │ ├── SessionProvider.java │ │ ├── UidDumper.java │ │ └── UidProvider.java │ │ ├── proxy │ │ ├── BaseProxyServer.java │ │ ├── IcmpProxyServerForwarder.java │ │ ├── ProxyServer.java │ │ ├── ProxyServerForwarder.java │ │ ├── TcpProxyServer.java │ │ ├── TcpProxyServerForwarder.java │ │ ├── UdpProxyServer.java │ │ └── UdpProxyServerForwarder.java │ │ ├── ssl │ │ ├── CertificateGenerator.java │ │ ├── CertificateInstallActivity.java │ │ ├── JKS.java │ │ ├── SSLCodec.java │ │ ├── SSLEngineFactory.java │ │ ├── SSLKeyManagerProvider.java │ │ ├── SSLRefluxCallback.java │ │ ├── SSLRequestCodec.java │ │ ├── SSLResponseCodec.java │ │ ├── SSLTrustManagerProvider.java │ │ └── SSLUtils.java │ │ ├── tcp │ │ └── TcpVirtualGateway.java │ │ ├── tunnel │ │ ├── ConnectionShutdownException.java │ │ ├── NioCallback.java │ │ ├── NioTunnel.java │ │ ├── TcpProxyTunnel.java │ │ ├── TcpRemoteTunnel.java │ │ ├── TcpTunnel.java │ │ ├── TcpVATunnel.java │ │ ├── Tunnel.java │ │ ├── UdpRemoteTunnel.java │ │ ├── UdpTunnel.java │ │ ├── UdpVATunnel.java │ │ └── VirtualGatewayTunnel.java │ │ ├── udp │ │ └── UdpVirtualGateway.java │ │ └── ws │ │ ├── WebSocketCallback.java │ │ ├── WebSocketProtocol.java │ │ └── WebSocketReader.java │ └── res │ └── values │ └── styles.xml ├── netbare-injector ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── github │ └── megatronking │ └── netbare │ ├── http │ ├── Cookie.java │ ├── HttpBody.java │ ├── HttpHeaderPart.java │ ├── HttpInjectInterceptor.java │ ├── HttpRawBody.java │ ├── HttpRequestHeaderPart.java │ ├── HttpRequestInjectorCallback.java │ ├── HttpResponseHeaderPart.java │ └── HttpResponseInjectorCallback.java │ ├── injector │ ├── BlockedHttpInjector.java │ ├── HttpInjector.java │ ├── InjectorCallback.java │ └── SimpleHttpInjector.java │ ├── io │ ├── ByteBufferInputStream.java │ └── HttpBodyInputStream.java │ ├── stream │ ├── BufferStream.java │ ├── ByteStream.java │ ├── Stream.java │ ├── StringStream.java │ └── TinyFileStream.java │ └── utils │ └── CaseInsensitiveLinkedMap.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.mingxiangChen.droidnet" 7 | minSdkVersion 24 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:28.0.0' 24 | implementation 'com.android.support:design:28.0.0' 25 | implementation 'com.android.support:recyclerview-v7:28.0.0' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 29 | implementation 'me.weishu:free_reflection:1.2.0' 30 | 31 | // NetBare libraries 32 | implementation project(':netbare-core') 33 | implementation project(':netbare-injector') 34 | 35 | implementation 'org.litepal.android:java:3.0.0' 36 | 37 | implementation 'com.github.huangyanbin:SmartTable:1.7.1' 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/mingxiangChen/droidnet/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.mingxiangChen.droidnet", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/assets/litepal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 22 | 23 | 24 | 34 | 35 | 36 | 37 | 38 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/AppService.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.graphics.BitmapFactory; 10 | import android.os.Build; 11 | import android.support.annotation.NonNull; 12 | import android.support.v4.app.NotificationCompat; 13 | 14 | import com.github.megatronking.netbare.NetBareService; 15 | import com.mingxiangChen.droidnet.activity.MainActivity; 16 | 17 | public class AppService extends NetBareService { 18 | 19 | private static String CHANNEL_ID = "com.mingxiangChen.droidnet.NOTIFICATION_CHANNEL_ID"; 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 25 | NotificationManager notificationManager = 26 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 27 | if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) { 28 | notificationManager.createNotificationChannel(new NotificationChannel(CHANNEL_ID, 29 | getString(R.string.app_name), NotificationManager.IMPORTANCE_LOW)); 30 | } 31 | } 32 | } 33 | 34 | @Override 35 | protected int notificationId() { 36 | return 100; 37 | } 38 | 39 | @NonNull 40 | @Override 41 | protected Notification createNotification() { 42 | Intent intent = new Intent(this, MainActivity.class); 43 | intent.addCategory(Intent.CATEGORY_LAUNCHER); 44 | intent.setAction(Intent.ACTION_MAIN); 45 | PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 46 | PendingIntent.FLAG_UPDATE_CURRENT); 47 | return new NotificationCompat.Builder(this, CHANNEL_ID) 48 | .setSmallIcon(R.drawable.ic_launcher_foreground) 49 | .setContentTitle(getString(R.string.app_name)) 50 | .setContentText(getString(R.string.app_name)) 51 | .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) 52 | .setOngoing(true) 53 | .setContentIntent(pendingIntent) 54 | .build(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/SwitcherListener.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet; 2 | 3 | /** 4 | * Interface definition for a {@link com.github.megatronking.netbare.gateway.VirtualGateway} that 5 | * monitors user operations on DroidNet. 6 | * 7 | * @author RSmxchen 8 | * @since 2019-05-01 15:41 9 | */ 10 | public interface SwitcherListener { 11 | 12 | /** 13 | * Callback method to be invoked when the user clicks capture start button. 14 | */ 15 | void captureOn(); 16 | 17 | /** 18 | * Callback method to be invoked when the user clicks capture stop button. 19 | */ 20 | void captureOff(); 21 | 22 | /** 23 | * Callback method to be invoked when the user clicks firewall start button. 24 | */ 25 | void firewallOn(); 26 | 27 | /** 28 | * Callback method to be invoked when the user clicks firewall stop button. 29 | */ 30 | void firewallOff(); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/activity/PackageListActivity.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.ProgressBar; 10 | 11 | import com.mingxiangChen.droidnet.App; 12 | import com.mingxiangChen.droidnet.R; 13 | import com.mingxiangChen.droidnet.util.ThreadProxy; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link Activity} shows all the packages in device and let the user choose one. Reference the 19 | * NetworkPacketCapture project. 20 | * 21 | * @author RSmxchen 22 | * @since 2019-05-05 22:09 23 | */ 24 | public class PackageListActivity extends Activity { 25 | 26 | private RecyclerView mRecyclerView; 27 | private ProgressBar mProgressBar; 28 | private List mPackageList; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_package_list); 34 | 35 | // 将耗时的getPackageShowInfo()方法扔进线程池里,别阻塞UI线程 36 | mRecyclerView = findViewById(R.id.recyclerView_package_list); 37 | mProgressBar = findViewById(R.id.progressBar_package_list); 38 | ThreadProxy.getInstance().execute(new Runnable() { 39 | 40 | private PackageShowInfoAdapter adapter; 41 | 42 | @Override 43 | public void run() { 44 | mPackageList = PackageShowInfo.getPackageShowInfo(App.getInstance()); 45 | adapter = new PackageShowInfoAdapter(mPackageList, PackageListActivity.this); 46 | runOnUiThread(new Runnable() { 47 | @Override 48 | public void run() { 49 | LinearLayoutManager layoutManager = new LinearLayoutManager(PackageListActivity.this); 50 | mRecyclerView.setLayoutManager(layoutManager); 51 | mRecyclerView.setAdapter(adapter); 52 | mProgressBar.setVisibility(View.GONE); 53 | } 54 | }); 55 | } 56 | }); 57 | } 58 | 59 | @Override 60 | public void onBackPressed() { 61 | Intent intent = new Intent(); 62 | setResult(RESULT_CANCELED, intent); 63 | finish(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/activity/PackageShowInfoAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.support.annotation.NonNull; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | import android.widget.Toast; 13 | 14 | import com.mingxiangChen.droidnet.R; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * The adapter class for recyclerView in {@link PackageListActivity}. 20 | * 21 | * @author RXmxchen 22 | * @since 2019-05-05 23 | */ 24 | public class PackageShowInfoAdapter extends 25 | RecyclerView.Adapter { 26 | 27 | private List mPackageShowInfos; 28 | private Activity mActivity; // 持有Activity的引用,处理recyclerView所在Activity的intent数据传递 29 | 30 | static class ViewHolder extends RecyclerView.ViewHolder { 31 | ImageView packageIcon; 32 | TextView packageName; 33 | View packageView; 34 | 35 | public ViewHolder(View view) { 36 | super(view); 37 | packageIcon = view.findViewById(R.id.img_package); 38 | packageName = view.findViewById(R.id.txt_packageName); 39 | packageView = view; 40 | } 41 | } 42 | 43 | public PackageShowInfoAdapter(List packageShowInfos, Activity activity) { 44 | this.mPackageShowInfos = packageShowInfos; 45 | this.mActivity = activity; 46 | } 47 | 48 | @NonNull 49 | @Override 50 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 51 | View view = LayoutInflater.from(parent.getContext()) 52 | .inflate(R.layout.item_package, parent, false); 53 | final ViewHolder holder = new ViewHolder(view); 54 | holder.packageView.setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View view) { 57 | int position = holder.getAdapterPosition(); 58 | PackageShowInfo pkgInfo = mPackageShowInfos.get(position); 59 | Intent intent = new Intent(); 60 | intent.putExtra("selected_package_name", pkgInfo.packageName); 61 | mActivity.setResult(Activity.RESULT_OK, intent); 62 | mActivity.finish(); 63 | } 64 | }); 65 | return holder; 66 | } 67 | 68 | @Override 69 | public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { 70 | PackageShowInfo info = mPackageShowInfos.get(position); 71 | viewHolder.packageIcon.setImageDrawable(info.packageIcon); 72 | viewHolder.packageName.setText(info.appName); 73 | } 74 | 75 | @Override 76 | public int getItemCount() { 77 | return mPackageShowInfos.size(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/activity/PacketDetailActivity.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.widget.TextView; 7 | 8 | import com.mingxiangChen.droidnet.R; 9 | 10 | /** 11 | * An activity that displays the packet's byte-stream in ascii-encoding. 12 | * 13 | * @author RSmxchen 14 | * @since 2019-05-14 16:53 15 | */ 16 | public class PacketDetailActivity extends Activity { 17 | 18 | private TextView mPacketDetail; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_packet_detail); 24 | 25 | mPacketDetail = findViewById(R.id.txt_packet_detail); 26 | 27 | Intent intent = getIntent(); 28 | mPacketDetail.setText(intent.getStringExtra("packetDetail")); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/dialog/BaseDialog.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.dialog; 2 | 3 | import android.app.Activity; 4 | import android.app.Dialog; 5 | import android.content.Context; 6 | import android.os.Bundle; 7 | import android.support.v4.app.Fragment; 8 | import android.view.Display; 9 | import android.view.Gravity; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | 13 | /** 14 | * A base class extends {@link Dialog} designed for loading self-defined layout, inspired by the 15 | * CSDN blog @see MyDialog1. 16 | * Create a class extending BaseDialog and put its layout and listenedItem in the constructor. 17 | * 18 | * @author RSmxchen 19 | * @since 2019-05-05 15:27 20 | */ 21 | public class BaseDialog extends Dialog { 22 | 23 | private Context mContext; 24 | private int mLayoutResID; 25 | private Fragment mParentFragment; 26 | 27 | public BaseDialog(Context context, int layoutResID, Fragment fragment) { 28 | super(context); 29 | this.mContext = context; 30 | this.mLayoutResID = layoutResID; 31 | this.mParentFragment = fragment; 32 | } 33 | 34 | public Context getmContext() { 35 | return mContext; 36 | } 37 | 38 | public Fragment getmParentFragment() { 39 | return mParentFragment; 40 | } 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(mLayoutResID); 46 | setCanceledOnTouchOutside(true); // 点击外部,Dialog消失 47 | 48 | Window dialogWindow = getWindow(); 49 | dialogWindow.setGravity(Gravity.CENTER); // 设置dialog显示居中 50 | WindowManager windowManager = ((Activity)mContext).getWindowManager(); 51 | Display display = windowManager.getDefaultDisplay(); 52 | WindowManager.LayoutParams lp = getWindow().getAttributes(); 53 | lp.width = display.getWidth()*7/8; // 设置dialog宽度为屏幕的7/8 54 | getWindow().setAttributes(lp); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/dialog/TableChanged.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.dialog; 2 | 3 | /** 4 | * A interface invoked when dialog operates the table 5 | * {@link com.mingxiangChen.droidnet.table.InterceptRules}. SmartTable calls the interface method to 6 | * update UI data. 7 | * 8 | * @author RSmxchen 9 | * @since 2019-05-09 16:40 10 | */ 11 | public interface TableChanged { 12 | void onTableChanged(); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/AddPacketHandler.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | 6 | /** 7 | * A handler designed for {@link com.mingxiangChen.droidnet.interceptor.CaptureRawInterceptor} thread 8 | * communicating with UI thread. 9 | * 10 | * @author RSmxchen 11 | * @since 2019-05-13 22:46 12 | */ 13 | public class AddPacketHandler extends Handler implements PacketCapturedListener { 14 | 15 | private PacketShowInfoAdapter adapter; 16 | 17 | public AddPacketHandler(PacketShowInfoAdapter adapter) { 18 | this.adapter = adapter; 19 | } 20 | 21 | @Override 22 | public void handleMessage(Message msg) { 23 | if (msg.obj instanceof PacketShowInfo) { 24 | adapter.addPacket((PacketShowInfo) msg.obj); 25 | } 26 | } 27 | 28 | @Override 29 | public void onPacketCaptured(PacketShowInfo info) { 30 | Message message = new Message(); 31 | message.obj = info; 32 | this.sendMessage(message); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | /** 11 | * I don't know how to explain now...just imitates the NetworkPacketCapture project. 12 | * 13 | * @author RSmxchen 14 | * @since 2019-05-04 13:49 15 | */ 16 | public abstract class BaseFragment extends Fragment { 17 | @Nullable 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { 20 | return inflater.inflate(getLayout(), container, false); 21 | } 22 | 23 | abstract int getLayout(); 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/CaptureFragment.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Message; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | import com.mingxiangChen.droidnet.App; 16 | import com.mingxiangChen.droidnet.R; 17 | 18 | import java.util.ArrayList; 19 | 20 | public class CaptureFragment extends BaseFragment { 21 | 22 | private RecyclerView mPacketRecyclerView; 23 | private PacketShowInfoAdapter mPacketShowInfoAdapter; 24 | 25 | private AddPacketHandler mHandler; 26 | 27 | @Override 28 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 29 | super.onViewCreated(view, savedInstanceState); 30 | 31 | mPacketRecyclerView = view.findViewById(R.id.recyclerView_packet_list); 32 | mPacketShowInfoAdapter = new PacketShowInfoAdapter(new ArrayList(), getActivity()); 33 | mHandler = new AddPacketHandler(mPacketShowInfoAdapter); 34 | App.getInstance().mDroidNetVirtualGatewayFactory.setPacketCaptureListener(mHandler); 35 | LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); 36 | mPacketRecyclerView.setLayoutManager(layoutManager); 37 | mPacketRecyclerView.setAdapter(mPacketShowInfoAdapter); 38 | } 39 | 40 | @Override 41 | int getLayout() { 42 | return R.layout.fragment_capture; 43 | } 44 | 45 | public PacketShowInfoAdapter getPacketShowInfoAdapter() { 46 | return mPacketShowInfoAdapter; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/PacketCapturedListener.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | /** 4 | * A callback which invoked when {@link com.mingxiangChen.droidnet.interceptor.CaptureRawInterceptor} 5 | * intercept() method captures a packet. Let the {@link CaptureFragment} know to refresh the recyclerView. 6 | * So the adapter of the recyclerView should implement this interface. 7 | * 8 | * @author RSmxchen 9 | * @since 2019-05-13 00:35 10 | */ 11 | public interface PacketCapturedListener { 12 | void onPacketCaptured(PacketShowInfo info); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/PacketShowInfo.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | import android.graphics.drawable.Drawable; 8 | 9 | import com.mingxiangChen.droidnet.R; 10 | 11 | /** 12 | * It contains the information of a packet captured by 13 | * {@link com.mingxiangChen.droidnet.interceptor.CaptureRawInterceptor}. 14 | * 15 | * @author RSmxchen 16 | * @since 2019-05-12 14:20 17 | */ 18 | public class PacketShowInfo { 19 | 20 | private Drawable appIcon; 21 | private String pkgName; 22 | private String protocol; 23 | private String session; 24 | private String packetSize; 25 | private String bufferInAscii; 26 | private ApplicationInfo applicationInfo; 27 | 28 | public PacketShowInfo(Context context, int uid) { 29 | PackageManager packageManager = context.getPackageManager(); 30 | try { 31 | PackageInfo packageInfo = packageManager.getPackageInfo(packageManager.getNameForUid(uid), 32 | PackageManager.MATCH_UNINSTALLED_PACKAGES); 33 | this.applicationInfo = packageInfo.applicationInfo; 34 | this.appIcon = applicationInfo.loadIcon(packageManager); 35 | this.pkgName = (String) applicationInfo.loadLabel(packageManager); 36 | } catch (PackageManager.NameNotFoundException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | public Drawable getAppIcon() { 42 | return appIcon; 43 | } 44 | 45 | public String getPkgName() { 46 | return pkgName; 47 | } 48 | 49 | public String getProtocol() { 50 | return protocol; 51 | } 52 | 53 | public void setProtocol(String protocol) { 54 | this.protocol = protocol; 55 | } 56 | 57 | public String getSession() { 58 | return session; 59 | } 60 | 61 | public void setSession(String session) { 62 | this.session = session; 63 | } 64 | 65 | public String getPacketSize() { 66 | return packetSize; 67 | } 68 | 69 | public void setPacketSize(String pakcetSize) { 70 | this.packetSize = pakcetSize; 71 | } 72 | 73 | public String getBufferInAscii() { 74 | return bufferInAscii; 75 | } 76 | 77 | public void setBufferInAscii(String bufferInAscii) { 78 | this.bufferInAscii = bufferInAscii; 79 | } 80 | 81 | public ApplicationInfo getApplicationInfo() { 82 | return applicationInfo; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/fragment/ToastFirewallHandler.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.widget.Toast; 7 | 8 | /** 9 | * A {@link Handler} designed for {@link com.mingxiangChen.droidnet.interceptor.FirewallInterceptor}, 10 | * which lets FirewallInterceptor show a interception toast in proxy server thread. 11 | * 12 | * @author RSmxchen 13 | * @since 2019-06-03 18:00 14 | */ 15 | public class ToastFirewallHandler extends Handler { 16 | 17 | private Context mContext; 18 | 19 | public void setContext(Context mContext) { 20 | this.mContext = mContext; 21 | } 22 | 23 | @Override 24 | public void handleMessage(Message msg) { 25 | String toastString = (String) msg.obj; 26 | Toast.makeText(mContext, toastString, Toast.LENGTH_SHORT).show(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/gateway/DroidNetVirtualGatewayFactory.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.gateway; 2 | 3 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 4 | import com.github.megatronking.netbare.gateway.Request; 5 | import com.github.megatronking.netbare.gateway.RequestChain; 6 | import com.github.megatronking.netbare.gateway.Response; 7 | import com.github.megatronking.netbare.gateway.ResponseChain; 8 | import com.github.megatronking.netbare.gateway.VirtualGateway; 9 | import com.github.megatronking.netbare.gateway.VirtualGatewayFactory; 10 | import com.github.megatronking.netbare.net.Session; 11 | import com.mingxiangChen.droidnet.fragment.PacketCapturedListener; 12 | import com.mingxiangChen.droidnet.fragment.ToastFirewallHandler; 13 | import com.mingxiangChen.droidnet.interceptor.CaptureRawInterceptor; 14 | import com.mingxiangChen.droidnet.interceptor.CaptureRawInterceptorFactory; 15 | import com.mingxiangChen.droidnet.interceptor.FirewallInterceptor; 16 | import com.mingxiangChen.droidnet.interceptor.FirewallInterceptorFactory; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | * A {@link VirtualGatewayFactory} constructs the instance of {@link DroidNetVirtualGateway}. 23 | * 24 | * @author RSmxchen 25 | * @since 2019-05-01 17:07 26 | */ 27 | public class DroidNetVirtualGatewayFactory implements VirtualGatewayFactory { 28 | 29 | private List> mFactories; 30 | 31 | public DroidNetVirtualGatewayFactory() { 32 | mFactories = new ArrayList<>(); 33 | CaptureRawInterceptorFactory captureRawInterceptorFactory = new CaptureRawInterceptorFactory(); 34 | mFactories.add(captureRawInterceptorFactory); 35 | FirewallInterceptorFactory firewallInterceptorFactory = new FirewallInterceptorFactory(); 36 | mFactories.add(firewallInterceptorFactory); 37 | } 38 | 39 | public void setPacketCaptureListener(PacketCapturedListener packetCaptureListener) { 40 | for (InterceptorFactory factory: mFactories) { 41 | if (factory instanceof CaptureRawInterceptorFactory) { 42 | ((CaptureRawInterceptorFactory) factory).setPacketCapturedListener(packetCaptureListener); 43 | } 44 | } 45 | } 46 | 47 | public void setToastFirewallHandler(ToastFirewallHandler handler) { 48 | for (InterceptorFactory factory: mFactories) { 49 | if (factory instanceof FirewallInterceptorFactory) { 50 | ((FirewallInterceptorFactory) factory).setHandler(handler); 51 | } 52 | } 53 | } 54 | 55 | @Override 56 | public VirtualGateway create(Session session, Request request, Response response) { 57 | return new DroidNetVirtualGateway(session, request, response, new ArrayList<>(mFactories)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/gateway/FirewallVirtualGateway.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.gateway; 2 | 3 | import com.github.megatronking.netbare.gateway.Interceptor; 4 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 5 | import com.github.megatronking.netbare.gateway.Request; 6 | import com.github.megatronking.netbare.gateway.RequestChain; 7 | import com.github.megatronking.netbare.gateway.Response; 8 | import com.github.megatronking.netbare.gateway.ResponseChain; 9 | import com.github.megatronking.netbare.gateway.VirtualGateway; 10 | import com.github.megatronking.netbare.net.Session; 11 | 12 | import java.io.IOException; 13 | import java.nio.ByteBuffer; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link VirtualGateway} provides firewall functions. 19 | * 20 | * @author RSmxchen 21 | * @since 2019-04-28 21:29 22 | */ 23 | public class FirewallVirtualGateway extends VirtualGateway { 24 | 25 | private final List> mInterceptors; 26 | 27 | public FirewallVirtualGateway(Session session, Request request, Response response, 28 | List> factories) { 29 | super(session, request, response); 30 | this.mInterceptors = new ArrayList<>(factories.size()); 31 | for (InterceptorFactory factory : factories) { 32 | mInterceptors.add(factory.create()); 33 | } 34 | } 35 | 36 | @Override 37 | public void onRequest(ByteBuffer buffer) throws IOException { 38 | new RequestChain(mRequest, mInterceptors).process(buffer); 39 | } 40 | 41 | @Override 42 | public void onResponse(ByteBuffer buffer) throws IOException { 43 | new ResponseChain(mResponse, mInterceptors).process(buffer); 44 | } 45 | 46 | @Override 47 | public void onRequestFinished() { 48 | for (Interceptor interceptor: mInterceptors) { 49 | interceptor.onRequestFinished(mRequest); 50 | } 51 | } 52 | 53 | @Override 54 | public void onResponseFinished() { 55 | for (Interceptor interceptor: mInterceptors) { 56 | interceptor.onResponseFinished(mResponse); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/gateway/FirewallVirtualGatewayFactory.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.gateway; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 6 | import com.github.megatronking.netbare.gateway.Request; 7 | import com.github.megatronking.netbare.gateway.RequestChain; 8 | import com.github.megatronking.netbare.gateway.Response; 9 | import com.github.megatronking.netbare.gateway.ResponseChain; 10 | import com.github.megatronking.netbare.gateway.VirtualGateway; 11 | import com.github.megatronking.netbare.gateway.VirtualGatewayFactory; 12 | import com.github.megatronking.netbare.net.Session; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link VirtualGatewayFactory} that produces the {@link FirewallVirtualGateway}. 19 | * 20 | * @author RSmxchen 21 | * @since 2019-04-28 21:50 22 | */ 23 | public class FirewallVirtualGatewayFactory implements VirtualGatewayFactory { 24 | 25 | private List> mFactories; 26 | 27 | public FirewallVirtualGatewayFactory(@NonNull List> factories) { 29 | this.mFactories = factories; 30 | } 31 | 32 | @Override 33 | public VirtualGateway create(Session session, Request request, Response response) { 34 | return new FirewallVirtualGateway(session, request, response, new ArrayList<>(mFactories)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/gateway/RawTcpVirtualGateway.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.gateway; 2 | 3 | import com.github.megatronking.netbare.gateway.Interceptor; 4 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 5 | import com.github.megatronking.netbare.gateway.Request; 6 | import com.github.megatronking.netbare.gateway.RequestChain; 7 | import com.github.megatronking.netbare.gateway.Response; 8 | import com.github.megatronking.netbare.gateway.ResponseChain; 9 | import com.github.megatronking.netbare.net.Session; 10 | import com.github.megatronking.netbare.tcp.TcpVirtualGateway; 11 | 12 | import java.io.IOException; 13 | import java.nio.ByteBuffer; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link TcpVirtualGateway} designed for showing Tcp data in ASCII. 19 | * 20 | * @author RSmxchen 21 | * @since 2019-04-27 13:50 22 | */ 23 | public class RawTcpVirtualGateway extends TcpVirtualGateway { 24 | 25 | private final List> mInterceptors; 26 | 27 | RawTcpVirtualGateway(Session session, Request request, Response response, 28 | List> factories) { 29 | super(session, request, response); 30 | this.mInterceptors = new ArrayList<>(factories.size()); 31 | for (InterceptorFactory factory : factories) { 32 | mInterceptors.add(factory.create()); 33 | } 34 | } 35 | 36 | @Override 37 | protected void onSpecRequest(ByteBuffer buffer) throws IOException { 38 | new RequestChain(mRequest, mInterceptors).process(buffer); 39 | } 40 | 41 | @Override 42 | protected void onSpecResponse(ByteBuffer buffer) throws IOException { 43 | new ResponseChain(mResponse, mInterceptors).process(buffer); 44 | } 45 | 46 | @Override 47 | protected void onSpecRequestFinished() { 48 | for (Interceptor interceptor: mInterceptors) { 49 | interceptor.onRequestFinished(mRequest); 50 | } 51 | } 52 | 53 | @Override 54 | protected void onSpecResponseFinished() { 55 | for (Interceptor interceptor: mInterceptors) { 56 | interceptor.onResponseFinished(mResponse); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/gateway/RawTcpVirtualGatewayFactory.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.gateway; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 6 | import com.github.megatronking.netbare.gateway.Request; 7 | import com.github.megatronking.netbare.gateway.RequestChain; 8 | import com.github.megatronking.netbare.gateway.Response; 9 | import com.github.megatronking.netbare.gateway.ResponseChain; 10 | import com.github.megatronking.netbare.gateway.VirtualGateway; 11 | import com.github.megatronking.netbare.gateway.VirtualGatewayFactory; 12 | import com.github.megatronking.netbare.net.Session; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link VirtualGatewayFactory} that produces the {@link RawTcpVirtualGateway}. 19 | * 20 | * @author RSmxchen 21 | * @since 2019-04-27 14:08 22 | */ 23 | public class RawTcpVirtualGatewayFactory implements VirtualGatewayFactory { 24 | 25 | private List> mFactories; 26 | 27 | public RawTcpVirtualGatewayFactory(@NonNull List> factories) { 29 | this.mFactories = factories; 30 | } 31 | 32 | @Override 33 | public VirtualGateway create(Session session, Request request, Response response) { 34 | return new RawTcpVirtualGateway(session, request, response, new ArrayList<>(mFactories)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/interceptor/CaptureRawInterceptorFactory.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.interceptor; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.github.megatronking.netbare.gateway.Interceptor; 6 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 7 | import com.mingxiangChen.droidnet.fragment.PacketCapturedListener; 8 | 9 | /** 10 | * A {@link InterceptorFactory} that creates {@link CaptureRawInterceptor}. 11 | * 12 | * @author RSmxchen 13 | */ 14 | public class CaptureRawInterceptorFactory implements InterceptorFactory { 15 | 16 | private PacketCapturedListener mPacketCapturedListener; 17 | 18 | // public PacketCapturedListener getPacketCapturedListener() { 19 | // return mPacketCapturedListener; 20 | // } 21 | 22 | public void setPacketCapturedListener(PacketCapturedListener mPacketCapturedListener) { 23 | this.mPacketCapturedListener = mPacketCapturedListener; 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public Interceptor create() { 29 | CaptureRawInterceptor captureRawInterceptor = new CaptureRawInterceptor(); 30 | captureRawInterceptor.setPacketCapturedListener(mPacketCapturedListener); 31 | return captureRawInterceptor; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/interceptor/FirewallInterceptorFactory.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.interceptor; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.github.megatronking.netbare.gateway.Interceptor; 6 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 7 | import com.mingxiangChen.droidnet.fragment.ToastFirewallHandler; 8 | 9 | /** 10 | * A {@link InterceptorFactory} that creates {@link FirewallInterceptor}. 11 | * 12 | * @author RSmxchen 13 | * @since 2019-06-03 17:48 14 | */ 15 | public class FirewallInterceptorFactory implements InterceptorFactory { 16 | 17 | private ToastFirewallHandler mHandler; 18 | 19 | public void setHandler(ToastFirewallHandler handler) { 20 | this.mHandler = handler; 21 | } 22 | 23 | @NonNull 24 | @Override 25 | public Interceptor create() { 26 | FirewallInterceptor firewallInterceptor = new FirewallInterceptor(); 27 | firewallInterceptor.setHandler(mHandler); 28 | return firewallInterceptor; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/interceptor/HttpUrlPrintInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.interceptor; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.util.Log; 5 | 6 | import com.github.megatronking.netbare.http.HttpIndexedInterceptor; 7 | import com.github.megatronking.netbare.http.HttpInterceptor; 8 | import com.github.megatronking.netbare.http.HttpInterceptorFactory; 9 | import com.github.megatronking.netbare.http.HttpRequestChain; 10 | import com.github.megatronking.netbare.http.HttpResponseChain; 11 | 12 | import java.io.IOException; 13 | import java.nio.ByteBuffer; 14 | 15 | public class HttpUrlPrintInterceptor extends HttpIndexedInterceptor { 16 | 17 | private String TAG = "Url:"; 18 | 19 | public static HttpInterceptorFactory createFactory() { 20 | return new HttpInterceptorFactory() { 21 | @NonNull 22 | @Override 23 | public HttpInterceptor create() { 24 | return new HttpUrlPrintInterceptor(); 25 | } 26 | }; 27 | } 28 | 29 | @Override 30 | protected void intercept(@NonNull HttpRequestChain chain, @NonNull ByteBuffer buffer, int index) throws IOException { 31 | if (index == 0) { 32 | // 一个请求可能会有多个数据包,故此方法会多次触发,这里只在收到第一个包的时候打印 33 | Log.i(TAG, "Request: " + chain.request().url()); 34 | } 35 | // 调用process将数据发射给下一个拦截器,否则数据将不会发给服务器 36 | chain.process(buffer); 37 | } 38 | 39 | @Override 40 | protected void intercept(@NonNull HttpResponseChain chain, @NonNull ByteBuffer buffer, int index) throws IOException { 41 | chain.process(buffer); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/interceptor/RawTcpPrintInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.interceptor; 2 | 3 | import android.content.pm.PackageManager; 4 | import android.support.annotation.NonNull; 5 | import android.util.Log; 6 | 7 | import com.github.megatronking.netbare.gateway.AbstractRequestChain; 8 | import com.github.megatronking.netbare.gateway.AbstractResponseChain; 9 | import com.github.megatronking.netbare.gateway.Interceptor; 10 | import com.github.megatronking.netbare.gateway.InterceptorFactory; 11 | import com.github.megatronking.netbare.gateway.Request; 12 | import com.github.megatronking.netbare.gateway.Response; 13 | import com.mingxiangChen.droidnet.App; 14 | 15 | import java.io.IOException; 16 | import java.nio.ByteBuffer; 17 | import java.nio.CharBuffer; 18 | import java.nio.charset.Charset; 19 | 20 | /** 21 | * A {@link Interceptor} converts tcp data to ASCII-encoding String. 22 | * 23 | * @author RSmxchen 24 | * @since 2019-04-27 25 | */ 26 | public class RawTcpPrintInterceptor implements Interceptor { 27 | 28 | private String TAG = "Raw Tcp data\n"; 29 | private Charset mAscii; 30 | 31 | private RawTcpPrintInterceptor() { 32 | this.mAscii = Charset.forName("ascii"); 33 | } 34 | 35 | public static InterceptorFactory createFactory() { 36 | return new InterceptorFactory() { 37 | @NonNull 38 | @Override 39 | public Interceptor create() { 40 | return new RawTcpPrintInterceptor(); 41 | } 42 | }; 43 | } 44 | 45 | @Override 46 | public void intercept(@NonNull AbstractRequestChain chain, @NonNull ByteBuffer buffer) throws IOException { 47 | PackageManager packageManager = App.getInstance().getPackageManager(); 48 | Log.d("PackageName:", packageManager.getNameForUid(chain.request().uid())); 49 | 50 | CharBuffer result = mAscii.decode(buffer); 51 | Log.d(TAG, result.toString()); 52 | 53 | buffer.flip(); // decode过程操作了buffer,需要把极限和位置还原,否则remote tunnel发送大小为0 54 | chain.process(buffer); 55 | } 56 | 57 | @Override 58 | public void intercept(@NonNull AbstractResponseChain chain, @NonNull ByteBuffer buffer) throws IOException { 59 | CharBuffer result = mAscii.decode(buffer); 60 | Log.d(TAG, result.toString()); 61 | 62 | buffer.flip(); 63 | chain.process(buffer); 64 | } 65 | 66 | @Override 67 | public void onRequestFinished(@NonNull Request request) { 68 | Log.i(TAG, "onRequestFinished!"); 69 | } 70 | 71 | @Override 72 | public void onResponseFinished(@NonNull Response response) { 73 | Log.i(TAG, "onResponseFinished!"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/table/InterceptRules.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.table; 2 | 3 | import org.litepal.annotation.Column; 4 | import org.litepal.crud.LitePalSupport; 5 | 6 | /** 7 | * A litepal table contains the intercept rules 8 | * used by {@link com.mingxiangChen.droidnet.interceptor.FirewallInterceptor}. 9 | * 10 | * @author RSmxchen 11 | * @since 2019-04-29 15:40 12 | */ 13 | public class InterceptRules extends LitePalSupport { 14 | 15 | @Column(nullable = false) 16 | private int priority; 17 | 18 | @Column(nullable = false, defaultValue = "N/A") 19 | private String session; 20 | 21 | @Column(nullable = false, defaultValue = "N/A") 22 | private String packageName; 23 | 24 | @Column(nullable = false, defaultValue = "N/A") 25 | private String pattern; 26 | 27 | public String getSession() { 28 | return session; 29 | } 30 | 31 | public void setSession(String session) { 32 | this.session = session; 33 | } 34 | 35 | public String getPackageName() { 36 | return packageName; 37 | } 38 | 39 | public void setPackageName(String packageName) { 40 | this.packageName = packageName; 41 | } 42 | 43 | public String getPattern() { 44 | return pattern; 45 | } 46 | 47 | public void setPattern(String pattern) { 48 | this.pattern = pattern; 49 | } 50 | 51 | public int getPriority() { 52 | return priority; 53 | } 54 | 55 | public void setPriority(int priority) { 56 | this.priority = priority; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/mingxiangChen/droidnet/util/ThreadProxy.java: -------------------------------------------------------------------------------- 1 | package com.mingxiangChen.droidnet.util; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.util.concurrent.Executor; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.ThreadFactory; 8 | import java.util.concurrent.ThreadPoolExecutor; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * A singleton class provides multithreading operations. Reference the NetworkPacketCapture project. 13 | * 14 | * @author RSmxchen 15 | * @since 2019-05-08 13:48 16 | */ 17 | public class ThreadProxy { 18 | 19 | private final Executor executor; 20 | 21 | static class InnerClass { 22 | static ThreadProxy instance = new ThreadProxy(); //内部类实现的单例模式? 23 | } 24 | 25 | private ThreadProxy() { 26 | 27 | executor = new ThreadPoolExecutor(1, 4, 28 | 10L, TimeUnit.MILLISECONDS, 29 | new LinkedBlockingQueue(1024), new ThreadFactory() { 30 | @Override 31 | public Thread newThread(@NonNull Runnable r) { 32 | Thread thread = new Thread(r); 33 | thread.setName("ThreadProxy"); 34 | return thread; 35 | } 36 | }); 37 | } 38 | public void execute(Runnable run){ 39 | executor.execute(run); 40 | } 41 | public static ThreadProxy getInstance(){ 42 | return InnerClass.instance; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RSencoder/DroidNet/e24b248206d3f5edee9f7b0b2b4e43c7a7ca8e19/app/src/main/res/drawable/settings.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RSencoder/DroidNet/e24b248206d3f5edee9f7b0b2b4e43c7a7ca8e19/app/src/main/res/drawable/start.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RSencoder/DroidNet/e24b248206d3f5edee9f7b0b2b4e43c7a7ca8e19/app/src/main/res/drawable/stop.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 20 | 21 | 24 | 25 | 29 | 30 | 31 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_package_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 19 | 20 | 24 | 25 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_packet_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_capture.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_firewall.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 18 | 19 |