Xposed 探索之Hook 駕考寶典

本文固定鏈接,轉載請先評論點贊

一、起因:

最近在考駕照,錢是去年年初的時候交的。科目一到前段時間纔開始,又碰上疫情。所以耐着性子看了三四遍駕考寶典。1350個題目用兩個不同的駕考app各刷了一遍。總擔心考不過科目一。尤其是刷了第一遍題目後總感覺還有些內容總結不夠。看這個app會員功能有總結,當時還發了個朋友圈要買個會員,問別人有沒有會員可以借來使使的(當然,經過大家一致的吐糟,最後迎着苦澀又刷了一遍題目)。所以,過程有點曲折,但是起因就是對這個app的vip功能情有獨鍾。

二、契機:

最近在看Xposed的事情,如果你看過之前的文章,你會知道我爲啥看這個框架。總之是折騰之後有點失落。最後決定對這個享譽盛名的app表達一下尊重。我們嚴肅的表示,我們在探索技術。

三、準備工作:

從他的官網下載了app。保存在桌面。安裝了MuMu模擬器。用模擬器安裝這個app。
備註:爲什麼用MuMu模擬器原因有兩個:
1、模擬器開發者模式和root都已經做了。Xposed框架基礎條件都有
2、在調試功能的時候要經常重啓。如果用真機我擔心對我的“三老婆”有損。(二老婆是車(暫時沒有)三老婆是手機(寶貝着咧))

按照上一個文章所示,搭建好android studio 環境,過程請看:
Android Studio 在MuMu模擬器上實現 xposed簡單劫持
工程結構如圖:
在這裏插入圖片描述
MainActivity.java代碼如下:

package com.cf.exposedpractice;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn=(Button)findViewById(R.id.button);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showCenterContent();
            }
        });
    }

    public void showCenterContent()
    {
        TextView centerText=(TextView)findViewById(R.id.centerTextView);

        centerText.setText(GetContent());
    }

    public String GetContent()
    {
        return  "Xposed test";
    }
}

XposedTools.java代碼如下:

package com.cf.exposedpractice;

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 XposedTools implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {

        XposedBridge.log("Loaded app: " + lpparam.packageName);

        if(lpparam.packageName.equals("com.cf.exposedpractice"))
        {
            XposedHelpers.findAndHookMethod("com.cf.exposedpractice.MainActivity", lpparam.classLoader, "GetContent", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    XposedBridge.log("GetContent afterHookedMethod");

                    param.setResult("hooked the function of GetContent");
                }
            });
        }

        if(lpparam.packageName.equals("com.handsgo.jiakao.android"))
        {
            XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isJiakaoVip", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    XposedBridge.log("afterHookedMethod");

                    Object result=param.getResult();

                    boolean v=(boolean)result;

                    XposedBridge.log("afterHookedMethod isJiakaoVip ori v:"+v);

                    param.setResult(true);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

            XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isAdmin", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    boolean v=(boolean)result;

                    XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);

                    param.setResult(true);
                }
            });

            XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getExpiredTime", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    Long v=(Long)result;

                    v+=999999999;

                    XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);

                    param.setResult(v);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

            XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getNickname", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    String v=(String)result;

                    XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);

                    param.setResult("Xposed "+v);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

            XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager", lpparam.classLoader, "getPracticeVideoCount", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    int v=(int)result;

                    XposedBridge.log("afterHookedMethod getPracticeVideoCount ori v:"+v);

                    param.setResult(v+888);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

            XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager", lpparam.classLoader, "LMa", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    int v=(int)result;

                    XposedBridge.log("afterHookedMethod LMa ori v:"+v);

                    param.setResult(v+9999);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });
        }
    }
}

看過上面的文章你一定能發現,我這裏做了個簡單的按鈕,點擊按鈕顯示想要的內容。這裏這一步是爲了測試整個框架有沒有生效。因爲就我的發現是,在某些不確定的情況下,框架有可能不成功。所以需要價格按鈕來確定如果框架成功了,點擊按鈕顯示的就是:hooked the function of GetContent

否則顯示的應該是Xposed test。如圖:
在這裏插入圖片描述
另外,因爲我使用的輸出日誌的方法是:XposedBridge.log,所以在Xposed Installler中能看到對應的日誌。

四、關於app:

像這種app不可能不代碼混淆。所以這個是一個蛋疼的點。我嘗試用jadx這個工具反編譯這個app。如圖:

在這裏插入圖片描述
反編譯的方法很簡單,就是直接用工具打開桌面上apk就行。不過我感覺這個東西耗內存。反編譯過程內存按照G來算的。

反編譯等他執行完了之後執行如圖所示反代碼混淆:
在這裏插入圖片描述
事實上只稍微好那麼一丟丟。但是比起CSDN或者百度搜索反編譯反混淆都是千篇一律的那種要好一些吧。至少看到了不一樣的聲音。
工具我已經整體打包上傳CSDN了,有需要的下載

五、想做什麼?

我想看看他的vip功能是怎麼做的!
所以,我在jadx上搜索vip。搜索結果顯示如下:
在這裏插入圖片描述
我發現,在包名爲:package cn.mucang.android.comment.api.data,類名是:UserSimpleJsonData的java類中,定義了一個名爲:jiakaoVip的變量,如圖:
在這裏插入圖片描述
打開這個類,能看到有一些get/set方法。
在這裏插入圖片描述
進一步,我搜索這個方法有哪些地方賦值了,在jadx中直接右鍵點擊方法名,選擇查找用例,如圖:
在這裏插入圖片描述
只有一個地方用到了,如圖:
在這裏插入圖片描述
額。。。。。感覺跟設想的不一樣。用戶信息中的vip屬性不應該是很多地方都用的嗎,看這個類的名稱:CommentTitleModel,這丫丫的不是啥標題啥的?

我感覺我的思路除了點問題。

回顧一波:
首先是我想通過Xposed框架修改vip屬性。所以我通過jadx搜索vip字段。但時並沒有如我預想的那樣。
然後我在Android Studio 的Xposedtools中對代碼進行修改,發現並沒有什麼用。代碼如圖:

if(lpparam.packageName.equals("com.handsgo.jiakao.android"))
        {
            XposedHelpers.findAndHookMethod("cn.mucang.android.comment.api.data.UserSimpleJsonData", lpparam.classLoader, "isJiakaoVip", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    XposedBridge.log("afterHookedMethod");

                    Object result=param.getResult();

                    boolean v=(boolean)result;

                    XposedBridge.log("afterHookedMethod isJiakaoVip ori v:"+v);

                    param.setResult(true);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });
      	}

這個地方我對包名做了限制,只有是包名爲:com.handsgo.jiakao.android的應用才起作用。包名是通過jadx中的AndroidManifest.xml看到的,如圖:
在這裏插入圖片描述
順便貼一下他的簽名信息:
在這裏插入圖片描述
額…矯情了。

言歸正傳。

既然找不到vip相關的信息,我試着找userinfo信息等關鍵字。如圖:
在這裏插入圖片描述
上面紅框裏面那些android.support我就不看了,我看到下面有個包名下面有個AccountManager的類。我感覺這個應該就是用戶信息了。
如圖:
在這裏插入圖片描述
這個地方不是一個賬號管理Manager嘛,爲毛還有Activity,這是哪個程序員寫的?拖出去槍斃。
管理功能裏面怎麼能放Activity咧。你不得通過通知之類的方法去使用啊。搞不懂。因爲是反編譯還帶混淆功能。一時半會看不懂他的邏輯。但是我找到了一個AuthUser的類。點開看看:
在這裏插入圖片描述
額,看樣子這就是個人信息了。但是奇怪的是,這個類中依舊沒有vip相關的信息。我得思考。我有點彷徨,我有點猶豫,我有點像撞牆,我有點想去拉大便。。。。。。。

暫停十分鐘。。。。。

好了,舒暢。。。。

不管他,先試試這個nickname。代碼如下:

XposedHelpers.findAndHookMethod("cn.mucang.android.account.data.AuthUser", lpparam.classLoader, "getNickname", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    String v=(String)result;

                    XposedBridge.log("afterHookedMethod isAdmin ori v:"+v);

                    param.setResult("Xposed "+v);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

這個代碼也就是說,如果有地方需要用名稱的時候強項在前面加個Xposed 。試試。編譯到MuMu模擬器,將ExposedPractice 添加到Xposed Installler模塊中,重啓模擬器。運行這個app.如圖:

在這裏插入圖片描述
在這裏插入圖片描述

呵呵,這個功能算是成功了。

但我並不能滿足於此,vip還是沒有搞定。於是,我繼續通過jadx查。

我看視頻如果是新用戶只能播放3個,我是不是可以修改這個數量,也不知道他們是不是再前端限制的播放次數。反正試試唄。如圖:
在這裏插入圖片描述
這裏顯示一段文字:可免費觀看3個視頻,那我搜索“可免費觀看”如圖:
在這裏插入圖片描述

點進去,看具體代碼:
在這裏插入圖片描述
嗯,這個LMa的變量應該是用了混淆的結果吧。反正從這個代碼中看,是這個變量顯示的數量。其中有個類叫:PracticeVideoManager,貌似是個管理類。如圖:

在這裏插入圖片描述
對應的方法在:
在這裏插入圖片描述

看這個方法,同時發現了另外一個class,如圖:
在這裏插入圖片描述
這裏大概就是所謂3次的由來了。試着用代碼Hook


            XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager.VideoCountModel", lpparam.classLoader, "getPracticeVideoCount", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    int v=(int)result;

                    XposedBridge.log("afterHookedMethod getPracticeVideoCount ori v:"+v);

                    param.setResult(v+888);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

            XposedHelpers.findAndHookMethod("com.handsgo.jiakao.android.main.manager.PracticeVideoManager", lpparam.classLoader, "LMa", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);

                    Object result=param.getResult();

                    int v=(int)result;

                    XposedBridge.log("afterHookedMethod LMa ori v:"+v);

                    param.setResult(v+9999);

                    //打印堆棧查看調用關係
                    StackTraceElement[] wodelogs = new Throwable("wodelog").getStackTrace();

                    for (int i = 0; i < wodelogs.length; i++) {
                        XposedBridge.log("查看堆棧:" + wodelogs[i].toString());
                    }

                    //獲取類
                    Class<?> clazz = param.thisObject.getClass();

                    XposedBridge.log("要hook的方法所在的類:" + clazz.getName());
                }
            });

重新編譯,重啓MuMu,運行查看。


報錯了:
在這裏插入圖片描述

額。沒有找到這個東東。

啥原因????

額。。。。。。。。。。。我得研究一下。。。。

由於篇幅問題,暫時就到這裏吧。主要原因是我還得研究研究。我都是一邊研究一邊寫文章的。所以過程很重要。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

另外:誰有更好的反混淆工具推薦的。請一定留言告知。不勝感激。

好了,再拉屎去…

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