XposedHook:hook敏感函數

Xposed框架

Xposed框架通過修改Android系統的源碼,並替換Android的主程序Zygote(Init 是所有Linux程序的起點,而Zygote於Android,正如它的英文意思,是所有java程序的’孵化池’),從而能夠控制Android進程的執行流程,hook java層的API。xposed的具體解析可以參考深入理解Android(三):Xposed詳解

首先在app_main.cpp中,對appRuntime.cpp進行了修改,其中onVmCreated(JNIEnv* env)修改如下:

在onVmCreate中,它將調用libxposed_dalvik.so中的xposedInitLib函數,然後再調用so中設置的onVmCreated函數。這個onVmCreated函數由xposedInitLib設置。

在app_main.cpp的main方法中,進行了對xposed的環境初始化:

最後,如果xposed框架啓用成功,那麼zygote的入口類將由以前的com.android.internal.os.ZygoteInit變成de.robv.android.xposed.XposedBridge。

下面我們按照執行流程,把相關函數分析一遍:

AppRuntime的onVmCreated,它最終會導致libxposed_dalvik.so中的onVmCreated被調用。我們直接分析最後這個onVmCreated。

然後AppRuntime裏會調用de.robv.android.xposed.XposedBridge.main函數。

所以通過調用XposedBridge.main函數,可以給APK進程的一些特定函數掛上鉤子,從而能夠監聽該函數,進而通過beforeHookedMethod和afterHookedMethod方法可以分別實現調用函數前的操作和調用函數後的操作。


Hook用到的具體函數

下面給出我在做Android惡意程序分析時需要hook的函數的一些操作,該程序參考了halfkiss的框架。

  • 用到的Xposed的函數: 首先定義一個抽象類MethodHookCallBack繼承自Xposed的XC_MethodHook類,該類有兩個方法:beforeHookedMethod(MethodHookParam param)和AfterHookedMethod(MethodHookParam param)方法,這兩個方法分別對應於要hook的函數調用之前所要執行的動作與該函數調用之後所要執行的動作。比如:
    public void beforeHookedMethod(MethodHookParam param)
    {
            Log.i("Before hook");
    }

上面的例子說明在調用要hook的函數之前打印一段log爲Before hook。

  • Xposed的hook的主函數hookMethod(Member hookMethod, XC_MethodHook callback),其中參數hookMethod表示要hook的函數,該函數可以通過java的反射機制獲得,具體怎麼獲得在下面會講到,參數callback就是前面講到的Xposed函數的XC_MethodHook類,該類主要是表示該對要hook的函數做怎樣的處理。具體的hookMethod方法如下圖所示:

由hookMethod可知,一個目標函數可以掛多個鉤子,這些鉤子由一個集合來存儲。然後我們將轉到JNI層去看看hookMethodNative幹了什麼事情。這纔是hook的核心。分析如下圖所示:

所以當apk執行被hook的函數時,實際執行的是hookMethodCallBack函數,該函數就是鉤子函數,我們來看看hookmethodCallBack函數具體是怎麼執行的,該函數在libXposed_dalvik.cpp中。

在xposedHandleHookedMethod函數中會以此執行鉤子函數,即在前面介紹的XC_MethodHook函數,然後再會執行程序的原函數。

在此,Hook需要用到的基本函數已經介紹完畢。接下來會介紹如何利用Xposed來實現hook敏感函數的操作。


hook敏感函數

  • 首先定義MethodHookCallBack類繼承自XC_MethodHook,該函數實現了beforeHookedMethod和afterHookedMethod函數,主要是獲得HookParam類,該類主要是存儲了一些MethodHookParam的一些參數。然後調用該類中beforeHookedMethod(HookParam param)或者afterHookedMethod(HookParam param)。
    public abstract class MethodHookCallBack extends XC_MethodHook {

            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                // TODO Auto-generated method stub
                super.beforeHookedMethod(param);
                HookParam hookParam = HookParam.fromXposed(param);
                this.beforeHookedMethod(hookParam);
                if(hookParam.hasResult())
                    param.setResult(hookParam.getResult());
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                // TODO Auto-generated method stub
                super.afterHookedMethod(param);
                HookParam hookParam = HookParam.fromXposed(param);
                this.afterHookedMethod(hookParam);
                if(hookParam.hasResult())
                    param.setResult(hookParam.getResult());
            }

            public abstract void beforeHookedMethod(HookParam param);
            public abstract void afterHookedMethod(HookParam param);

        }
  • 根據字符串找到要hook的函數,主要是利用java的反射函數,如果有興趣的可以去查閱一下java的反射機制,主要是通過字符串來得到相應的類,函數或變量等,具體代碼如下:
    public static Method findMethod(String className, ClassLoader classLoader, String methodName,
                Class<?>... parameterTypes)
        {

            try {
            Class clazz = classLoader.loadClass(className);
            Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
            method.setAccessible(true);
            return method;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

我們通過該方法可以獲得要hook的具體method。

  • 定義抽象類AbstractBahaviorHookCallBack繼承自前面講到的MethodHookCallBack類,該類具體實現當調用要hook的函數時,就打印該函數。具體實現如下:
    public abstract class AbstractBahaviorHookCallBack extends MethodHookCallBack {

        @Override
        public void beforeHookedMethod(HookParam param) {
            // TODO Auto-generated method stub
            /*int length = param.args.length;
            Object[] m = param.args;
            String args = "/";
            for(int i = 0; i < length;i++)
            {
                args+=(String)m[i]+"/";
            }*/
            Logger.logD("Invoke "+ param.method.getDeclaringClass().getName()+"->"+param.method.getName());
            this.descParam(param);
            //this.printStackInfo();
        }

        @Override
        public void afterHookedMethod(HookParam param) {
            // TODO Auto-generated method stub
            //Logger.log_behavior("End Invoke "+ param.method.toString());
        }

        private void printStackInfo(){
            Throwable ex = new Throwable();
            StackTraceElement[] stackElements = ex.getStackTrace();
            if(stackElements != null){
                StackTraceElement st;
                for(int i=0; i<stackElements.length; i++){
                    st = stackElements[i];
                    if(st.getClassName().startsWith("com.android.binpang")||st.getClassName().startsWith("de.robv.android.xposed.XposedBridge"))
                        continue;
                    Logger.logD(st.getClassName()+":"+st.getMethodName()+":"+st.getFileName()+":"+st.getLineNumber());
                }
            }
        }

        public abstract void descParam(HookParam param);
}
  • 具體要實現的hook函數
    Method sendTextMessagemethod =  FindMethod.findMethod(
                    "android.telephony.SmsManager", ClassLoader.getSystemClassLoader(),
                    "sendTextMessage", String.class,String.class,String.class,PendingIntent.class,PendingIntent.class);
            hookhelper.hookMethod(sendTextMessagemethod, new AbstractBahaviorHookCallBack() {

                @Override
                public void descParam(HookParam param) {
                    // TODO Auto-generated method stub
                    Logger.logI("Send SMS ->");
                    String dstNumber = (String)param.args[0];
                    String content = (String)param.args[2];
                    Logger.logI("SMS DestNumber:"+dstNumber);
                    Logger.logI("SMS Content:"+content);
                }
            });

該示例函數是hook了android.telephony.SmeManager/sendTextMessage函數,當調用該函數的時候,會打印出來要發送的目標號碼,及發送的message的內容。

  • 監聽的敏感函數列表

SmsManager

  1. android.telephony.SmsManager/sendTextMessage
  2. android.telephony.SmsManager/getAllMessagesFromIcc
  3. android.telephony.SmsManager/sendDataMessage
  4. android.telephony.SmsManager/sendMultipartTextMessage

TelephonyManager

  1. android.telephony.TelephonyManager/getLine1Number
  2. android.telephony.TelephonyManager/listen

AccountManager

  1. android.accounts.AccountManager/getAccounts
  2. android.accounts.AccountManager/getAccountsByType

ActivityManager

  1. android.app.ActivityManager/killBackgroundProcesses
  2. android.app.ActivityManager/forceStopPackage

AlarmManager

  1. android.app.AlarmManager/setImpl

AudioRecord

  1. android.media.AudioRecord

Camera

  1. android.hardware.Camera/takepicture
  2. android.hardware.Camera/setPreviewCallback
  3. android.hardware.Camera/setPreviewCallbackWithBuffer
  4. android.hardware.Camera/setOneShotPreviewCallback

ConnectivityManager

  1. android.net.ConnectivityManager/setMobileDataEnabled

ContentResolver

  1. android.content.ContentResolver/qurey
  2. android.content.ContentResolver/registerContentObserver
  3. android.content.ContentResolver/insert
  4. android.content.ContentResolver/bulkInsert
  5. android.content.ContentResolver/delete
  6. android.content.ContentResolver/update
  7. android.content.ContentResolver/applyBatch

ContextImpl

  1. android.app.ContextImpl/registerReceiver

MediaRecorder

  1. android.media.MediaRecorder/start
  2. android.media.MediaRecorder/stop

Internet

  1. java.net.URL/openConnection
  2. org.apache.http.impl.client.AbstractHttpClient/execute

NotificationManager

  1. android.app.NotificationManager/notify

ApplicationPackageManager

  1. android.app.ApplicationPackageManager/installPackage
  2. android.app.ApplicationPackageManager/deletePackage
  3. android.app.ApplicationPackageManager/getInstalledPackages

Xposed編程步驟

  • 首先在xposedbridgeapi.jar包導入到項目中,這裏採用了XposedBridgeApi-54.jar包
  • 再項目的assets文件夾中新建一個xposed_init文件(沒有後綴),該文件表示該xposed模板的主函數類的具體路徑,比如該項目爲

  • 在AndroidManifest.xml文件的標籤下添加xposed的一些信息,以便Xposed能夠識別該模板。
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.methodhook"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
    android:minSdkVersion="18"
    android:targetSdkVersion="21" />

    <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
    android:name="com.binpang.methodhook.MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>
    <meta-data
    android:name="xposedmodule"
    android:value="true" />
    <meta-data
    android:name="xposedminversion"
    android:value="40" />
    <meta-data
    android:name="xposeddescription"
    android:value="Monitor the System's apis" />
    </application>

    </manifest>
  • 在Android手機(或模擬器,建議使用模擬器,一般的模擬器都已經root過了)中安裝XposedInstaller(需要root權限), 由於Xposed替換了Android的一些程序,所以需要重啓才能生效。
  • 然後啓動該模板程序,使其安裝到Android手機中,然後再Xposed的模板中找到它,並打鉤,如圖所示:

演示hook結果

通過短信軟件向5554號碼發送”hello,world”內容,如圖所示:

結果查找logcat如圖所示:


具體可以參考我的github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章