「個人能量無窮無盡,只有強大暗能量才能統治Android界。
受屎吧!!! =≡Σ((( つ•̀ω•́)つ 」
-- 來自暗世界android工程師java
前言:android
這是黑科技系列的第二篇,是Android知識正營中較有深度難理解的知識。若是你是一個初學者,牽扯的知識太深,文中沒有從零講起。皆是拔雲見霧的帶你們看。能夠先收藏起來,往後慢慢系統性的對着文中的Github源碼寫一遍。git
這個世界上手機有三大系統,蘋果、 安卓、 中國安卓 。本篇強烈呼籲你們不要去作哪些違反用戶體驗的黑科技功能,研究研究玩玩就行了啦。全當增加技術,在真實的項目開發中儘可能能不用就不要用得好。道理你們都懂的。github
那些年Android黑科技②:欺騙的藝術windows
hook一詞最先我是在用windows的時候學習到的。當時用來作鍵盤監聽。懵逼的我沒法理解這個翻譯叫「鉤子」東西究竟是什麼鬼。網絡
那麼先說下hook究竟是在幹嗎。咱們能夠把hook看成代理模式或劫持來理解。在一個方法的前或後動態插入一段咱們的邏輯事情,甚至改變本來方法在執行前的參數,返回後的參數。總之能夠hook任意java寫的代碼,修改替換apk內部的資源文件。一摸索到如今到android中hook已知有兩種。這兩種分別是:app
xposed是一個hook的框架。通常是用來作手機插件的。好比修改系統電池圖標、信號、按鍵交換位置等等,可是也有人用來作一些應用的破解等。咱們先說下xposed原理。只有明白原理了才知道這個東西是怎麼玩的。框架
apk在android運行的時候是經過ActivityManagerService(如下簡稱AMS)發送Socket給Zygote進程進行通訊。由Zygote進程fork一個子進程來啓動咱們的apk程序。
AMS -> Socket-> Zygote->apk啓動
重點來了。下面將是android Xposed Hook的核心原理。仔細看。
在android運行環境中,Zygote進程是全部虛擬機進程的父親,Zygote進程在開機初始化的時候會建立一個虛擬機,AMS發消息給Zygote建立的時候其實是copy一份虛擬機的實例在子進程中。同時在初始化的時候還會註冊一些android核心Jni的庫放在虛擬機實例內提供上層api調用。fork出的虛擬機會共享這些jni類庫。 那麼實際上XPosed就是在root後對替換/system/bin/app_process並將注入XposedBridge.jar。app_process是用來控制Zygote的,經過替換成修改後的 app_process可使Zygote進程加載到咱們的XposedBridege.jar。而這個庫就是用來作動態Hook java代碼形成劫持的。
插件也是同樣用android Studio寫就能夠了,只是咱們不須要任何活動容器。
1 .新建一個工程在gradle裏添加xposedApi依賴
dependencies { provided ‘de.robv.android.xposed:api:++’ }
2.在AndroidManifest中配置聲明標籤讓xposed殼認識你的插件
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposeddescription" android:value=" example " /> <meta-data android:name="xposedminversion" android:value="22" /> </application>
3.使用xposed提供的接口作具體的hook邏輯
4.串改變量示例
public class Demo implements IXposedHookInitPackageResources{ @Override public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam resparam) { //判斷當前須要hook的包名 if (resparam.packageName.equals("com.android.xxxx")) { //調用setReplacement方法替換名爲aaa的變量值爲false resparam.res.setReplacement(resparam.packageName, "String", "aaa", 「123」); } }
5.在工程裏的assets目錄下建立名稱爲xposed_init的配置文件(注意是無格式的文本),在該文件裏寫入你插件的包名。xposed框架會在設備開機的時候讀取的插件。
com.bolex.xxx
6.打包出來 安裝到手機上 而後在Xposed裏面勾上你的插件重啓便可
Xposed框架在玩機的發燒友手機上號稱是必裝的神器。做爲android的咱們實際上是有能力本身寫插件的。同時若是咱們是作付費軟件和金融軟件的對Xposed仍是要作一些防範。好比加固、混淆你的應用讓壞人無法很輕鬆的知道你的代碼邏輯。
相信作過android的同窗就算沒有用過反射也聽過。咱們知道反射能夠在不修改源代碼的狀況下對私有方法和成員變量調用或修改。同上一個章節講到的hook技術同樣。除了Xposed的方式之外,反射自己也能作hook。
一般有兩種方式動態代理、靜態代理,本文使用動態代理來說解,因此若是你不明白動態代理的原理能夠去補補這塊的知識。簡單來講就是動態代理會利用被被代理對象的接口,經過反射模擬一份同樣的接口來實現代理。
能夠作的事情:
原理剖析:
android系統層會提供接口的形式來實現一些回調操做。咱們經過反射去獲取持有接口引用的對象。而後偷樑換柱的將本身的接口塞進去替換原有的對象。致使系統調用接口的時候是調用咱們換過的代理對象。咱們在代理對象內部再去調用本來的對象的接口方法,這樣就能夠作到hook的目的。
好比咱們經常使用的 OnClickListener()接口,用於點擊事件的回調。若是hook View的ListenerInfo對象名稱爲mListenerInfo。就能夠攔截點擊或者在點擊以前和以後作一些咱們想作的事情。下面咱們講一個高深且好玩一點的案例。
先思考一個問題,爲何咱們的Activity須要在AndroidManifest.xml文件中註冊?若是不註冊能不能啓動呢?
咱們知道是AMS負責調起Activity。在啓動以前他作了些什麼事情呢?前面咱們說過實際上AMS是給Zygote發送了消息,由Zygote進程fork一個虛擬機進程來。
那麼其實在開機時Zygote進程在運行時第一個fork的進程是system_server的進程,這個服務用於管理系統級別的服務啓動。
System_server進程包含了如下頂級的系統服務
既然AMS承載了調用邏輯。咱們是否能夠對AMS動刀子來作到不註冊Activity也能直接啓動呢?
這裏爲何咱們前面要講system_server服務,緣由是咱們要知道AMS進程不在咱們本身的應用內,而是獨立的遠程服務進程。java層的上的反射是沒法作到跨進程的。因此咱們能夠在本身的應用內利用AIDL的特性拿代理對象,去欺騙AMS服務。
流程以下:
這裏咱們經過反射獲取到AMS的代理本地代理對象Hook之後動態串改Intent爲已註冊的來躲避檢測
經過動態代理實現對startActivity中的Intent串改,具體邏輯見代碼和註釋。
hook ActivityThread 中的 handle 在這裏咱們須要替換咱們未被註冊的Activity Intent
攔截啓動消息
替換咱們真實要被啓動的Intent
封裝之後咱們ASMHook將變得很是簡單,簡單到一行代碼就能夠實現不註冊的狀況下啓動Activity。
其中HostActivity是咱們的殼,OtherActivity是未被註冊的。咱們能夠像平時正常調用API的條件下直接使用startActivity了。
結果 啓動了。
哎媽呀,好膩害的樣子,喘口氣看看剛剛發生了什麼事情。
獻上封裝好的HookAMS菊花(GitHubDemo):https://github.com/BolexLiu/AndroidHookStartActivity
做者:香脆的大雞排 連接:http://www.jianshu.com/p/2ad105f54d07 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。