Android上玩玩Hook:Cydia Substrate實戰

來源:互聯網
上載者:User

標籤:

作者簡介:周聖韜,百度進階Android開發工程師,部落格地址:http://blog.csdn.net/yzzst

瞭解Hook

還沒有接觸過Hook技術讀者一定會對Hook一詞感覺到特別的陌生,Hook英文翻譯過來就是“鉤子”的意思,那我們在什麼時候使用這個“鉤子”呢?

我們知道,在Android作業系統中系統維護著自己的一套事件分發機制。應用程式,包括應用觸發事件和後台邏輯處理,也是根據事件流程一步步的向下執行。而“鉤子”的意思,就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子勾上事件一樣。並且能夠在勾上事件時,處理一些自己特定的事件。如所示:

Hook的這個本領,使它能夠將自身的代碼“融入”被勾住(Hook)的程式的進程中,成為目標進程的一個部分。我們也知道,在Android系統中使用了沙箱機制,普通使用者程式的進程空間都是獨立的,程式的運行彼此間都不受幹擾。

這就使我們希望通過一個程式改變其他程式的某些行為的想法不能直接實現,但是Hook的出現給我們開拓瞭解決此類問題的道路。當然,根據Hook對象與Hook後處理的事件方式不同,Hook還分為不同的種類,如訊息Hook、API Hook等。

Cydia Substrate架構

如果使用過蘋果手機的使用者應該對Cydia Substrate架構來說一點都不會陌生,因為Cydia Substrate架構為蘋果使用者提供了越獄相關的服務架構。

Cydia Substrate原名MobileSubstrate(類庫中都是以MS開頭),作者為大名鼎鼎的Jay Freeman(saurik)。

當然,Cydia Substrate也推出了Android版。Cydia Substrate是一個代碼修改平台,它可以修改任何主進程的代碼,不管是用Java還是C/C++(native代碼)編寫的。

安裝Cydia Substrate架構Android本地服務

首先就是在Android裝置中安裝Cydia Substrate架構的本地服務應用substrate.apk,我們可以在其官網下載到。

當然,我們安裝substrate後,需要“Link Substrate Files”(串連本地的Substrate服務檔案),這一步是需要Root許可權的,串連後還需要重啟裝置才能夠生效。

下載使用Cydia Substrate庫 

Cydia Substrate官方建議在Android SDK Manager中添加它們外掛程式地址的方式進行更新下載。如:在使用者自訂網址中添加http://asdk.cydiasubstrate.com/addon.xml。

通過使用Android SDK Manager工具下載完Cydia Substrate架構後,其儲存於目錄${ANDROID_HOME}\sdk\extras\saurikit\cydia_substrate下。

但是,由於Android SDK Manager在國內使用起來存在很多的限制,下載的時候也不是非常穩定,所以還是建議大家直接去官網下載開發庫。 

下載完成後,將得到的所有檔案(很多的jar包與so庫),都拷貝都Android項目下的libs檔案夾中,就可以直接使用了。其中的substrate.h標頭檔與lib檔案夾下的so檔案是提供在使用NDK進行原生Hook程式開發中的函數支援庫。

TIPS:Cydia Substrate架構對於inline Hook的操作目前還是存在一些bug,使用的時候可能會出現崩潰的現象,部分使用了國內定製的ROM的裝置在使用Cydia Substrate架構時會造成裝置無法重新啟動或無法Hook的現象。
Cydia Substrate怎麼用?

Cydia Substrate怎麼用?其實很簡單,Cydia Substrate提供了三個靜態方法工具類,我們只需要學會使用它就好 。

 

  1. MS.hookClassLoad    拿到指定Class載入時的通知
  2. MS.hookMethod   使用一個Java方法去替換另一個Java方法
  3. MS.moveUnderClassLoader   使用不同的ClassLoder重載對象

 

具體說明如下:

 

/** * Hook一個指定的Class *  * @param name Class的包名+類名,如android.content.res.Resources * @param hook 成功Hook一個Class後的回調 */void hookClassLoad(String name, MS.ClassLoadHook hook);/** * Hook一個指定的方法,並替換方法中的代碼 *  * @param _class Hook的calss * @param member Hook class的方法參數 * @param hook 成功Hook方法後的回調 * @param old Hook前方法,類似C中的方法指標 */void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old);/** * Hook一個指定的方法,並替換方法中的代碼 *  * @param _class Hook的calss * @param member Hook class的方法參數 * @param alteration */void hookMethod(Class _class, Member member, MS.MethodAlteration alteration);/** * 使用一個ClassLoader重載一個對象 *  * @param loader 使用的ClassLoader * @param object 帶重載的對象 * @return 重載後的對象 */<T> T moveUnderClassLoader(ClassLoader loader, T object);

 

開始實戰(廣告注入)

聽到這個題目,我估計很多打包黨也已經迫不及待了,稍安勿躁。靠廣告是賺不了大錢的,筆者也是一個打包黨。程式員還是以成長發展為主,一時的快錢帶會讓你在編程的路上越走越遠。

回到正題,使用Cydia Substrate架構我們能夠任意的Hook系統中的Java API,當然其中也用到了很多的反射機制,那麼除了系統中給開發人員提供的API以外,我們能否也Hook應用程式中的一些方法呢?答案是肯定的。下面我們就以一個實際的例子講解一下如何Hook一個應用程式。

下面我們針對Android作業系統的瀏覽器應用,Hook其首頁Activity的onCreate方法(其他方法不一定存在,但是onCreate方法一定會有),並在其中注入我們的廣告。根據上面對Cydia Substrate的介紹,我們有了一個簡單的思路。

首先,我們根據某廣告平台的規定,在我們的AndroidManifest.xml檔案中填入一些廣告相關的ID。並且在AndroidManifest.xml檔案中填寫一些使用Cydia Substrate相關的配置與許可權。當然,我們還會聲明一個廣告的Activity,並設定此Activity為背景透明的Activity,為什麼設定透明背景的Activity,如:

好了,下面我們就來實際操作一下。

其AndroidManifest.xml檔案的部分內容如下所示:

 

<!-- 廣告相關的許可權  --><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.GET_TASKS" /><!-- 加入substrate許可權  --><uses-permission android:name="cydia.permission.SUBSTRATE" /><application    android:allowBackup="true"    android:icon="@drawable/ic_launcher"    android:label="@string/app_name"    android:theme="@style/AppTheme" >    <!-- 廣告相關參數 -->    <meta-data        android:name="APP_ID"        android:value="c62bd976138fa4f2ec853bb408bb38af" />    <meta-data        android:name="APP_PID"        android:value="DEFAULT" />    <!-- 聲明substrate的注入口味Main類 -->    <meta-data        android:name="com.saurik.substrate.main"        android:value="com.example.hookad.Main" />    <!-- 透明無動畫的廣告Activity -->    <activity        android:name="com.example.hookad.MainActivity"        android:theme="@android:style/Theme.Translucent.NoTitleBar" >        <intent-filter>            <action android:name="android.intent.action.VIEW" />            <category android:name="android.intent.category.DEFAULT" />            <!-- 廣告的action  -->            <action android:name="com.example.hook.AD" />        </intent-filter>    </activity></application>

 

對於Cydia Substrate的主入口Main類,依照之前的步驟建立一個包含有initialize方法的Main類。

這個時候我們希望使用MS.hookClassLoad方式找到瀏覽器首頁的Activity名稱。

這裡我們使用adb shell下使用dumpsys activity命令找到瀏覽器首頁的Activity名稱為com.android.browser.BrowserActivity。

使用MS.hookClassLoad方法擷取了BrowserActivity之後再hook其onCreate方法,在其中啟動一個含有廣告的Activity。Main類的代碼如下所示:

 

public class Main {    /**     * substrate 初始化後的入口     */    static void initialize() {        //Hook 瀏覽器的主Activity,BrowserActivity        MS.hookClassLoad("com.android.browser.BrowserActivity", new MS.ClassLoadHook() {            public void classLoaded(Class<?> resources) {                Log.e("test", "com.android.browser.BrowserActivity");                // 擷取BrowserActivity的onCreate方法                Method onCreate;                try {                    onCreate = resources.getMethod("onCreate", Bundle.class);                } catch (NoSuchMethodException e) {                    onCreate = null;                }                if (onCreate != null) {                    final MS.MethodPointer old = new MS.MethodPointer();                    // hook onCreate方法                    MS.hookMethod(resources, onCreate, new MS.MethodHook() {                        public Object invoked(Object object, Object...args) throws Throwable {                            Log.e("test", "show ad");                            // 執行Hook前的onCreate方法,保證瀏覽器正常啟動                            Object result =  old.invoke(object, args);                            // 沒有Context                            // 執行一個shell 啟動我們的廣告Activity                            CMD.run("am start -a com.example.hook.AD");                            return result;                        }                    }, old);                }            }        });    }}

 

對於啟動的廣告MainActivity,在其中就是彈出一個插屏廣告。當然可也可是其他形式的廣告或者浮層,內容比較簡單這裡不做示範了。對整個項目進行編譯,運行。這個時候我們重新啟動Android內建的瀏覽器的時候發現,瀏覽器會彈出一個廣告彈框。

從上面的圖片我們可以看出來了,之前我們設定插屏廣告MainActivity為無標題透明(Theme.Translucent.NoTitleBar)就是為了使得彈出來的廣告與瀏覽器融為一體,讓使用者感覺是瀏覽器彈出的廣告,也是惡意廣告程式為了防止自身被卸載掉的一些通用隱藏手段。

這裡示範的注入廣告是通過Hook指定的Activity中的onCreate方法來啟動一個廣告Activity。當然,這裡我們示範的Activity只是簡單的彈出來了一個廣告。如果啟動的Activity帶有惡意性,如將Activity做得與原Activity一模一樣的釣魚Activity,那麼對於行動裝置使用者來說是極具詐騙。

寫在最後

其實我不想發這篇文章,我做過廣告打包黨,深知這又為各個地下掘金的打包黨提供了思路。但,Cydia Substrate不僅僅是為了對廣告進行注入而生,希望大家多多挖掘思路,以共同學習提升為主。

Android上玩玩Hook:Cydia Substrate實戰

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.