Android Xposed hook从了解到学废.004

实战:Hook软件sign算法

Android Xposed hook从了解到学废.003
本文阐述如何逆向Hook软件的思路和写法,未对涉及到的软件有任何意图,仅提供学习请勿用作非法行为,有任何疑问都可以邮件[email protected]

1.准备工具

下述括号内是我所有的版本或软件
1.Android Studio (3.5)
2.模拟器或者Android手机 (雷电)
3.Fiddler (4) 下载
4.jeb (2.2.7.20160815)下载
4.MT管理器.apk(注意是新版)下载
5.游拍.apk(3.5.1.56) 这里不提供地址

jeb收费,破 j 版安装也过于麻烦,所以第4个工具2选一,这里我都演示了

环境搭建请看第一篇:Android Xposed hook从了解到学废.001

2.找寻需要HOOK的类和方法

目标:进入直播间出现的弹幕和说话的sign

数据:

POST http://mapi.4399youpai.com/app/android/v3.5/chat-msg.html HTTP/1.1
MUDID: xiaomigofDrSauMT9BcT8MD5b0e
APIVERSION: 3.5.1.56.481
CHANNEL: xiaomi
MAUTH: a4b37556327aad56c379dd7645be14d5
DEVID: 865166028278623
User-Agent: 4399YouPai/3.5.1.56(android;vivo x9;5.1.1;1080x1920;WIFI;481;xiaomi;xxhdpi)
APKNAME: com.m4399.youpai
MAUTHCODE: 795e2e49
Content-Type: application/x-www-form-urlencoded
Content-Length: 256
Host: mapi.4399youpai.com
Connection: Keep-Alive
Accept-Encoding: gzip

is_new_version=1&sign=99257bef9ad502accda48ce50b0a3d96&msg=%E6%9D%A5%E4%BA%86&apk_version=3.5.1.56.481&nickname=2984236588&apkName=com.m4399.youpai&is_face=0&push_id=17214772&uniqueId=865166028278623&system=1&room_id=1918&channel=public%3Ayptv_172147728e28

在这里插入图片描述
通过Fiddler 4抓取到发送的数据为:is_new_version=1&sign=99257bef9ad502accda48ce50b0a3d96&msg=%E6%9D%A5%E4%BA%86&apk_version=3.5.1.56.481&nickname=2984236588&apkName=com.m4399.youpai&is_face=0&push_id=17214772&uniqueId=865166028278623&system=1&room_id=1918&channel=public%3Ayptv_172147728e28

查询类和方法的第一种方式 使用jeb

我们打开jeb拖入apk
在这里插入图片描述
这里我们抓到的提交地址是chat-msg.html,所以我们直接Ctrl+F搜索,不过不知道啥原因我的jeb有点不太配合我,没搜到(MT管理器可以,稍后再说)

于是乎我直接搜索了他的提交参数"apk_version
这里有个"表明他是个常量而不是代码或者函数
在这里插入图片描述
发现周围用橙色突出的常量都是提交的参数名,所以确定了,这个位置就是提交弹幕的函数
使用快捷键Q键转换成java代码查看

在这里插入图片描述

 private void a(String arg4, int arg5, String arg6) {
        HashMap v0 = new HashMap();
        ((Map)v0).put("msg_id", arg6);
        ((Map)v0).put("nickname", this.r.getNickName());
        ((Map)v0).put("msg", arg4);
        ((Map)v0).put("system", arg5 + "");
        ((Map)v0).put("apkName", ((Fragment)this).getActivity().getPackageName());
        ((Map)v0).put("apk_version", c.b(((Fragment)this).getActivity()));
        ((Map)v0).put("channel", this.r.getPushChannel());
        ((Map)v0).put("push_id", this.q + "");
        ((Map)v0).put("room_id", this.s);
        arg6 = LiveManager.getInstance().getIdentifiesId();
        if(TextUtils.isEmpty(((CharSequence)arg6))) {
            arg6 = e.c(((Fragment)this).getActivity());
        }
        
        ((Map)v0).put("uniqueId", arg6);
        v6 = new StringBuilder();
        v6.append(arg4);
        v6.append(this.r.getNickName());
        v6.append(arg5);
        v6.append("#4399yp*msg#");
        ((Map)v0).put("sign", i.a(v6.toString()));
        if(arg5 == 0) {
            ((b)this).loadData(LiveManager.getInstance().getApiService().sendChatMsg(((Map)v0)), this.m);
        }
    }
	v6 = new StringBuilder();
        v6.append(arg4);
        v6.append(this.r.getNickName());
        v6.append(arg5);
        v6.append("#4399yp*msg#");
        ((Map)v0).put("sign", i.a(v6.toString()));

创建名为v6的StringBuilder对象
然后加入
arg4
this.r.getNickName()
arg5
#4399yp*msg#
转为string类型传递给i.a()

我们看一下
arg4
this.r.getNickName()
arg5
都是什么
在这里插入图片描述

结合发出去的数据可以看出来
arg4是msg 也就是"来了"
this.r.getNickName()是nickname 也就是2984236588
arg5是system 也就是1

双击i.a跳转过去看看
在这里插入图片描述
digest和update是md5的特征
我们数一下sign:99257bef9ad502accda48ce50b0a3d96
一共32位这里又写了md5
基本可以确定是md5加密
那么我们hook他拿出他的原文看看

在这里插入图片描述
翻到最上面这个时候我们得到了需要hook的方法和类了

查询类和方法的第一种方式 使用MT管理器

jeb的可以划走,这里说的是mt管理器

单击APK选择查看
在这里插入图片描述
发现他有3个Dex
随便点一个
我们选择dex++编辑,然后全选,使用搜索功能

在这里插入图片描述

搜索chat-msg.html

在这里插入图片描述
搜索到一个,我们点击进去
在这里插入图片描述

MT管理器使用转java代码需要收费,估计看文章的没几个有会员,哈哈
(PS:哎16年买的永久会员真香哈哈哈哈哈)

这里看到方法是sendChatMsg,我们出去搜索看看哪里调用了
在这里插入图片描述

这里一共有3个地方使用过sendChatMsg
我们倒着一个一个看吧
在这里插入图片描述

post过去的值都存在,所以这个可能是我们所要找的
开启会员特权给你们看一眼

在这里插入图片描述
应该都看懂了吧,我们回去看看代码

    const-string p1, "#4399yp*msg#"
    invoke-virtual {p3, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    invoke-virtual {p3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    move-result-object p1
    .line 30
    invoke-static {p1}, Lcom/youpai/framework/util/i;->a(Ljava/lang/String;)Ljava/lang/String;
    move-result-object p1
    const-string p3, "sign"

这里代码是Smali代码,反正我是看不懂
不过能理解一丢丢,然后代码看过java的也应该能理解一点了

invoke-static {p1}, Lcom/youpai/framework/util/i;->a(Ljava/lang/String;)Ljava/lang/String;
    move-result-object p1

Lcom/youpai/framework/util/i;->a(Ljava/lang/String;)
传入String类型值给Lcom/youpai/framework/util/i;->a处理
那么我们过去看看

在这里插入图片描述
在这里插入图片描述

哈!在第二个dex里
在这里插入图片描述
我们就已经确定了目标开始hook

3.开始编写Hook代码

这里目标包名是:com.m4399.youpai
目标类是:com.youpai.framework.util.i
目标方法:a

编写代码

package com.hygzs.hook;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class hook implements IXposedHookLoadPackage {
    public void handleLoadPackage(LoadPackageParam loadPackageParam) throws Throwable {
        if (!loadPackageParam.packageName.equals("com.m4399.youpai"))
            return;
        XposedBridge.log("已经找到目标软件");
        XposedHelpers.findAndHookMethod("com.youpai.framework.util.i", loadPackageParam.classLoader,
                //上面看第2篇
                "a",
                //目标为isCorrectInformation
                String.class,
                //传递的1个值是string类型,所以这里直接1个String.class
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
                        //afterHookedMethod是在调用原方法后执行
                        XposedBridge.log("原文 = " + (String) param.args[0]);
                        //打印到xposed日志内
                        super.afterHookedMethod(param);
                        //调用
                    }
                }
        );

    }
}

这里代码和之前的没什么区别,就是改了判断的包名,类名还有方法名
我们写好后运行,然后重启模拟器或者模拟器或者vxp框架

整体过程可以看前面的文章我就不赘述了

现在开启fd然后抓包
抓到了新的数据
在这里插入图片描述
sign:99257bef9ad502accda48ce50b0a3d96
看一下日志
在这里插入图片描述

日志:来了29842365881#4399ypmsg#
我们通过工具查询md5
在这里插入图片描述一模一样
到此Sign算法和原文就得到了
来了+nickname+system+#4399yp
msg#

这里要说一下此app的通过chat-msg.html发送数据一共有2个地方,一个是弹幕,一个就是这种刚刚进入直播间的提示system是不一样的

额外知识点

因为我们需要不断的去看日志就很麻烦,所以这里提供xposed使用toast的方法
直接贴代码详细可以看这篇文章Android逆向工程:大显神通的Xposed,如何在Xposed中弹出Toast提示

package com.hygzs.hook;

import android.content.Context;
import android.view.ContextThemeWrapper;
import android.widget.Toast;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class hook implements IXposedHookLoadPackage {
    private Context context;
    public void handleLoadPackage(LoadPackageParam loadPackageParam) throws Throwable {
        XposedHelpers.findAndHookMethod(ContextThemeWrapper.class, "attachBaseContext",Context.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                context=(Context) param.args[0];
            }
        });

        if (!loadPackageParam.packageName.equals("com.m4399.youpai"))
            return;
        XposedBridge.log("已经找到目标软件");
        XposedHelpers.findAndHookMethod("com.youpai.framework.util.i", loadPackageParam.classLoader,
                //上面看第2篇
                "a",
                //目标为isCorrectInformation
                String.class,
                //传递的1个值是string类型,所以这里直接1个String.class
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
                        //afterHookedMethod是在调用原方法后执行
                        XposedBridge.log("原文 = " + (String) param.args[0]);
                        Toast.makeText(context,"加密原文:"+(String) param.args[0],Toast.LENGTH_SHORT).show();
                        //打印到xposed日志内
                        super.afterHookedMethod(param);
                        //调用
                    }
                }
        );

    }
}

在这里插入图片描述

发布了5 篇原创文章 · 获赞 0 · 访问量 726

猜你喜欢

转载自blog.csdn.net/qq_15781179/article/details/104458260