xposed的基本使用

1、原理

Android運行的核心是zygote進程,全部app的進程都是經過zygote fork出來的。經過替換system/bin/下面的app_process等文件,至關於替換了zygote進程,實現了控制手機上的全部APP。基本原理是修改了ART/Davilk虛擬機,將須要hook的函數註冊爲Native層函數,當執行到該函數時,虛擬機會先執行Native層函數,而後執行Java層函數,這樣完成hook。html

更詳細的能夠參考:https://blog.csdn.net/wxyyxc1992/article/details/17320911java

2、Xposed安裝

環境:網易mumu、Android Studio3.3.1android

github地址:https://github.com/rovo89/XposedInstallergit

Xposedinstaller的apk:https://repo.xposed.info/module/de.robv.android.xposed.installergithub

在網易mumu中安裝好xposedinstaller apk後,關閉應用兼容性(不關閉的話安裝xposed框架會出錯),進去以後點擊小云彩便可安裝完成。api

image-20190619104940343

3、Xposed代碼編寫

新建項目,選擇empty activity,建立成功後,在AndroidManifest.xml中添加以下代碼性能優化

<meta-data
    android:name="xposedmodule"
    android:value="true" />   <!--告訴xposed框架這是一個xposed模塊-->
<meta-data
    android:name="xposeddescription"
    android:value="這是一個Xposed例程" /> <!--模塊描述-->
<meta-data
    android:name="xposedminversion" <!--模塊支持的最低版本-->
    android:value="30" />

在gradle中配置XposedbridgeApi,build.gradle中配置網絡

repositories {
    jcenter()
}
dependencies {
        ...
    compileOnly 'de.robv.android.xposed:api:82'
    compileOnly 'de.robv.android.xposed:api:82:sources'
    ...
}

這是在網絡通暢的狀況下進行的, 網絡不通暢的話,能夠手動下載XposedBridgeApi-82.jar,拖動到/app/libs中,刪除上述gradle中配置的 jcenter,右鍵"Add As Library"添加這個jar包。app

在界面上畫個按鈕,並在MainAcitiviy中編寫以下代碼(單純寫hook的話前面新建項目的時候能夠add no activity)框架

package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;
import android.view.View;
public class MainActivity2 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(MainActivity2.this, toastMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    public String toastMessage() {
        return "我未被劫持";
    }
}

編寫Hook代碼,在MainActivity同級目錄下新建HookTest.java,而且繼承接口IXposedHookLoadPackage和重寫handleLoadPackage方法

package com.example.myapplication;
import java.lang.reflect.Array;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Map;
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 {

    private static final String HOOK_APP_NAME = "APP名字";

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {

        //性能優化,避免操做無關app
        if (!lpparam.packageName.equals(HOOK_APP_NAME))
            return;
        if (lpparam.packageName.equals("HOOK_APP_NAME")) {
            XposedBridge.log(" 劫持成功!!!");
          
        XposedBridge.log("XposedMainInit handleLoadPackage 執行");
        XposedBridge.log("Loaded app: " + lpparam.packageName);            XposedHelpers.findAndHookMethod("APP名字.MainActivity",//hook的類
                    lpparam.classLoader,
                    "toastMessage", // 被Hook的函數
                    //Map.class, 被Hook函數的第一個參數  (此處沒有,只是舉個例子)
                    //String.class, 被Hook函數的第二個參數String
                    new XC_MethodHook() {
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            // 參數獲取
                            XposedBridge.log("入口函數執行");
                            //參數1
                            XposedBridge.log("beforeHookedMethod map:" + param.args[0]);
                            //參數2
                            XposedBridge.log("beforeHookedMethod hash_key:" + param.args[1]);
                            //函數返回值
                            XposedBridge.log("beforeHookedMethod result:" + param.getResult());
                        }
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            XposedBridge.log("afterHookedMethod result:" + param.getResult());
                          param.setResult("你已被劫持");
                        }
                    });        
        }
    }
}

在src/mian目錄下添加一個assets目錄,目錄下添加一個xposed_init文件,裏面的代碼是你的Hook類的包名+類名。

com.example.myapplication.HookTest

最後選擇禁用 Instant Run: 單擊 File -> Settings -> Build, Execution, Deployment -> Instant Run,把勾所有去掉。

image-20190619133257899

這個時候鉤子已經執行了,具體想鉤什麼,就看本身的需求了。

注:實際操做中,須要對APP先進行反編譯(反編譯了才能知道要鉤那個函數),反編譯工具備不少,這裏就不細說了。

4、面對加了殼的APP

直接用反編譯工具打開apk,查看加的是哪一種殼,尋找對應的函數,相似attachBaseContext這樣的方法。

參考連接:https://www.cnblogs.com/xiaobaiyey/p/6442417.html

public class EncryptHook implements IXposedHookLoadPackage {

    public void handleLoadPackage(LoadPackageParam loadPackageParam) throws Throwable {
        if (!loadPackageParam.packageName.equals("app包名")) { return; }
        XposedBridge.log("Start hook " + loadPackageParam.packageName);

        XposedHelpers.findAndHookMethod("com.stub.StubApp", loadPackageParam.classLoader,
                 //com.stub.StubApp 加殼的類
                "attachBaseContext", Context.class, new XC_MethodHook() {
                 // attachBaseContext 加殼的方法 
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    Context context = (Context) param.args[0];
                    ClassLoader classLoader = context.getClassLoader();
                    XposedBridge.log("Enter stubApp");

                    XposedHelpers.findAndHookMethod("com.huijiemanager.utils.t", classLoader,
                        "a", byte[].class, PublicKey.class, new XC_MethodHook() {
                            @Override
                            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                XposedBridge.log("rsa before params: " + new String(
                                    (byte[]) param.args[0]) + "," + param.args[1]);
                            }
                            @Override
                            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                XposedBridge.log("rsa after params: " + new String(
                                    (byte[]) param.args[0]) + "," + param.args[1]);
                            }
                        });
                }
            });
    }
}

注:反編譯的代碼不必定準確,逆向的時候最好對每一個關鍵函數都掛上鉤子,查看參數是否正確。

附上xposedAPI文檔:https://api.xposed.info/reference/packages.html

相關文章
相關標籤/搜索