Commit b2741d12 authored by liuyang's avatar liuyang

非root抓包处理

parent 68607be4
package com.duolebo.blyrobot
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.duolebo.blyrobot.service.BylRobotService
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.duolebo.blyrobot.activity.PackageListActivity
import com.duolebo.blyrobot.data.ApkPackageInfo
import com.duolebo.blyrobot.service.BylWebService
import com.duolebo.blyrobot.util.AppUtil
import com.minhui.vpn.ProxyConfig
import com.minhui.vpn.VPNConstants.*
import com.minhui.vpn.service.FirewallVpnService
import com.minhui.vpn.utils.ThreadProxy
import com.minhui.vpn.utils.VpnServiceHelper
import com.minhui.vpn.utils.VpnServiceHelper.START_VPN_SERVICE_REQUEST_CODE
import java.io.File
import java.io.FileFilter
class MainActivity : AppCompatActivity() {
private val REQUEST_PACKAGE = 103
private lateinit var captureButton:Button
private var vpnStatusListener: ProxyConfig.VpnStatusListener = object : ProxyConfig.VpnStatusListener {
override fun onVpnStart(context: Context) {
runOnUiThread {
refreshCaptureBtn()
}
}
override fun onVpnEnd(context: Context) {
runOnUiThread {
refreshCaptureBtn()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i("", "onCreate....")
setContentView(R.layout.activity_main)
startService(Intent(this, BylRobotService::class.java))
ProxyConfig.Instance.registerVpnStatusListener(vpnStatusListener)
// startService(Intent(this, BylRobotService::class.java))
val selectBtn = findViewById<Button>(R.id.selectBtn)
selectBtn.setOnClickListener{
selectApp()
}
captureButton = findViewById(R.id.captureButton)
captureButton.setOnClickListener {
runOrStopCapture()
}
}
override fun onResume() {
super.onResume()
refreshCaptureBtn()
}
override fun onDestroy() {
super.onDestroy()
ProxyConfig.Instance.unregisterVpnStatusListener(vpnStatusListener)
}
private fun refreshCaptureBtn() {
if (VpnServiceHelper.vpnRunningStatus()) {
captureButton.text = "停止抓取"
}
else {
captureButton.text = "启动抓取"
}
}
private fun runOrStopCapture() {
if (VpnServiceHelper.vpnRunningStatus()) {
// stopService(Intent(this, BylWebService::class.java))
VpnServiceHelper.changeVpnRunningStatus(this, false)
}
else {
val sp = getSharedPreferences(VPN_SP_NAME, Context.MODE_PRIVATE)
val selectPackage = sp.getString(DEFAULT_PACKAGE_ID, null)
val selectName = sp.getString(DEFAULT_PACAGE_NAME, null)
if (selectPackage.isNullOrEmpty() && selectName.isNullOrEmpty()) {
Toast.makeText(this, "请选择抓取应用", Toast.LENGTH_SHORT).show()
}
else {
VpnServiceHelper.changeVpnRunningStatus(this, true)
startService(Intent(this, BylWebService::class.java))
}
}
}
private fun selectApp() {
val intent = Intent(this, PackageListActivity::class.java)
startActivityForResult(intent, REQUEST_PACKAGE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == START_VPN_SERVICE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
VpnServiceHelper.startVpnService(applicationContext)
} else if (requestCode == REQUEST_PACKAGE && resultCode == Activity.RESULT_OK) {
val showInfo = data?.getParcelableExtra<ApkPackageInfo>(PackageListActivity.SELECT_PACKAGE)
showInfo?.run {
val sp = getSharedPreferences(VPN_SP_NAME, Context.MODE_PRIVATE)
sp.edit().putString(DEFAULT_PACKAGE_ID, packageName)
.putString(DEFAULT_PACAGE_NAME, appName).apply()
}
}
}
private fun clearHistoryData() {
ThreadProxy.getInstance().execute {
val file = File(BASE_DIR)
AppUtil.deleteFile(file, FileFilter { pathname ->
return@FileFilter true
})
}
}
}
package com.duolebo.blyrobot.activity
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.view.ViewGroup
import android.widget.*
import com.duolebo.blyrobot.R
import com.minhui.vpn.utils.ThreadProxy
import com.duolebo.blyrobot.data.ApkPackageInfo
class PackageListActivity : AppCompatActivity() {
private var packageListView: GridView? = null
private var apkPackageInfo: List<ApkPackageInfo>? = null
internal lateinit var pm: PackageManager
private var pg: ProgressBar? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_package_list)
supportActionBar!!.title = "选择需要抓包的程序"
pg = findViewById(R.id.pg)
pm = packageManager
packageListView = findViewById(R.id.package_list)
ThreadProxy.getInstance().execute(object : Runnable {
private var showPackageAdapter: ShowPackageAdapter? = null
override fun run() {
apkPackageInfo = ApkPackageInfo.getAppInfos(applicationContext)
showPackageAdapter = ShowPackageAdapter()
runOnUiThread {
packageListView!!.adapter = showPackageAdapter
pg!!.visibility = View.GONE
}
}
})
packageListView!!.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
val intent = Intent()
if (position != 0) {
intent.putExtra(SELECT_PACKAGE, apkPackageInfo!![position])
}
setResult(AppCompatActivity.RESULT_OK, intent)
finish()
}
}
internal inner class ShowPackageAdapter : BaseAdapter() {
private var defaultDrawable: Drawable = resources.getDrawable(R.drawable.sym_def_app_icon)
override fun getCount(): Int {
return apkPackageInfo!!.size
}
override fun getItem(position: Int): Any? {
return null
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val holder: Holder
if (convertView == null) {
convertView = View.inflate(this@PackageListActivity, R.layout.item_select_package, null)
holder = Holder(convertView!!, position)
convertView.tag = holder
} else {
holder = convertView.tag as Holder
holder.holderPosition = position
}
val packageInfo = this@PackageListActivity.apkPackageInfo!![position]
if (packageInfo.appName == null) {
holder.appName.text = packageInfo.packageName
} else {
holder.appName.text = packageInfo.appName
}
holder.icon.setImageDrawable(defaultDrawable)
val alertIconView = convertView
ThreadProxy.getInstance().execute(Runnable {
val iconHolder = alertIconView.tag as Holder
if (iconHolder.holderPosition != position) {
return@Runnable
}
val drawable = packageInfo.applicationInfo.loadIcon(pm)
runOnUiThread(Runnable {
val iconHolder = alertIconView.tag as Holder
if (iconHolder.holderPosition != position) {
return@Runnable
}
holder.icon.setImageDrawable(drawable)
})
})
return convertView
}
internal inner class Holder(baseView: View, var holderPosition: Int) {
var appName: TextView = baseView.findViewById(R.id.app_name)
var icon: ImageView = baseView.findViewById(R.id.select_icon)
}
}
companion object {
const val SELECT_PACKAGE = "package_select"
}
}
package com.duolebo.blyrobot.data
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.Parcel
import android.os.Parcelable
import java.util.ArrayList
import java.util.Collections
import java.util.Comparator
class ApkPackageInfo : Parcelable {
var appName: String? = null
lateinit var packageName: String
lateinit var applicationInfo: ApplicationInfo
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(this.appName)
dest.writeString(this.packageName)
dest.writeParcelable(this.applicationInfo, flags)
}
constructor() {}
protected constructor(ins: Parcel) {
this.appName = ins.readString()
this.packageName = ins.readString()
this.applicationInfo = ins.readParcelable(ApplicationInfo::class.java.classLoader)
}
companion object {
private val NO_APP_NAME = "COM."
fun getAppInfos(context: Context): List<ApkPackageInfo> {
val appInfos = ArrayList<ApkPackageInfo>()
val packageManager = context.packageManager
val installedPackages = packageManager.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES)
for (info in installedPackages) {
if (info.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM <= 0) {
val packageShowInfo = ApkPackageInfo()
packageShowInfo.packageName = info.packageName
packageShowInfo.appName = info.applicationInfo.loadLabel(packageManager) as String
packageShowInfo.applicationInfo = info.applicationInfo
appInfos.add(packageShowInfo)
}
}
Collections.sort(appInfos, Comparator { o1, o2 ->
if (o1 === o2) {
return@Comparator 0
}
if (o1.appName == null && o2.appName == null) {
return@Comparator o1.packageName.toUpperCase().compareTo(o2.packageName.toUpperCase())
}
if (o1.appName == null) {
return@Comparator -1
}
if (o2.appName == null) {
return@Comparator 1
}
if (o1.appName!!.toUpperCase().startsWith(NO_APP_NAME) && !o2.appName!!.toUpperCase().startsWith(NO_APP_NAME)) {
return@Comparator 1
}
if (!o1.appName!!.toUpperCase().startsWith(NO_APP_NAME) && o2.appName!!.toUpperCase().startsWith(NO_APP_NAME)) {
-1
} else o1.appName!!.toUpperCase().compareTo(o2.appName!!.toUpperCase())
})
return appInfos
}
@JvmField
val CREATOR: Parcelable.Creator<ApkPackageInfo> = object : Parcelable.Creator<ApkPackageInfo> {
override fun createFromParcel(source: Parcel): ApkPackageInfo {
return ApkPackageInfo(source)
}
override fun newArray(size: Int): Array<ApkPackageInfo?> {
return arrayOfNulls(size)
}
}
}
}
package com.duolebo.blyrobot.service
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.duolebo.blyrobot.web.CaptureWebServer
class BylWebService : Service() {
lateinit var webServer: CaptureWebServer
override fun onCreate() {
super.onCreate()
webServer = CaptureWebServer(48080, this)
webServer.start()
}
override fun onDestroy() {
super.onDestroy()
webServer.stop()
}
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
}
package com.duolebo.blyrobot.util
import java.io.File
import java.io.FileFilter
object AppUtil {
fun deleteFile(file: File?, fileFilter: FileFilter) {
if (file == null) {
return
}
if (!fileFilter.accept(file)) {
return
}
if (file.isFile) {
file.delete()
return
}
val files = file.listFiles()
if (files == null) {
file.delete()
return
}
for (childFile in files) {
deleteFile(childFile, fileFilter)
}
file.delete()
}
}
\ No newline at end of file
package com.duolebo.blyrobot.web
import android.content.Context
import com.minhui.vpn.ProxyConfig
import com.minhui.vpn.VPNConstants
import com.minhui.vpn.VPNConstants.DEFAULT_PACKAGE_ID
import com.minhui.vpn.nat.NatSession
import com.minhui.vpn.utils.TimeFormatUtil
import com.minhui.vpn.utils.VpnServiceHelper
import fi.iki.elonen.NanoHTTPD
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
class CaptureWebServer : NanoHTTPD {
private var context:Context
private var timer: ScheduledExecutorService? = null
private var captureList = ArrayList<NatSession>()
private var listener: ProxyConfig.VpnStatusListener = object : ProxyConfig.VpnStatusListener {
override fun onVpnStart(context: Context) {
startTimer()
}
override fun onVpnEnd(context: Context) {
cancelTimer()
}
}
constructor(port: Int, context: Context) : super("0.0.0.0", port) {
init()
this.context = context
}
private fun init() {
ProxyConfig.Instance.registerVpnStatusListener(listener)
if (VpnServiceHelper.vpnRunningStatus()) {
startTimer()
}
refreshData()
}
private fun startTimer() {
timer = Executors.newSingleThreadScheduledExecutor()
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
refreshData()
}
}, 1000, 1000, TimeUnit.MILLISECONDS)
}
private fun cancelTimer() {
timer?.run {
shutdownNow()
}
timer = null
}
private fun refreshData() {
val allNetConnection = VpnServiceHelper.getAllSession()
if (allNetConnection == null || allNetConnection.isEmpty()) {
return
}
val iterator = allNetConnection.iterator()
val packageName = context.packageName
val sp = context.getSharedPreferences(VPNConstants.VPN_SP_NAME, Context.MODE_PRIVATE)
val selectPackage = sp.getString(DEFAULT_PACKAGE_ID, null)
while (iterator.hasNext()) {
val next = iterator.next()
if (next.bytesSent == 0 && next.receiveByteNum == 0L) {
iterator.remove()
continue
}
if (NatSession.UDP == next.type || !next.isHttp || next.getRequestUrl() == null) {
iterator.remove()
continue
}
val appInfo = next.appInfo
if (appInfo != null) {
val appPackageName = appInfo!!.pkgs.getAt(0)
if (packageName == appPackageName) {
iterator.remove()
continue
}
if (selectPackage != null && selectPackage != appPackageName) {
iterator.remove()
}
}
}
if (allNetConnection.size > 0) {
captureList.clear()
captureList.addAll(allNetConnection)
}
}
override fun serve(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
var msg = "<html><head><meta http-equiv=\"refresh\" content=\"10\"><meta charset=\"UTF-8\"><title>多乐播抓取辅助工具页面</title></head><body><h1>请求地址抓取记录</h1>\n"
val parms = session.parms
if (parms["clear"] != null) {
} else {
for (natSession in captureList) {
msg += "<p>================================================================================="
msg += "<p>请求时间 : " + TimeFormatUtil.formatHHMMSSMM(natSession.refreshTime)
msg += "<p>请求地址:" + natSession.getRequestUrl()
}
}
return NanoHTTPD.newFixedLengthResponse("$msg</body></html>\n")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment