這個Hook
不是鄧紫棋要給你唱的Hook
哦!而是在程序界流傳的強大祕技-Hook
函數,Hook
原意是指鉤子
,它表示的就是在某個函數的上下文作自定義的處理來實現咱們想要的黑科技
。 在不少技術領域都存在的這種Hook
技術,好比下面這些:java
在Python
的Web框架
中,如Django
,Flask
都存在這種Hook
技術,能夠在請求的上下文
,應用的上下文
作自定義操做。android
在Scrapy
框架中,能夠自定義MiddlerWare
,在請求
,解析
的時候作自定操做。編程
在K8S
編排框架中,咱們也能夠在執行某些函數的上下文中插入Hook
函數,這也是和Web
框架同理 而今天咱們講解的是關於Android
的Hook
技術,而有一款神器可以幫助咱們快速地開發Hook
模塊,也就是Xposed
框架。其實網上的關於Xposed
模塊編寫的教程可謂是一抓一大把。但因爲時間的推移,不少工具和方法都發生了變化(如Eclipse
退出安卓編程舞臺,AndroidStudio
不斷升級致使其一些設置也隨之變化等)也正所以,網上的教程每每有一些時限性,好比現現在 provide
這個關鍵字已經被捨棄了卻仍有人在用,還有些說要把jar
包放到lib
文件夾而非libs
文件夾……種種錯誤或者落伍的教程對新手產生了很大的誤導。以前也搞過一陣子Xposed
框架,而今天在從新部署環境的時候參考某些教程的時候也遇到了不少的坑,因此想從新結合最新的配套工具寫個小教程,主要講解的如下兩個方面:segmentfault
Xposed
框架介紹以及原理api
Xposed
框架實戰bash
Xposed
框架介紹以及原理 Xposed
是Github
上rovo89
大佬設計的一個針對Android平臺
的動態劫持項目,經過替換/system/bin/app_process
程序控制Zygote
進程,使得app_process
在啓動過程當中會加載XposedBridge.jar
這個jar
包,從而完成對Zygote
進程及其建立的Dalvik虛擬機
的劫持。 由於Xposed
工做原理是在/system/bin
目錄下替換文件,在install
的時候須要root
權限,可是運行時不須要root
權限。 看到這裏不少人會很懵,什麼是Zygote
?簡單來講在Android
系統中,應用程序進程都是由Zygote
進程孵化出來的,而Zygote
進程是由Init
進程啓動的。Zygote
進程在啓動時會建立一個Dalvik
虛擬機實例,每當它孵化一個新的應用程序進程時,都會將這個Dalvik
虛擬機實例複製到新的應用程序進程裏面去,而一個應用程序進程被Zygote
進程孵化出來的時候,不只會得到Zygote
進程中的Dalvik
虛擬機實例拷貝,還會與Zygote
一塊兒共享Java運行時
庫。這也就是能夠將XposedBridge
這個jar
包加載到每個Android
應用程序中的緣由。XposedBridge
有一個私有的Native(JNI)
方法hookMethodNative
,這個方法也在app_process
中使用。這個函數提供一個方法對象利用Java
的Reflection
機制來對內置方法覆寫。。。。等等這些都會借鑑各路大神的思路和分析,總而言之,就是從底層替換方法,可讓咱們在不修改APK
源碼的狀況下,經過本身編寫的模塊來影響程序運行的框架服務,實現相似於自動搶紅包、微信消息自動回覆等功能。 其實,從本質上來說,Xposed
模塊也是一個Android
程序。但與普通程序不一樣的是,想要讓寫出的Android
程序成爲一個``Xposed 模塊,要額外多完成如下四個硬性任務:微信
一、讓手機上的xposed框架知道咱們安裝的這個程序是個xposed模塊。
二、模塊裏要包含有xposed的API的jar包,以實現下一步的hook操做。
三、這個模塊裏面要有對目標程序進行hook操做的方法。
四、要讓手機上的xposed框架知道,咱們編寫的xposed模塊中,哪個方法是實現hook操做的。
複製代碼
這就引出我即將要介紹的四大件(與前四步一一對照):網絡
一、AndroidManifest.xml
二、XposedBridgeApi-xx.jar 與 build.gradle
三、實現hook操做的具體代碼
四、xposed_Init
複製代碼
牢記以上四大件,按照順序一個一個實現,就能完成咱們的第一個Xposed模塊編寫。以上的原理咱們大體就介紹這麼多,下面咱們實戰開始吧!架構
Xposed
框架實戰IDE
是
Android Studio
,首先打開
AndroidStudio
(以版本
3.4.2
爲例,還在用老版本的請升級),創建一個工程,提示咱們選擇「
Activity
」,那就選一個
Empty Activity
吧。(這個是模塊的界面,隨意選擇便可)。
Xposed
模塊 咱們能夠把項目查看方式設置爲Project
模式,以方便查看。而後在 「項目名稱/app/src/main/
」目錄下找到AndroidManifest.xml
,打開這個文件,並在指定位置插入如下三段代碼:app
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="微信hook" />
<meta-data
android:name="xposedminversion"
android:value="53" />
複製代碼
效果如圖:
Run
運行
App
。
Device
設備來運行這個
App
Android Studio
,鏈接的辦法不少,包括經過
USB鏈接(物理鏈接)
和
Wifi鏈接(也就是網絡鏈接)
,咱們爲了節省方法,就採用物理鏈接,Ps: 有關於遠程鏈接能夠參考
這篇文章,鏈接好咱們的實體機以後咱們點擊這裏
Android Studio
鏈接手機,鏈接好咱們就能夠看到在
Logcat
選項裏面看到咱們的手機運行的日誌報告。
Run
以後會提示咱們的手機安裝咱們剛纔剛寫的
Apk
,不過個人手機提示
安裝時驗證超時
,不能直接安裝,苦惱,之後選手機也要選個正常的。關於
Android Studio
安裝
Apk
失敗的緣由能夠參考
這篇文章,既然咱們不能直接安裝
Apk
,咱們就使用
adb
直接來安裝
Xposed
框架中勾選咱們剛纔的模塊,而後咱們重啓一下
Xposed
框架,就能夠啦
Xposed
框架已經認出了咱們寫的程序。但先別高興太早——雖然框架已經以爲他是一個
Xposed
模塊了,但咱們本身內心清楚,這個模塊還啥都不會幹呢。下一步,咱們讓這個模塊長點本事。
咱們知道,Xposed
模塊主要功能是用來Hook
其餘程序的各類函數。可是,如何讓前一步中的那個「一貧如洗」的模塊長本事呢?那就要引入 XposedBridgeApi.jar
這個包,你能夠理解爲一把兵器,模塊有了這把寶刀才能施展出Hook
本領。不少之前的老教程都須要手動下載諸如XposedBridgeApi-54.jar
、 XposedBridgeApi-82.jar
等jar
包,而後手工導入到libs
目錄裏,才能走下一步道路,而這些jar
沒有官方的渠道來安裝,一般只是一個傳一個的,都不知道變成了什麼版本。其實在最新的AndroidStudio 3.1
之後,咱們徹底不用這麼麻煩,只須要多寫一行代碼,就讓AndroidStuido
自動給咱們配置XposedBridgeApi.jar
!下面操做開始: 在 「項目名稱/app/src/main/」
目錄下找到build.gradle
,在圖示位置加上:
repositories {
jcenter()
}
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'
複製代碼
這句代碼是告訴AndroidStuido
使用jcenter
做爲代碼倉庫,從這個倉庫裏遠程尋找 de.robv.android.xposed:api:82
這個API
。這個網上不多有Xposed
教程介紹它的!(咱們不用本身找XposedBridgeApi.jar
了。注意!此處要用compileOnly
這個修飾符!網上有些寫的是provide
,可是如今已經停用了!坑人啊!) 寫完以後, build.gradle
會提示文件已經修改,是否同步。點擊 「sync now」
,同步便可:
repositories { jcenter()}
這個步驟了,改作這個步驟:手動下載
XposedBridgeApi-82.jar
,拖放到
「項目名稱/app/libs/」
裏面(不是網上說的單獨創建
lib
文件夾,那是好久之前的故事了!),而後右鍵
「Add As Library」
自行添加這個
jar
包。而
compileOnly ‘de.robv.android.xposed:api:82′
和
compileOnly ‘de.robv.android.xposed:api:82:sources’
這兩句仍然照常添加。】 好了,咱們如今已經搞好了全部的準備工做。下一步,就要開始「施展刀法」(編寫
hook
代碼)了。
hook
操做的具體代碼 在「施展刀法」(編寫hook
代碼)以前,咱們先要立一個靶子。在界面上畫一個按鈕,並在MainAcitiviy
裏寫代碼以下:
package com.example.wx;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, toastMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public String toastMessage() {
return "我未被劫持";
}
}
複製代碼
而在頁面佈置的文件中,也就是activity_main.xml
中增長以下紅框的代碼
MainActivity
界面有個按鈕,點擊按鈕後會彈出一個
toast
提示,該提示的內容由
toastMessage()
方法提供,而
toastMessage()
的返回值爲
「我未被劫持」
。 如今,咱們已經作好了咱們的
App
了,下面咱們正式開始「施展刀法」(編寫
hook
代碼) 來
hook
咱們的
MainActivity
並修改這個類的
toastMessage()
方法,讓它的返回值爲
「你已被劫持」
:
「HookTest.java」
package com.example.wx;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class HookTest implements IXposedHookLoadPackage {
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (loadPackageParam.packageName.equals("com.example.root.xposd_hook_new")) {
XposedBridge.log(" has Hooked!");
Class clazz = loadPackageParam.classLoader.loadClass(
"com.example.root.xposd_hook_new.MainActivity");
XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
//XposedBridge.log(" has Hooked!");
}
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult("你已被劫持");
}
});
}
}
}
複製代碼
IXposedHookLoadPackage
接口中的
handleLoadPackage
方法來實現
Hook
並篡改程序的輸出結果的。代碼中
「com.example.wx」
是目標程序的包名,
」com.example.wx.MainActivity」
是想要Hook的類,
「toastMessage」
是想要
Hook
的方法。咱們在
afterHookedMethod
方法(用來定義Hook了目標方法以後的操做)中,修改了
toastMessage()
方法的返回值爲「你已被劫持」。在完成代碼編寫以前,說一下爲何要
Hook toastMessage
這個方法,咱們先用
Jadx
查看一下咱們
Apk
的源代碼
Hook
的函數。 OK,以上用來
hook
的代碼編寫完畢,讓咱們進行下一步操做。
右鍵點擊 「main 」
文件夾 , 選擇new –> Folder –>Assets Folder
,新建assets
文件夾:
而後右鍵點擊 assets
文件夾, new–> file
,文件名爲xposed_init
(文件類型選text
),並在其中寫上入口類的完整路徑(就是本身編寫的那一個Hook
類),這樣,Xposed
框架就可以從這個xposed_init
讀取信息來找到模塊的入口,而後進行Hook
操做了:
好了,曙光就在前面!最後選擇禁用Instant Run
: 單擊 File -> Settings -> Build, Execution, Deployment -> Instant Run
,把勾所有去掉。 咱們從新以前的安裝Xposed
模塊的方法,運行模塊,點擊,奇蹟出現~
從上面的實戰中咱們能夠發現Hook
的基本原理以及步驟,從新看看咱們以前說的四大步,Hook
的關鍵其實咱們須要知道針對哪一個模塊的哪一個方法進行Hook
一、讓手機上的xposed框架知道咱們安裝的這個程序是個xposed模塊。
二、模塊裏要包含有xposed的API的jar包,以實現下一步的hook操做。
三、這個模塊裏面要有對目標程序進行hook操做的方法。
四、要讓手機上的xposed框架知道,咱們編寫的xposed模塊中,哪個方法是實現hook操做的。
複製代碼
像咱們這個例子很簡單,沒有特地的進行代碼混淆
以及程序入口改寫
等等,咱們尋找仍是很簡單的,通常市面上的App
都是有不少反Xposed
的行爲,咱們其實要學習的還有不少,這個小教程就當作個小入門吧。 下一篇文章和最近工做上的需求有關係,針對的是2019.10.28
以後搜狗微信關閉了在某些公衆號內搜索的功能,因此咱們想要獲取最新的公衆號文章就不能採起搜狗微信這個渠道了,網上有不少教程都在談論其餘的方法,相比較來講,仍是Hook
這個渠道是最實際的,咱們將會在以後的文章裏詳細談論,你們能夠期待一下~
「hook入門」
便可得到項目地址以及現成的Apk
前兩年在二線大廠工做,目前在創業公司搬磚
接觸方向是爬蟲和雲原生架構方面
有豐富的反爬攻克經驗以及雲原生二次開發經驗
其餘諸如數據分析、黑客增加也有所涉獵
作過百餘人的商業分享以及屢次開辦培訓課程
目前也是CSDN博客專家和華爲雲享專家
深刻理解Python的TLS機制和Threading.local()
下一代容器架構已出,Docker何去何處?看看這裏的6問6答!!
公衆號內回覆「私藏資料」便可領取爬蟲高級逆向教學視頻以及多平臺的中文數據集