日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android apk快速定位、灰色按钮克星--DroidSword

發布時間:2024/8/1 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android apk快速定位、灰色按钮克星--DroidSword 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80994434

在進行Android應用程序的逆向分析時,經常需要對Android應用程序的按鈕事件、Activity界面等類的代碼進行定位分析,傳統的代碼定位方法就是進行按鈕或者Activity界面等顯示的 字符串信息 進行全局的搜索,然后找他們的id或者類進行代碼的定位,比較繁瑣,這里介紹一個基于Xposed Hook實現的Android apk快速定位,灰色按鈕克星工具DroidSword,當然了亦可以使用我前面的博客中提到的《Xposed框架Hook Android應用的所有類方法打印Log日志》和《查找和定位Android應用的按鈕點擊事件的代碼位置基于Xposed Hook實現》進行Android應用程序的需要分析的代碼的定位。


DroidSword工具的功能介紹:

1.快速定位Activity,以及點擊View的信息

2.點擊懸浮窗口獲取Fragment

3.灰色按鈕克星

4.文字修改神器

DroidSword工具的github地址:https://github.com/githubwing/DroidSword

DroidSword工具作者的學習博客:http://androidwing.net


DroidSword工具是基于Xposed Hook實現的,但是作者githubwing是使用Kotlin語言實現的,對于Kotlin語言不熟悉,但是對于DroidSword工具的實現思路還是能看明白,下面簡要的分析一下。

1.類IHooker是作者編寫的xposed hook的接口類,代碼如下:


2.類net.androidwing.droidsword.Init是DroidSword工具xposed hook的入口類:

3.類ViewClickedHooker主要用于實現Hook類android.view.View的方法onTouchEvent,獲取到View類的名稱和View類的id以及View的事件監聽類對象的類名稱;Hook類android.view.View的方法dispatchTouchEvent,獲取到的View類的名稱、View類的id、View的事件監聽類對象的類名稱并在設備的界面上顯示出來。

源碼文件路徑:/frameworks/base/core/java/android/view/View.java

一般View組件情況下,Hook類android.view.View的類方法onTouchEvent函數,View組件通過獲取實例對象View中的成員變量mListenerInfo->mOnClickListener所屬的類名稱,得到響應View按鈕單擊事件的監聽響應類OnClickListener的信息。

/*** Implement this method to handle touch screen motion events.* <p>* If this method is used to detect click actions, it is recommended that* the actions be performed by implementing and calling* {@link #performClick()}. This will ensure consistent system behavior,* including:* <ul>* <li>obeying click sound preferences* <li>dispatching OnClickListener calls* <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when* accessibility features are enabled* </ul>** @param event The motion event.* @return True if the event was handled, false otherwise.*/public boolean onTouchEvent(MotionEvent event) {final int viewFlags = mViewFlags;if ((viewFlags & ENABLED_MASK) == DISABLED) {if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {setPressed(false);}// A disabled view that is clickable still consumes the touch// events, it just doesn't respond to them.return (((viewFlags & CLICKABLE) == CLICKABLE ||(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));}if (mTouchDelegate != null) {if (mTouchDelegate.onTouchEvent(event)) {return true;}}if (((viewFlags & CLICKABLE) == CLICKABLE ||(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {switch (event.getAction()) {case MotionEvent.ACTION_UP:boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {// take focus if we don't have it already and we should in// touch mode.boolean focusTaken = false;if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {focusTaken = requestFocus();}if (prepressed) {// The button is being released before we actually// showed it as pressed. Make it show the pressed// state now (before scheduling the click) to ensure// the user sees it.setPressed(true);}if (!mHasPerformedLongPress) {// This is a tap, so remove the longpress checkremoveLongPressCallback();// Only perform take click actions if we were in the pressed stateif (!focusTaken) {// Use a Runnable and post this rather than calling// performClick directly. This lets other visual state// of the view update before click actions start.if (mPerformClick == null) {mPerformClick = new PerformClick();}if (!post(mPerformClick)) {performClick();}}}if (mUnsetPressedState == null) {mUnsetPressedState = new UnsetPressedState();}if (prepressed) {postDelayed(mUnsetPressedState,ViewConfiguration.getPressedStateDuration());} else if (!post(mUnsetPressedState)) {// If the post failed, unpress right nowmUnsetPressedState.run();}removeTapCallback();}break;case MotionEvent.ACTION_DOWN:mHasPerformedLongPress = false;if (performButtonActionOnTouchDown(event)) {break;}// Walk up the hierarchy to determine if we're inside a scrolling container.boolean isInScrollingContainer = isInScrollingContainer();// For views inside a scrolling container, delay the pressed feedback for// a short period in case this is a scroll.if (isInScrollingContainer) {mPrivateFlags |= PFLAG_PREPRESSED;if (mPendingCheckForTap == null) {mPendingCheckForTap = new CheckForTap();}postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());} else {// Not inside a scrolling container, so show the feedback right awaysetPressed(true);checkForLongClick(0);}break;case MotionEvent.ACTION_CANCEL:setPressed(false);removeTapCallback();removeLongPressCallback();break;case MotionEvent.ACTION_MOVE:final int x = (int) event.getX();final int y = (int) event.getY();// Be lenient about moving outside of buttonsif (!pointInView(x, y, mTouchSlop)) {// Outside buttonremoveTapCallback();if ((mPrivateFlags & PFLAG_PRESSED) != 0) {// Remove any future long press/tap checksremoveLongPressCallback();setPressed(false);}}break;}return true;}return false;}

對于AdapterView類型的View組件,通過Hook類android.view.View的方法dispatchTouchEvent,AdapterView組件獲取實例對象View中的成員變量mOnItemClickListener的類(事件響應類)的類名稱,得到監聽和響應用戶單擊事件的處理類OnItemClickListener的信息。

/*** Pass the touch screen motion event down to the target view, or this* view if it is the target.** @param event The motion event to be dispatched.* @return True if the event was handled by the view, false otherwise.*/public boolean dispatchTouchEvent(MotionEvent event) {if (mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onTouchEvent(event, 0);}if (onFilterTouchEventForSecurity(event)) {//noinspection SimplifiableIfStatementListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {return true;}if (onTouchEvent(event)) {return true;}}if (mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);}return false;}

4.類ActivityHooker主要用于實現Hook類android.app.Activity的方法onResume,獲取類方法onResume所屬類Activity的實例對象的類名稱并顯示出來。

/*** Called after {@link #onRestoreInstanceState}, {@link #onRestart}, or* {@link #onPause}, for your activity to start interacting with the user.* This is a good place to begin animations, open exclusive-access devices* (such as the camera), etc.** <p>Keep in mind that onResume is not the best indicator that your activity* is visible to the user; a system window such as the keyguard may be in* front. Use {@link #onWindowFocusChanged} to know for certain that your* activity is visible to the user (for example, to resume a game).** <p><em>Derived classes must call through to the super class's* implementation of this method. If they do not, an exception will be* thrown.</em></p>* * @see #onRestoreInstanceState* @see #onRestart* @see #onPostResume* @see #onPause*/protected void onResume() {if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);getApplication().dispatchActivityResumed(this);mCalled = true;}

5.類FragmentHooker用于實現Hook類"android.support.v4.app.Fragment"的方法onResume和方法setUserVisibleHint,獲取類Fragment的類名稱并進行顯示。

源碼文件路徑:/frameworks/support/v4/java/android/support/v4/app/Fragment.java


/*** Called when the fragment is visible to the user and actively running.* This is generally* tied to {@link Activity#onResume() Activity.onResume} of the containing* Activity's lifecycle.*/public void onResume() {mCalled = true;}

/*** Set a hint to the system about whether this fragment's UI is currently visible* to the user. This hint defaults to true and is persistent across fragment instance* state save and restore.** <p>An app may set this to false to indicate that the fragment's UI is* scrolled out of visibility or is otherwise not directly visible to the user.* This may be used by the system to prioritize operations such as fragment lifecycle updates* or loader ordering behavior.</p>** @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),* false if it is not.*/public void setUserVisibleHint(boolean isVisibleToUser) {if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {mFragmentManager.performPendingDeferredStart(this);}mUserVisibleHint = isVisibleToUser;mDeferStart = !isVisibleToUser;}

有作者gtict112將DroidSword工具的功能用java代碼進行了實現并添加了新的功能構建成工程xposedhook,xposedhook工程的github地址:https://github.com/gtict112/xposedhook,后面有時間我再看下將這部分代碼集成到我自己的Xposed模塊中。

DroidSword工具的類ViewClickedHooker的代碼:

package net.androidwing.droidsword.hookerimport android.app.AlertDialog import android.app.AndroidAppHelper import android.app.Dialog import android.content.DialogInterface import android.view.MotionEvent import android.view.View import android.widget.* import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import net.androidwing.droidsword.func.TextViewChanger import net.androidwing.droidsword.func.ViewEnabler import net.androidwing.droidsword.utils.LogUtils/*** Created on 28/10/2017.*/ class ViewClickedHooker : IHooker {override fun hook(lp: XC_LoadPackage.LoadPackageParam) {// Hook類android.view.View的方法onTouchEvent// public boolean onTouchEvent(MotionEvent event)XposedHelpers.findAndHookMethod(View::class.java,"onTouchEvent",MotionEvent::class.java, object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)// 獲取類方法onTouchEvent所在的實例對象Viewval view = param?.thisObject as View// 獲取類方法onTouchEvent的傳入參數MotionEvent實例對象val event = param.args!![0] as MotionEvent// 對用戶點擊屏幕的事件進行判斷if (event.action == MotionEvent.ACTION_UP) {// 獲取實例對象View中的成員變量mListenerInfo->mOnClickListener所屬的類名稱val listener = XposedHelpers.getObjectField(XposedHelpers.getObjectField(view, "mListenerInfo"),"mOnClickListener").javaClass.name// 顯示獲取到的View類的名稱、View類的id、View的事件監聽類對象的類名稱ActivityHooker.setActionInfoToMenu("","${view.javaClass.name} ${view.id} \nListener: $listener")antiDisable(view)}}})// Hook類android.view.View的方法dispatchTouchEvent// public boolean dispatchTouchEvent(MotionEvent event)XposedHelpers.findAndHookMethod(View::class.java,"dispatchTouchEvent",MotionEvent::class.java, object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)// 獲取類方法dispatchTouchEvent所在類View的實例val view = param?.thisObject as View// 獲取類方法onTouchEvent的傳入參數MotionEvent實例對象val event = param.args!![0] as MotionEvent// 進行用戶點擊屏幕的事件類型的判斷if (event.action == MotionEvent.ACTION_DOWN) {// 進行View類型的判斷(AdapterView)if (view is AdapterView<*>) {// 獲取實例對象View中的成員變量mOnItemClickListener的類(事件響應類)的類名稱val listener = XposedHelpers.getObjectField(view,"mOnItemClickListener").javaClass.name// 顯示獲取到的View類的名稱、View類的id、View的事件監聽類對象的類名稱ActivityHooker.setActionInfoToMenu("","${view.javaClass.name} ${view.id} \nListener: $listener")}}}})// 文字修改功能的實現XposedHelpers.findAndHookMethod(View::class.java,"onTouchEvent",MotionEvent::class.java, object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)val targetView = param?.thisObject as Viewif (true) {// ??showChangeTextDialog(targetView, param)}}})}private fun antiDisable(view: View) {//TODO 默認開啟待添加配置文件if (false) {ViewEnabler.antiDisable(view)}}/*** 文本修改神器功能*/private fun showChangeTextDialog(targetView: View,param: XC_MethodHook.MethodHookParam) {//TODO 默認開啟待添加配置文件val event = param.args!![0] as MotionEventif (false) {TextViewChanger.showChangeDialog(targetView, event)}}

DroidSword工具的類ActivityHooker的代碼:

package net.androidwing.droidsword.hookerimport android.app.Activity import android.app.AndroidAppHelper import android.app.Fragment import android.content.Context import android.graphics.Color import android.os.Build import android.os.Bundle import android.support.v7.widget.AppCompatImageHelper import android.text.TextUtils import android.view.LayoutInflater import android.view.ViewGroup import android.widget.FrameLayout import android.widget.TextView import android.widget.Toast import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import net.androidwing.droidsword.utils.LogUtils import java.util.ArrayList/*** Created on 30/10/2017.*/ class ActivityHooker : IHooker {// /frameworks/base/core/java/android/app/Activity.javaoverride fun hook(lp: XC_LoadPackage.LoadPackageParam) {// Hook類android.app.Activity的方法onResume// protected void onResume()XposedHelpers.findAndHookMethod(Activity::class.java, "onResume", object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)// 獲取類方法onResume所屬類Activity的實例對象val activity = param?.thisObject as Activity// 顯示類對象實例Activity的類名稱addTextView(activity)// Hook類Fragment的類方法,獲取類Fragment實例對象的類名稱FragmentHooker().hookFragment(param)}})}// 顯示類對象實例Activity的類名稱private fun addTextView(activity: Activity) {// 獲取類對象實例Activity的類名稱val className = activity.javaClass.name.toString()// 構建TextView實例對象if (sTextView == null) {genTextView(activity)}if (sTextView?.parent != null) {val parent = sTextView?.parentif (parent is ViewGroup) {parent.removeView(sTextView)}}(activity.window.decorView as FrameLayout).addView(sTextView)// 顯示類對象實例Activity的類名稱setActionInfoToMenu(className, "")sTextView?.bringToFront()}// 創建TextView的實例對象private fun genTextView(activity: Activity) {sTextView = TextView(activity)with(sTextView!!) {textSize = 8fy = 48 * 2fsetBackgroundColor(Color.parseColor("#cc888888"))setTextColor(Color.WHITE)layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.WRAP_CONTENT)}}companion object {var sTextView: TextView? = nullprivate var sActivityName = ""private var sViewName = ""fun setActionInfoToMenu(activityName: String, viewName: String) {sTextView?.text = getActionInfo(activityName, viewName)}public var sFragmentName = ""private fun getActionInfo(activityName: String, viewName: String): CharSequence? {if (activityName.isEmpty().not()) {sActivityName = activityName}if (viewName.isEmpty().not()) {sViewName = viewName}val pid = android.os.Process.myPid()return "Activity: $sActivityName \nPid: $pid \nClick: $sViewName \nFragment:$sFragmentName"}}

DroidSword工具的類FragmentHooker的代碼:

package net.androidwing.droidsword.hookerimport de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import net.androidwing.droidsword.utils.LogUtils/*** Created on 30/10/2017.*/ class FragmentHooker : IHooker {override fun hook(lp: XC_LoadPackage.LoadPackageParam) {}// /frameworks/support/v4/java/android/support/v4/app/Fragment.javafun hookFragment(param: XC_MethodHook.MethodHookParam?) {// Hook類"android.support.v4.app.Fragment"的方法onResume// public void onResume()XposedHelpers.findAndHookMethod(param?.thisObject?.javaClass?.classLoader?.loadClass("android.support.v4.app.Fragment"),"onResume",object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)// 獲取類Fragment的類名稱ActivityHooker.sFragmentName = (param?.thisObject?.javaClass?.name!!)// 進行類Fragment的類名稱顯示的設置ActivityHooker.setActionInfoToMenu("","")}override fun beforeHookedMethod(param: MethodHookParam?) {super.beforeHookedMethod(param)}})// Hook類"android.support.v4.app.Fragment"的方法setUserVisibleHint// public void setUserVisibleHint(boolean isVisibleToUser)XposedHelpers.findAndHookMethod(param?.thisObject?.javaClass?.classLoader?.loadClass("android.support.v4.app.Fragment"),"setUserVisibleHint", Boolean::class.java,object : XC_MethodHook() {override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)if (param?.args!![0] == true) {LogUtils.e("fragment showing:")LogUtils.e("fragment ${param?.thisObject?.javaClass?.name}")// 獲取類Fragment的類名稱ActivityHooker.sFragmentName = (param?.thisObject?.javaClass?.name!!)// 進行類Fragment的類名稱顯示的設置ActivityHooker.setActionInfoToMenu("","")}}override fun beforeHookedMethod(param: MethodHookParam?) {super.beforeHookedMethod(param)}})}}

總結

以上是生活随笔為你收集整理的Android apk快速定位、灰色按钮克星--DroidSword的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。