申请ID:hygzs
个人邮箱:1341806518@qq.com
原创技术文章:
csdn地址:Android Xposed hook从了解到学废.004_幻叶-叶子的博客-CSDN博客
Android Xposed hook从了解到学废.004
通过xposed hook逆向直播app的sign加密
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
数据:
[JavaScript] 纯文本查看 复制代码 POST [url=http://mapi.4399youpai.com/app/android/v3.5/chat-msg.html]http://mapi.4399youpai.com/app/android/v3.5/chat-msg.html[/url] 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代码查看
[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);
}
}
[Java] 纯文本查看 复制代码 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过去的值都存在,所以这个可能是我们所要找的
开启会员特权给你们看一眼应该都看懂了吧,我们回去看看代码[Asm] 纯文本查看 复制代码 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的也应该能理解一点了[Asm] 纯文本查看 复制代码 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里我们就已经确定了目标开始hook3.开始编写Hook代码这里目标包名是:com.m4399.youpai
目标类是:com.youpai.framework.util.i
目标方法:a编写代码[Java] 纯文本查看 复制代码 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+#4399ypmsg#这里要说一下此app的通过chat-msg.html发送数据一共有2个地方,一个是弹幕,一个就是这种刚刚进入直播间的提示system是不一样的额外知识点因为我们需要不断的去看日志就很麻烦,所以这里提供xposed使用toast的方法直接贴代码详细可以看这篇文章Android逆向工程:大显神通的Xposed,如何在Xposed中弹出Toast提示[Asm] 纯文本查看 复制代码 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);
//调用
}
}
);
}
}
|