中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

成都市網(wǎng)站建設(shè)怎么自己注冊網(wǎng)站

成都市網(wǎng)站建設(shè),怎么自己注冊網(wǎng)站,第三方免費做網(wǎng)站,樓盤網(wǎng)站建設(shè)方案1 前言 前面章節(jié)我們學(xué)習(xí)了【Android Framework系列】第5章 AMS啟動流程和【Android Framework系列】第6章 AMS原理之Launcher啟動流程,大概了解了AMS的原理及啟動流程,這一章節(jié)我們通過反射和動態(tài)代理對不同Android版本下的AMS進行Hook,實現(xiàn)…

1 前言

前面章節(jié)我們學(xué)習(xí)了【Android Framework系列】第5章 AMS啟動流程和【Android Framework系列】第6章 AMS原理之Launcher啟動流程,大概了解了AMS的原理及啟動流程,這一章節(jié)我們通過反射和動態(tài)代理對不同Android版本下的AMS進行Hook實現(xiàn)登錄頁面的跳轉(zhuǎn)

這里我們只簡單介紹一下HookAMS思路和重點代碼,需要詳細了解的請到文末處項目地址下載查看。

1.1 實現(xiàn)打開統(tǒng)一登錄頁面

我們在Android的APP中,一般會有登錄狀態(tài)。如果非登錄狀態(tài)下,除了閃屏頁和登錄頁外,其他頁面打開需要先登錄。往往登錄狀態(tài)也會有有效期的說法,如果在有效期到了跳轉(zhuǎn),我們則需要跳轉(zhuǎn)到登錄頁面,而不是繼續(xù)打開頁面,這種情況下我們通過HookAMS可以實現(xiàn)。

1.2 實現(xiàn)打開動態(tài)插件下發(fā)頁面

另外通過HookAMS還可以實現(xiàn)動態(tài)下發(fā)插件的功能,比如動態(tài)下發(fā)的ActivityAndroidManifest.xml里是沒有注冊,要想打開則需要通過HookAMS的方式,使用代理頁面在AndroidManifest.xml注冊,在跳轉(zhuǎn)時動態(tài)切換到下發(fā)下來的插件內(nèi)Activity

2 實現(xiàn)

2.1 實現(xiàn)思路

通過動態(tài)代理的方式,將AMSstartActivity方法攔截下來,把要跳轉(zhuǎn)的意圖替換成我們要打開的Activity。由于不同的Android版本AMS源碼有所差別,所以這里區(qū)分SDK<=23、SDK<=28SDK>28這三種情況做HookAMS適配。下面我們來看看項目結(jié)構(gòu)

2.2 項目結(jié)構(gòu)

在這里插入圖片描述
上圖我們可以看到項目結(jié)構(gòu)如下:

// Config					常量配置類
// HookAMSApplication		Application進行HookAMS初始化
// HookAMSUtils				HookAMS工具類,主要的Hook邏輯	
// ListActivity				數(shù)據(jù)頁面,登錄后才可打開
// LoginActivity			登錄頁
// MainActivity				首頁,這里打開數(shù)據(jù)頁面
// ProxyActivity			代理頁,用于欺瞞AMS,跳轉(zhuǎn)時動態(tài)替換為真正Activity

首先我們來看是怎么HookAMSApplication

2.3 HookAMSApplication

package com.yvan.hookams;import android.app.Application;
import android.os.Handler;
import android.os.Looper;/*** @author yvan* @date 2023/7/28* @description*/
public class HookAMSApplication extends Application {private final Handler handler = new Handler(Looper.getMainLooper());@Overridepublic void onCreate() {super.onCreate();handler.post(this::hookAMS);}public void hookAMS() {try {HookAMSUtils hookUtils = new HookAMSUtils(this, ProxyActivity.class);hookUtils.hookAms();} catch (Exception e) {e.printStackTrace();}}
}

在App啟動時,ApplicationonCreate()方法內(nèi)通過Handlerpost方法進行對HookAMSUtils類的hookAms()方法調(diào)用。為什么要使用Handler呢?初始化ApplicationonCreate()初始化還沒完成,直接調(diào)hookAms()方法會崩潰,這里加了post,將任務(wù)加入到主線程的隊列里,這樣就不會出現(xiàn)崩潰異常。

我們繼續(xù)看HookAMSUtils類:

2.4 HookAMSUtils

package com.yvan.hookams;import static android.os.Build.VERSION.SDK_INT;import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.util.Log;import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;/*** @author yvan* @date 2023/7/28* @description Hook AMS工具類*/
public class HookAMSUtils {private static final String TAG = HookAMSUtils.class.getSimpleName();private Context context;private Class<?> proxyActivity;/*** proxyActivity 傳入一個有注冊在AndroidManifest的就行** @param context* @param proxyActivity*/public HookAMSUtils(Context context, Class<?> proxyActivity) {this.context = context;this.proxyActivity = proxyActivity;}public void hookAms() throws Exception {if (SDK_INT <= 23) {hookAmsFor6();} else if (SDK_INT <= 28) {hookAmsFor9();} else {hookAmsFor10();}hookSystemHandler();}public void hookAmsFor10() throws Exception {Class<?> iActivityManagerClazz = Class.forName("android.app.IActivityTaskManager");Class<?> clazz = Class.forName("android.app.ActivityTaskManager");Field singletonField = clazz.getDeclaredField("IActivityTaskManagerSingleton");singletonField.setAccessible(true);Object singleton = singletonField.get(null);Class<?> singletonClass = Class.forName("android.util.Singleton");Field mInstanceField = singletonClass.getDeclaredField("mInstance");mInstanceField.setAccessible(true);final Object mInstance = mInstanceField.get(singleton);Object proxyInstance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{iActivityManagerClazz}, new AmsInvocationHandler(mInstance));mInstanceField.setAccessible(true);mInstanceField.set(singleton, proxyInstance);}public void hookAmsFor9() throws Exception {// 1.反射獲取類>ActivityTaskManager,這個就是AMS實例Class ActivityManagerClz = Class.forName("android.app.ActivityManager");// 2.獲取IActivityManagerSingleton,并設(shè)置訪問權(quán)限Field iActivityManagerSingletonFiled = ActivityManagerClz.getDeclaredField("IActivityManagerSingleton");iActivityManagerSingletonFiled.setAccessible(true);// 因為是靜態(tài)變量,所以獲取的到的是默認值final Object iActivityManagerSingletonObj = iActivityManagerSingletonFiled.get(null);// 3.現(xiàn)在創(chuàng)建我們的AMS實例// 由于IActivityManager是一個接口,那么其實我們可以使用Proxy類來進行代理對象的創(chuàng)建// 結(jié)果被擺了一道,IActivityManager這玩意居然還是個AIDL,動態(tài)生成的類,編譯器還不認識這個類,怎么辦?反射咯// 反射創(chuàng)建一個Singleton的classClass SingletonClz = Class.forName("android.util.Singleton");Field mInstanceField = SingletonClz.getDeclaredField("mInstance");mInstanceField.setAccessible(true);// 4.獲取AMS ProxyObject iActivityManagerObj = mInstanceField.get(iActivityManagerSingletonObj);// 5.獲取需要實現(xiàn)的接口IActivityManager實現(xiàn)類Class iActivityManagerClz = Class.forName("android.app.IActivityManager");// 6.動態(tài)生成接口對象// 構(gòu)建代理類需要兩個東西用于創(chuàng)建偽裝的Intent// 拿到AMS實例,然后用代理的AMS換掉真正的AMS,代理的AMS則是用 假的Intent騙過了 activity manifest檢測.Object proxyIActivityManager = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[]{iActivityManagerClz}, new AmsInvocationHandler(iActivityManagerObj));mInstanceField.setAccessible(true);// 7.替換掉系統(tǒng)的變量mInstanceField.set(iActivityManagerSingletonObj, proxyIActivityManager);}public void hookAmsFor6() throws Exception {//1.反射獲取類>ActivityManagerNativeClass ActivityManagerClz = Class.forName("android.app.ActivityManagerNative");//2.獲取變量>gDefaultField IActivityManagerSingletonFiled = ActivityManagerClz.getDeclaredField("gDefault");//2.1 設(shè)置訪問權(quán)限IActivityManagerSingletonFiled.setAccessible(true);//3. 獲取變量的實例值Object IActivityManagerSingletonObj = IActivityManagerSingletonFiled.get(null);//4.獲取mInstanceClass SingletonClz = Class.forName("android.util.Singleton");Field mInstanceField = SingletonClz.getDeclaredField("mInstance");mInstanceField.setAccessible(true);//5.獲取AMS ProxyObject AMSProxy = mInstanceField.get(IActivityManagerSingletonObj);//6.由于不能去手動實現(xiàn)IActivityManager實現(xiàn)類,//  所以只能通過動態(tài)代理去動態(tài)生成實現(xiàn)類//6.1 獲取需要實現(xiàn)的接口Class IActivityManagerClz = Class.forName("android.app.IActivityManager");//6.2 動態(tài)生成接口對象Object proxyIActivityManager = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{IActivityManagerClz}, new AmsInvocationHandler(AMSProxy));mInstanceField.setAccessible(true);//7.替換掉系統(tǒng)的變量mInstanceField.set(IActivityManagerSingletonObj, proxyIActivityManager);}private class AmsInvocationHandler implements InvocationHandler {private Object iActivityManagerObject;public AmsInvocationHandler(Object iActivityManagerObject) {this.iActivityManagerObject = iActivityManagerObject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("startActivity".contains(method.getName())) {Intent intent = null;int index = 0;for (int i = 0; i < args.length; i++) {Object arg = args[i];if (arg instanceof Intent) {intent = (Intent) args[i]; // 原意圖,過不了安檢index = i;break;}}Intent proxyIntent = new Intent();ComponentName componentName = new ComponentName(context, proxyActivity);proxyIntent.setComponent(componentName);proxyIntent.putExtra("realIntent", intent);//替換原有的intent為我們自己生成的,為了騙過PMS//為跳到我們的傳入的proxyActivityargs[index] = proxyIntent;}return method.invoke(iActivityManagerObject, args);}}//上面的主要是替換成我們自己的intent,騙過系統(tǒng)//下面的主要是將我們上面替換的intent中,取出我們真正的意圖(也就是正在要啟動的Activity)////下面是為了拿到mH對象,但是mH是一個非static 的值,那我們就只能拿到他的持有對象,也就是ActivityThread//正好發(fā)現(xiàn)在ActivityThread類中有一個static變量sCurrentActivityThread值可以拿到ActivityThread類,那我們就從他入手public void hookSystemHandler() throws Exception {//1.反射ActivityThreadClass ActivityThreadClz = Class.forName("android.app.ActivityThread");//2. 獲取sCurrentActivityThread 是一個static變量Field field = ActivityThreadClz.getDeclaredField("sCurrentActivityThread");field.setAccessible(true);//3.獲取ActivityThread對象Object ActivityThreadObj = field.get(null);//4.通過ActivityThreadObj獲取到mH變量Field mHField = ActivityThreadClz.getDeclaredField("mH");mHField.setAccessible(true);//5.獲取到mH的對象Handler mHObj = (Handler) mHField.get(ActivityThreadObj);//ok,當前的mH拿到了//到這里,獲取到mH的對象了,那我們怎么去監(jiān)聽他的方法調(diào)用呢?//能不能通過動態(tài)代理?不能,因為它不是個接口//由于在Handler的源碼中,我們知道如果mCallback如果不等于空,就會調(diào)用mCallback的handleMessage方法。//6.獲取mH的mCallbackField mCallbackField = Handler.class.getDeclaredField("mCallback");mCallbackField.setAccessible(true);//7.創(chuàng)建我們自己的Callback,自己處理handleMessageHandler.Callback proxyMHCallback = getMHCallback();//8.給系統(tǒng)的mH(Handler)的mCallback設(shè)值(proxyMHCallback)mCallbackField.set(mHObj, proxyMHCallback);}private Handler.Callback getMHCallback() {if (SDK_INT <= 23) {return new ProxyHandlerCallbackFor6();} else if (SDK_INT <= 28) {return new ProxyHandlerCallbackFor();} else {return new ProxyHandlerCallbackFor();}}private class ProxyHandlerCallbackFor6 implements Handler.Callback {private int LAUNCH_ACTIVITY = 100;@Overridepublic boolean handleMessage(Message msg) {if (msg.what == LAUNCH_ACTIVITY) {try {Class ActivityClientRecord = Class.forName("android.app.ActivityThread$ActivityClientRecord");//判斷傳過來的值(msg.obj)是不是ClientTransaction對象if (!ActivityClientRecord.isInstance(msg.obj)) return false;//獲取ActivityClientRecord的intent變量Field intentField = ActivityClientRecord.getDeclaredField("intent");intentField.setAccessible(true);if (intentField == null) return false;Intent mIntent = (Intent) intentField.get(msg.obj);if (mIntent == null) return false;//獲取我們之前傳入的realIntent,也就是我們真正要打開的ActivityIntent realIntent = mIntent.getParcelableExtra("realIntent");if (realIntent == null) {return false;}realStartActivity(mIntent, realIntent);} catch (Exception e) {e.printStackTrace();}}return false;}}private class ProxyHandlerCallbackFor implements Handler.Callback {private int EXECUTE_TRANSACTION = 159;@Overridepublic boolean handleMessage(Message msg) {if (msg.what == EXECUTE_TRANSACTION) {try {Class ClientTransactionClz = Class.forName("android.app.servertransaction.ClientTransaction");//判斷傳過來的值(msg.obj)是不是ClientTransaction對象if (!ClientTransactionClz.isInstance(msg.obj)) return false;Class LaunchActivityItemClz = Class.forName("android.app.servertransaction.LaunchActivityItem");//獲取ClientTransaction的mActivityCallbacks變量Field mActivityCallbacksField = ClientTransactionClz.getDeclaredField("mActivityCallbacks");//ClientTransaction的成員//設(shè)值成mActivityCallbacksField.setAccessible(true);//獲取到ASM傳遞過來的值(ClientTransaction對象)里的mActivityCallbacks變量Object mActivityCallbacksObj = mActivityCallbacksField.get(msg.obj);List list = (List) mActivityCallbacksObj;if (list.size() == 0) return false;Object LaunchActivityItemObj = list.get(0);if (!LaunchActivityItemClz.isInstance(LaunchActivityItemObj)) return false;//獲取mIntent變量Field mIntentField = LaunchActivityItemClz.getDeclaredField("mIntent");mIntentField.setAccessible(true);//獲取mIntent對象Intent mIntent = (Intent) mIntentField.get(LaunchActivityItemObj);//獲取我們之前傳入的realIntent,也就是我們真正要打開的ActivityIntent realIntent = mIntent.getParcelableExtra("realIntent");if (realIntent == null) {return false;}realStartActivity(mIntent, realIntent);} catch (Exception e) {e.printStackTrace();}}return false;}}private void realStartActivity(Intent mIntent, Intent realIntent) {//登錄判斷SharedPreferences share = context.getSharedPreferences(Config.SP_NAME,Context.MODE_PRIVATE);if (share.getBoolean(Config.SP_KEY_LOGIN, false)) {mIntent.setComponent(realIntent.getComponent());} else {Log.i(TAG, "handleLauchActivity: " + realIntent.getComponent().getClassName());ComponentName componentName = new ComponentName(context, LoginActivity.class);mIntent.putExtra("extraIntent", realIntent.getComponent().getClassName());mIntent.setComponent(componentName);}}}

從上面代碼我們能看到:

  1. hookAms()方法分別是SDK<=23、SDK<=28、SDK>28三種情況進行HookAMS,其實都是大同小異。實際上是獲取到IActivityManager對象,通過動態(tài)代理Proxy.newProxyInstance()Hook到其所有方法,通過AmsInvocationHandler進行方法調(diào)用的回調(diào)。
  2. hookSystemHandler()方法在hookAms()方法調(diào)用后立刻執(zhí)行,通過反射獲取android.app.ActivityThread類對象的sCurrentActivityThread屬性和Handler實例mH,將Handler的回調(diào)handleMessage()方法進行攔截。根據(jù)SDK<=23、SDK<=28、SDK>28三種情況不同來區(qū)別處理。
  3. 1中的AmsInvocationHandler負責hookAms()內(nèi)Hook到的方法調(diào)用的處理,在Hook到的Callback中判斷為startActivity()方法則攔截下來,將我們真正要跳轉(zhuǎn)的Activity意圖存在Extra內(nèi),由于在原來的Intent中隱藏了真正的Activity意圖,所以只需要將真正的意圖拿出來替換將其Intent的意圖替換為要打開的Activity
  4. 2中handleMessage()其實就是將startActivity()方法進行攔截,判斷如果是未登錄狀態(tài),則將真正要跳轉(zhuǎn)的ActivityExtra內(nèi)拿出來進行跳轉(zhuǎn),已登錄則不替換Intent意圖跳轉(zhuǎn)。
    在這里插入圖片描述

3 總結(jié)

文章只做核心HookAMS代碼思路的分析,這里是項目地址,小伙伴可以自行下載查看,別忘了點Star喔,謝謝!!

http://www.risenshineclean.com/news/11627.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)合同圖片網(wǎng)店推廣方案策劃書
  • 煙臺h5網(wǎng)站建設(shè)公司游戲代理免費加盟
  • 專門做恐怖電影網(wǎng)站谷歌排名推廣
  • 做網(wǎng)站的顏色搭配網(wǎng)絡(luò)優(yōu)化seo薪酬
  • 查詢網(wǎng)站備案號qq排名優(yōu)化網(wǎng)站
  • 網(wǎng)站服務(wù)器 內(nèi)存seo怎么才能做好
  • 做網(wǎng)站的如何找客戶平臺引流推廣怎么做
  • 做網(wǎng)站可以賺錢嗎?atp最新排名
  • 農(nóng)村網(wǎng)站建設(shè)百度上怎么免費開店
  • 設(shè)置本機外網(wǎng)ip做網(wǎng)站技術(shù)培訓(xùn)
  • 做線下活動的網(wǎng)站泉州百度關(guān)鍵詞排名
  • 可做生物試卷的網(wǎng)站站長統(tǒng)計在線觀看
  • 高端網(wǎng)站開發(fā)企業(yè)百度百度一下
  • 有做自由行包車的網(wǎng)站qq群推廣網(wǎng)站免費
  • 大理北京網(wǎng)站建設(shè)app開發(fā)定制
  • 青島app網(wǎng)站開發(fā)企業(yè)網(wǎng)站建設(shè)價格
  • 唐河做網(wǎng)站網(wǎng)站推廣鄭州
  • 如何選擇贛州網(wǎng)站建設(shè)網(wǎng)站關(guān)鍵詞排名服務(wù)
  • 長沙app下載seo網(wǎng)站推廣實例
  • 網(wǎng)站運營隊伍與渠道建設(shè)網(wǎng)站的宣傳與推廣
  • wordpress問答社區(qū)模板合肥seo整站優(yōu)化網(wǎng)站
  • 自己做pc網(wǎng)站建設(shè)seo教學(xué)視頻教程
  • 開80服務(wù)器怎么做網(wǎng)站網(wǎng)站設(shè)計的基本原則
  • 泰州做網(wǎng)站哪家好自動化測試培訓(xùn)機構(gòu)哪個好
  • 建站時網(wǎng)站地圖怎么做網(wǎng)絡(luò)推廣員一個月多少錢
  • 用php做網(wǎng)站用什么框架百度域名查詢官網(wǎng)
  • 做網(wǎng)站開發(fā)有哪些優(yōu)點呢百度賬號快速注冊
  • 做淘寶網(wǎng)站如何提取中間的提成2024年新聞?wù)?/a>
  • 北京景觀設(shè)計公司長春網(wǎng)絡(luò)優(yōu)化哪個公司在做
  • 軟件工程就業(yè)方向什么是網(wǎng)站推廣優(yōu)化