破解某交(y)友(p)app的VIP&&半自動im機器人


案例

就不放了,某交(y)友(p)app

致謝

Youpk[1]環信IM文檔[2]hanbing&&r0ysue

加固簡單分析

拿到app就先拿到jadx中分析,發現這是360加殼。這是時候我們就要祭出脫殼神奇Youpk Youpk的操作文檔具體可以看Youpk的github,再次感謝Youpk。我們在吧修復好的dex放在jadx中分析。修復的很給力,也可以看出源代碼基本沒有混淆,這就更利於我們的分析了。

破解VIP

  • 利用Xposed/Frida破解 我們首先打開這個app,在主頁點到一個人->進去,點擊私信,發現要開通會員纔可以呢。 這時候就可以 祭出搜索大法。打開jadx-全局搜索這個關鍵詞“成爲會員”。 這裏可以看到有兩個相同的。進入看看看。 這兩處都是,我們分析一下這兩處。
  • 第一處
 else if (this.isVip <= 1) {                        new CommomDialog(this, R.style.dialog, true, "成爲會員才能私聊哦!", new CommomDialog.OnCloseListener() {                            /* class com.**.**.main.user.UserInfoActivity.AnonymousClass6 */
/* JADX WARN: Type inference failed for: r0v0, types: [android.content.Context, com.**.**.main.user.UserInfoActivity] */ @Override // com.**.**.widget.dialog.CommomDialog.OnCloseListener public void onClick(Dialog dialog, boolean z) { if (z) { UserInfoActivity.this.startActivity(new Intent((Context) UserInfoActivity.this, MembersActivity.class)); dialog.dismiss(); } } }).setTitle("溫馨提示").setPositiveButton("開通會員").show(); return;

else if 裏面的this.isVip只有小於1纔會進入,也就是提示讓你開通會員。

  • 第二處
 if (this.isVip > 1) {                        Intent intent = new Intent((Context) this, (Class<?>) ChatActivity.class);                        intent.putExtra(UserCacheInfo.COLUMNNAME_USERIDIMID, this.user_id);                        intent.putExtra("userId", this.user_imid);                        startActivity(intent);                        return;                    }                    new CommomDialog(this, R.style.dialog, true, "成爲會員才能私聊哦!", new CommomDialog.OnCloseListener() {                        /* class com.**.**.main.user.UserInfoActivity.AnonymousClass8 */
/* JADX WARN: Type inference failed for: r0v0, types: [android.content.Context, com.**.**.main.user.UserInfoActivity] */ @Override // com.u**.**.widget.dialog.CommomDialog.OnCloseListener public void onClick(Dialog dialog, boolean z) { if (z) { UserInfoActivity.this.startActivity(new Intent((Context) UserInfoActivity.this, MembersActivity.class)); dialog.dismiss(); } } }).setTitle("溫馨提示").setPositiveButton("開通會員").show(); return; } return;

這裏可以看到this.isVip 大於1的話就會提示“開通會員了呢”

  • 最後 其實只要進入到 this.isVip大於1那不就,,,,嘿嘿嘿 繼續分析一下這個isVip是在哪裏賦值呢。查找用例。。。。。 找到啦。。我們改下返回值 我們這裏frida改一下。獻上代碼 這裏還會有個小問題,就是這塊類沒在內存加載的時候會報錯,這時候點下某人的主頁就好了。
Java.perform(function () {    var pre = Java.use("com.***.***.utils.UncleSharedPreferences");    pre.getInt.overload('android.content.Context', 'java.lang.String').implementation = function (a1, a2) {        return 2;    }})

看看效果。。。發過去了。。。但是我們需要一直用的話就要一個xposed的插件。這裏app採用的360加固,那我們就不能用常規的classloader進行hook,直接用360殼的classloader進行hook。

     XposedHelpers.findAndHookMethod("com.stub.StubApp", loadPackageParam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() {                @Override                protected void afterHookedMethod(MethodHookParam param) throws Throwable {                    super.afterHookedMethod(param);                    Context context = (Context) param.args[0];                    ClassLoader classLoader = context.getClassLoader();                    classLoaders = classLoader;                    XposedHelpers.findAndHookMethod("com.***.***.utils.UncleSharedPreferences", classLoader, "getInt", Context.class, String.class, new XC_MethodHook() {                        @Override                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {						//設置返回值爲2                            param.setResult(2);                        }                    });                    XposedHelpers.findAndHookMethod("com.***.***.utils.DateUtil", classLoader, "getDayDiff", Date.class, Date.class, new XC_MethodHook() {                        @Override                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {                            param.setResult(0L);                        }                    });
} });

好了完美。。。私聊小姐姐(****)們

  • 暗坑 最後發現他們有個體驗會員,到期就是放棄(退出)
  • 那還能咋辦,繼續分析 搜索大法 這裏的if都是&&,一真則真,一假則假。前邊幾個看着不好搞,就dayDiff入手,改他返回值,小於3就行了。 代碼就不放了。
  • 小結 這個vip的破解還是很簡單的那種。。。這塊其實可以通過攔截請求的方式更改數據包,將vip字段設置一下,沒具體分析。

聊天IM&&半自動im機器人

根據com.hyphenate.chat.EMMessage可以得到這是環信的im聊天,那就很簡單了。兩種方式實現發消息:

  • 1.使用環信sdk,逆向該app的inti環境的一些配置信息,完成發消息。
  • 2使用app本身的消息發送方法,用frida或者xposed主動調用。這裏由於沒有pythonSdk,所以採用第二種。

分析消息發送

這裏我們上ddms和環信的文檔,分析它的調用情況。文檔如下

發送文本消息//創建一條文本消息,content爲消息文字內容,toChatUsername爲對方用戶或者羣聊的id,後文皆是如此EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername);//如果是羣聊,設置chattype,默認是單聊if (chatType == CHATTYPE_GROUP)    message.setChatType(ChatType.GroupChat);//發送消息EMClient.getInstance().chatManager().sendMessage(message);

ddms如下打開jadx分析這個類代碼,可以看到如下發送消息時候,創建了EMMessage.createTxtSendMessage,需要發送文本和對方的id。下面的代碼是發送文本信息的

            if (this.chatFragmentHelper != null) {                this.chatFragmentHelper.onSetMessageAttributes(eMMessage);            }            if (this.chatType == 2) {                eMMessage.setChatType(EMMessage.ChatType.GroupChat);            } else if (this.chatType == 3) {                eMMessage.setChatType(EMMessage.ChatType.ChatRoom);            }            EaseUser userInfo = EaseUserUtils.getUserInfo(eMMessage.getFrom(), UncleSharedPreferences.getString(SZApplication.getContext(), UncleSharedPreferences.SP_UID));            eMMessage.setAttribute("avatar", userInfo.getAvatar());            eMMessage.setAttribute("gender", UncleSharedPreferences.getString(SZApplication.getContext(), UncleSharedPreferences.SP_USER_SEX));            eMMessage.setAttribute("name", userInfo.getNickname());            eMMessage.setAttribute("token", UncleSharedPreferences.getString(SZApplication.getContext(), UncleSharedPreferences.SP_UID));            if (UserCacheManager.getImidFromCache(this.toChatUsername) != null) {                eMMessage.setAttribute("tokenTo", UserCacheManager.getImidFromCache(this.toChatUsername).getUserId());            } else {                eMMessage.setAttribute("tokenTo", "");            }            eMMessage.setAttribute("nameTo", eMMessage.getTo());            eMMessage.setAttribute("avatarTo", UncleSharedPreferences.getString(SZApplication.getContext(), UncleSharedPreferences.SP_TO_USER_AVATAR)); EMClient.getInstance().chatManager().saveMessage(eMMessage);

知道上邊的我們就可以用frida玩玩。

  var to_user_id = '1000477560';        var content = '我是一個機器人你信嗎';        var uid = '1000511189';        var EMMessage = Java.use("com.hyphenate.chat.EMMessage");        var eMMessage = EMMessage.createTxtSendMessage(content, to_user_id);        eMMessage.setAttribute("avatar", "http://***/android/pic/1591284964")//頭像        eMMessage.setAttribute("gender", "1")        eMMessage.setAttribute("name", "看123了看刻錄機")        eMMessage.setAttribute("token", uid)//自己uid        eMMessage.setAttribute("nameTo", to_user_id)//對方imid        eMMessage.setAttribute("avatarTo", "")        eMMessage.setAttribute("tokenTo", to_user_id)        var EMClient = Java.use("com.hyphenate.chat.EMClient");  EMClient.getInstance().chatManager().saveMessage(eMMessage)

發送之後,需要點進去聊天界面,纔會發送過去,並且如果這個app沒有緩存這個用戶信息,就會閃退。

解決閃退

繼續ddms,點擊私信。搜索startAc,可以看到在UserInfoActivity下分析到如下代碼,可以很清楚到看到,這裏吧用戶信息存起來了。然後啓動聊天的tActivity。

       UserCacheManager.save(this.user_id, this.user_imid, this.nickname, this.avatar);                    EaseUser easeUser = new EaseUser(this.user_imid);                    easeUser.setAvatar(this.avatar);                    easeUser.setNickname(this.nickname);                    if (this.isVip > 1) {                        Intent intent = new Intent((Context) this, (Class<?>) ChatActivity.class);                        intent.putExtra(UserCacheInfo.COLUMNNAME_USERIDIMID, this.user_id);                        intent.putExtra("userId", this.user_imid);                        startActivity(intent);                        return;                    }

這次用xposed實現發送消息和啓動ui。

   Class EMMessage = XposedHelpers.findClass("com.hyphenate.chat.EMMessage", classLoaders);        Object eMMessage = XposedHelpers.callStaticMethod(EMMessage, "createTxtSendMessage", content, to_user_id);        XposedHelpers.callMethod(eMMessage, "setAttribute", "avatar", avatar);        XposedHelpers.callMethod(eMMessage, "setAttribute", "gender", gender);        XposedHelpers.callMethod(eMMessage, "setAttribute", "name", name);        XposedHelpers.callMethod(eMMessage, "setAttribute", "token", token);        XposedHelpers.callMethod(eMMessage, "setAttribute", "nameTo", nameTo);        XposedHelpers.callMethod(eMMessage, "setAttribute", "avatarTo", avatarTo);        XposedHelpers.callMethod(eMMessage, "setAttribute", "tokenTo", tokenTo);        Class EMClient = XposedHelpers.findClass("com.hyphenate.chat.EMClient", classLoaders);        Object getInstance = XposedHelpers.callStaticMethod(EMClient, "getInstance");        Object chatManager = XposedHelpers.callMethod(getInstance, "chatManager");        XposedHelpers.callMethod(chatManager, "saveMessage", eMMessage);        Class ChatActivity = XposedHelpers.findClass("com.***.***.main.im.ChatActivity", classLoaders);        Class UserCacheManager = XposedHelpers.findClass("com.***.***.main.im.cache.UserCacheManager", classLoaders);        XposedHelpers.callStaticMethod(UserCacheManager, "save", to_user_id, to_user_id, to_user_id, avatar);        Class EaseUser = XposedHelpers.findClass("com.hyphenate.easeui.domain.EaseUser", classLoaders);        Object easeUsernewInstance = XposedHelpers.newInstance(EaseUser, to_user_id);        XposedHelpers.callMethod(easeUsernewInstance, "setNickname", to_user_id);        XposedHelpers.callMethod(easeUsernewInstance, "setAvatar", avatar);        Intent intentChat = new Intent(contexts, ChatActivity);        intentChat.putExtra("userImId", to_user_id);        intentChat.putExtra("userId", to_user_id);        contexts.startActivity(intentChat);

這就基本完成了。

效果展示

最後藉助NanoHTTPD做了web接口。看下效果

gif傳不上來,戳原文看效果吧。

總結

這個app比較簡單,雖然360加殼,但是通過youpk脫殼之後,發現基本沒混淆。文中是藉助ddms分析調用情況。這個可以繼續擴展到,hook接收消息,收到消息之後,自動回覆信息。接口在com...SZHelper$9.onMessageReceived上,以後有時間再分析寫出來。

參考資料

[1]

Youpk: https://github.com/Youlor/Youpk

[2]

環信IM文檔: http://docs-im.easemob.com/im/android/basics/message

本文分享自微信公衆號 - 小白技術社(xbjss123)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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