1. 程式人生 > >反射+代理實現 API Hook(以 ActivityManager 為例)

反射+代理實現 API Hook(以 ActivityManager 為例)

最近看Android招聘資訊,發現一個自己不太會的點 hook 機制,查了一下資料,現在整理一下。特別感謝acxingyun同學提供了詳細的姿勢。點選地址

什麼是 Hook

hook 翻譯過來是鉤子的意思。 目的就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子鉤上事件一樣,並且能夠在鉤上事件時,處理一些自己特定的事件。而代理模式正好可以做到這種效果。

代理物件

瞭解了hook的目的,下面就是怎樣勾上整個事件,來監測事件的每一步。
拿 Activity 來舉例,Activity 的相關的啟動方法在IActivityManager接口裡面都已經定義好了,但正常情況下我們無法獲取相關的物件的資訊,更無法修改,所以在這裡我們要借用反射來獲取到相應的 Class 物件,將IActivityManager的例項替換為我們自己的代理物件,在代理物件裡面去做我們想做的事情。
無圖無真相。上圖
image

ActivityManagerNative 的例項持有一個Singleton<IActivityManager>型別的物件 gDefault,gDefault持有IActivityManager的例項mInstance,
正常狀態持有的mInstance例項 我們通過 Proxy.newProxyInstance() 做出一個代理物件來,再利用反射機制重新給 gDefault物件,這樣我們就能在InvocationHandler中監聽整個事件並處理。

具體實現

public class APIHook {

    /**
     * ActivityManager 替換為代理
     * @throws
ClassNotFoundException * @throws NoSuchFieldException * @throws IllegalAccessException */
public void hookAM() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Class<?> amnClass = Class.forName("android.app.ActivityManagerNative"); //獲取單例物件 Singleton<IActivityManager> ,變數名 gDefault 私有
Field gDefaultField = amnClass.getDeclaredField("gDefault"); //禁止JAVA 進行語言訪問檢查,private 等修飾的就可以訪問操作了 gDefaultField.setAccessible(true); //If the underlying field is a static field, the obj argument is ignored; it may be null. //靜態屬性,直接傳入 Null。獲取ActivityManagerNative 中的 gDefault Object gDefault = gDefaultField.get(null); Class<?> singletonClass = Class.forName("android.util.Singleton"); Field mInstanceField = singletonClass.getDeclaredField("mInstance"); mInstanceField.setAccessible(true); //呼叫 Singleton 的 get方法 取出 instance 物件 //instance 物件即 ActivityManager Object instance = mInstanceField.get(gDefault); //建立代理 handler ActivityManagerHandler handler = new ActivityManagerHandler(instance); //反射 IActivityManager介面 Class 檔案 Class<?> amClass = Class.forName("android.app.IActivityManager"); //建立代理物件 Object amProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{amClass}, handler); //將gDefault中的 Instance 置換為代理 mInstanceField.set(gDefault,amProxy); } /** * 代理物件回撥 */ private class ActivityManagerHandler implements InvocationHandler { private Object am; public ActivityManagerHandler(Object am) { this.am = am; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Log.e("APIHook","正在呼叫的方法--->"+method.getName()); return method.invoke(am,args); } } }

知識點:對於 private 修飾的變數,我們需要呼叫Field.setAccessible(true);來禁止 JAVA 語法檢查才能給變數賦值喲

這個程式碼是可以直接用的,把玩時在 Application 的 onCreate 中呼叫

new APIHook().hookAM();

就寫到這裡啦,權當又複習了一遍代理和反射,大家一起加油啊

相關推薦

反射+代理實現 API Hook ActivityManager

最近看Android招聘資訊,發現一個自己不太會的點 hook 機制,查了一下資料,現在整理一下。特別感謝acxingyun同學提供了詳細的姿勢。點選地址 什麼是 Hook hook 翻譯過來是鉤子的意思。 目的就是在事件傳送到終點前截獲並監控事件的傳輸

[GIS演算法] DEM相關處理 - 視窗分析平均值| 裁剪 - C語言實現

#include<stdio.h> #include<stdlib.h> typedef struct{ double x0,y0; //左下角點的座標值 int dx,dy; //柵格單元大小 int ycount,xcount; //行列號 doub

docker + nginx 實現web應用部署方案react

1. 安裝docker 使用yum install docker -y,此處不再詳細說明 2. 配置react專案 可以使用cmss-react-app,構建完成後可以看到如下的專案目錄 在根目錄下執行npm install & npm run build

Keras中實現模型載入與測試mnist

 需要安裝cv2 安裝h5py的命令如下(模型載入模組): sudo pip install cython sudo apt-get install libhdf5-dev sudo pip 

通過JDBC進行簡單的增刪改查MySQL

mage ron end main exce javax xtend 探索 rman 通過JDBC進行簡單的增刪改查(以MySQL為例) 目錄 前言:什麽是JDBC 一、準備工作(一):MySQL安裝配置和基礎學習 二、準備工作(二):下載數據庫對應的jar包並

自定義shell終端提示符及顏色 Centos

工作目錄 con bashrc func global 目錄 藍色 顯示 inux Linux修改Shell命令提示符及顏色 1. Linux登錄過程中加載配置文件順序: /etc/profile → /etc/profile.d/*.sh → ~/.bash_pro

11代碼重用思想遊戲

class 我想 就是 cas == 點擊 ~~ 重用 body 1)情況說明:      假如 我想在我的遊戲上 顯示以惡搞菜單 然後這個菜單 顯示1和2           要是我用鼠標點擊1 ,就可以玩 貪吃蛇遊戲           要是我用鼠標點擊

通過JDBC進行簡單的增刪改查MySQL轉載

IE trac archive solver ttl 賦值 TP 定義 for 轉載:https://www.cnblogs.com/wuyuegb2312/p/3872607.html 目錄 前言:什麽是JDBC 一、準備工作(一):MySQL安裝配置和基礎學習 二、準備

阿裏雲修改主機名centOS

主機 str name 按鍵 ID In 保存 ray ike 需要更改配置文件生效,修/etc/sysconfig/network裏的 HOSTNAME=主機名(可自定義),重啟生效。 如何修改? 1.[root@aliyunbaike ~]# cd /etc/sysco

OpenGL學習 著色器渲染Android

back lse setw %d 編譯 clas ddr attr type 一、Android平臺上下文環境的創建及初始化 1. 首先實例化Android上下文環境,即EGL的初始化。 bool EGLCore::init(EGLContext sharedContex

linux正則表達式,grep

ant per egrep 大小寫 則表達式 spa 表示 中括號 第四章 第一章 基礎正則表達式^word 匹配以word開頭的內容word$ 匹配以我word結尾的內容^$ 表示空行. 代表有且只代表任意一個字符\ 轉義符號,例如. 就只代表點本身,讓有著特殊身份意義

webpack 構建多頁面應用regularjs

webpack-regular github原始碼: https://github.com/fisher-zh/webpack-regular 基於webpack構建的多頁面網站開發環境。 webpack在前端開發的過程中逐漸扮演著越來越重要的角色,在使用vue

WLC-WLC升級2504

1、WLC升級需要按照升級路徑來操作,低版本到高版本的跨度太大,往往需要升級到中間版本,有時候還涉及到FUS。 2、我們升級,一般使用的筆記本上執行的TFTP/FTP  server。 需要注意:筆記本防火牆的影響。 如下是一個升級的簡單示例: 注意,筆記本防火牆因素。(Cisc

天地圖專題七:行政區域標記,熱力圖廣西

天地圖方面的文章已很久不寫。 主要是因為上一個專案結束,基本就不用天地圖了。用百度地圖的可能更大一些。   最近上個專案甲方想搞一個類似熱力圖,熱點圖的東西。在天地圖API上沒有找到類似的直接畫熱力圖的介面,只好用了一些替代的方法。 天地圖行政區域,行政區劃直接介面也沒找到,用

遞迴與迭代的聯絡以及優缺點c++

 1.遞迴的定義: 程式直接或間接的呼叫自身的方法。 遞迴演算法的特點:(1) 遞迴就是在過程或函式裡呼叫自身。(2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。(3) 遞迴演算法解題通常顯得很簡潔,但遞迴演算法解題的執行效率較低。所以一般不提倡用遞迴演算法設計程式。(4) 在遞迴呼叫

CMakeList.txt在大型檔案應用前端

基本的CMakeLists.txt並不難,主要有生成庫、生成執行檔案、連結二者以及找庫、找標頭檔案、生成執行檔案、連結庫和執行檔案兩種方法組成。 但是遇到大型庫的編寫,目標是生成一個新的大型庫myslam,生成執行檔案、連結二者。需要提前宣告生成執行檔案在bin,庫在lib中,並把OPenCV、

jenkins介紹及安裝步驟centos7

dha 連接 -i rman 發布 zone 安裝步驟 ges 分享圖片 一、 介紹Jenkins是一個開源軟件項目,是基於Java開發的一種持續集成工具,用於監控持續重復的工作,旨在提供一個開放易用的軟件平臺,使軟件的持續集成變成可能二、 作用1、持續的軟件版本發布/

Map集合遍歷的方式HashMap

color reac pri 循環 next code 方式 new 利用 環境:jdk1.8 HashMap的遍歷方式有多種,下面將會一一列出。 首先我們先在HashMap中添加幾個鍵值對。 HashMap<Integer, String> map = ne

雲端計算生產環境架構效能調優和遷移套路總結 AWS

最近完成了一個雲端計算平臺應用的架構調優。客戶是一個 Wordpress + MySQL 的站點,剛從本地資料中心遷移到了 AWS,由於團隊技能限制,無法充分發揮雲端計算的優勢。加之應用程式在夜間高流量時段崩潰,架構優化和遷移迫在眉睫。本文以這次架構遷移經驗為例,介紹雲端計算架構優化遷移的基本步驟和

繪製指定屬性圖形2.0

package javaPractice; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class Point { public static void