吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2493|回复: 9
收起左侧

[Android 原创] 简单的分析:某点评 TCP协议 私信交互(三)完结

[复制链接]
西枫游戏 发表于 2024-2-26 23:16
本帖最后由 西枫游戏 于 2024-2-26 23:37 编辑

前言

简单分析{某点评}TCP私信协议,本帖只负责分析交流切勿他用。若侵犯了权益,麻烦管理帮忙删除,谢谢!

TCP交互流程

TCP协议交互理解:

  1. 请求服务器共享密钥,或本地按规则生成一组key【完结】
  2. RSA公钥加密并且组包发送到服务器统一加密密钥({某小破站登陆协议一样})【分析TCP消息交互
  3. 登陆服务器:组包数据包括 1. 登陆的设备id  2. 附带APP版本号   3. 附带该账号的uid   4. 附带该账号的令牌{token,CK}之类
  4. 理解TCP消息交互参数:
    1. 带上token令牌或者CK登陆服务器
    2. 发送消息带上本机token的nickname,Chatid 以及对方的Chatid 【重要参数】
    3. UTF-8 编码消息文本 以及确认发送消息的字节集长度
    4. 收到对方的消息并且解密打印显示出来

工具

Tools Vsersion
样本 11.12.14 - 10.20.3
Frida 16.1.11
objection 1.11.0
jadx-gui 1.2.0
调试工具 Redmi Note 7

分析流程

  1. 对于定位到关键函数 一般log日志  或者直接hook整个java层的系统加解密函数打印堆栈直接可跟进去。前两篇文章 服务器统一密钥初始化token令牌并登陆服务器  重要的两步流程走对走完了,代表该账号已经登陆成功,可以接收任何私信信息。现在的话就可以开始继续深入的就是TCP消息交互了。对于整个APP关于这块其他的功能几乎都差不多没啥大的变化无非就是组包方式不同。延申到其他APP直播类的弹幕 私信 几乎都是差不多难就难在需要时间调试分析。分析技巧 推荐【objection 】是一个非常好用的工具[首先过检测],,主要对于批量Hook一个类下的所有方法或者批量Hook所有类下的所有方法对于调试这块简直事半功倍。
  2. 分析发送信息和收到信息:
    1.frida 自吐算法脚本安排,运行并转发端口  打开app 发送私信“123456789” 打印出堆栈。
    模式填充:AES/CTR/NoPadding
    java.lang.Exception
        at javax.crypto.spec.IvParameterSpec.<init>(Native Method)
        at com.sankuai.xm.protobase.utils.a.c(AES.java:9)
        at com.sankuai.xm.login.manager.channel.f.c(CryptProcessor.java:5)
        at com.sankuai.xm.login.manager.channel.b.G(ConnectionChannel.java:8)
        at com.sankuai.xm.login.manager.l.H(ConnectionManager.java:3)
        at com.sankuai.xm.c.a0(IMCore.java:5)
        at com.sankuai.xm.c.Z(IMCore.java:13)
        at com.sankuai.xm.login.manager.b.O(Unknown Source:33)
        at com.sankuai.xm.im.connection.c.x(IMProtoHandler.java:2)
        at com.sankuai.xm.im.message.d.t0(MessageProcessor.java:24)
        at com.sankuai.xm.im.message.d$e.run(MessageProcessor.java:8)
        at com.sankuai.xm.base.trace.g.run(TraceRunnable.java:2)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at com.sankuai.android.jarvis.i.run(JarvisRunnableProxy.java:13)
        at com.sankuai.android.jarvis.m.t(JarvisThreadPoolImpl.java:14)
        at com.sankuai.android.jarvis.m$d.run(Unknown Source:20)
        at java.lang.Thread.run(Thread.java:919)

    2.跟进at com.sankuai.xm.c.a0(IMCore.java:5)

        public final void a0(byte[] bArr) { //方法参数传进来 简单明了 
        Object[] objArr = {bArr};
        ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr, this, changeQuickRedirect2, 3133362)) {
            PatchProxy.accessDispatch(objArr, this, changeQuickRedirect2, 3133362);
            return;
        }
        Object[] objArr2 = {bArr, new Byte((byte) 0)};
        ChangeQuickRedirect changeQuickRedirect3 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr2, this, changeQuickRedirect3, 844226)) {
            PatchProxy.accessDispatch(objArr2, this, changeQuickRedirect3, 844226);
            return;
        }
        Object[] objArr3 = {null, bArr, new Byte((byte) 0)};
        ChangeQuickRedirect changeQuickRedirect4 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr3, this, changeQuickRedirect4, 2186738)) {
            PatchProxy.accessDispatch(objArr3, this, changeQuickRedirect4, 2186738);
        } else if (!s()) {
            com.sankuai.xm.login.d.f("IMCore::send:: is not init");
        } else {
            ((l) z().a()).H(bArr, false);//参数是从方法里面传进来
        }
    }
  1. 继续往上跟进at com.sankuai.xm.c.a0(IMCore.java:5)
    public final void Z(short s, byte[] bArr) {
        Object[] objArr = {new Short(s), bArr};
        ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr, this, changeQuickRedirect2, 9317743)) {
            PatchProxy.accessDispatch(objArr, this, changeQuickRedirect2, 9317743);
            return;
        }
        v vVar = new v(); //跟前两篇文章一样 new 了一个类
        vVar.L(J());   //TCP参数
        vVar.f = s;  //TCP参数
        vVar.g = N(); //TCP参数
        vVar.h = bArr; //TCP参数
        vVar.j = M(); //TCP参数
        com.sankuai.xm.base.trace.f j = i.j(); 
        if (j != null) {
            vVar.i = j.f87995a;    //TCP参数
            int c = com.sankuai.xm.base.proto.protobase.f.c(bArr);
            StringBuilder m2 = android.arch.core.internal.b.m("IMCore:send: xm_trace ");
            m2.append(j.f87995a);
            m2.append(",uri = ");
            m2.append(c);
            com.sankuai.xm.login.d.f(m2.toString());
        } else {
            com.sankuai.xm.login.d.a("IMCore:send: info == null");
        }
        a0(vVar.marshall());  //这里直接把传进去的参数组包拿出来
    }

4.继续跟进 public final byte[] marshall() 方法

    @Override // com.sankuai.xm.base.proto.protobase.g, com.sankuai.xm.base.proto.protobase.b
    public final byte[] marshall() {
        Object[] objArr = new Object[0];
        ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr, this, changeQuickRedirect2, 5041258)) {
            return (byte[]) PatchProxy.accessDispatch(objArr, this, changeQuickRedirect2, 5041258);
        }
        O(1966080026);   //发送私信消息标签
        C(this.f);     //传进来的参数
        A(this.g);    //传进来的参数
        x(this.h);    //传进来的参数
        D(this.d);   //传进来的参数
        A(this.i);    //传进来的参数
        D(this.j);   //传进来的参数
        return super.marshall();   //返回父类的值
    }

5.继续跟进父类 super.marshall() 方法

    @Override // com.sankuai.xm.base.proto.protobase.b
    public byte[] marshall() {
        int i;
        int i2;
        Object[] objArr = new Object[0];
        ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect;
        if (PatchProxy.isSupport(objArr, this, changeQuickRedirect2, 767391)) {
            return (byte[]) PatchProxy.accessDispatch(objArr, this, changeQuickRedirect2, 767391);
        }
        this.c.d = 0;
        b(0);
        this.c.f87920a = this.f87924b.position();
        this.f87924b.putInt(0, this.c.f87920a); // 整个TCP数据包的长度
        this.f87924b.putInt(4, this.c.f87921b); //发送私信消息标签
        this.f87924b.putShort(8, this.c.c);
        this.f87924b.putShort(10, this.c.d);
        this.f87924b.putInt(12, 0);                  //CRC32签名   空置
        d dVar = this.c;
        if (dVar.f <= 0) {
            Object[] objArr2 = new Object[0];
            ChangeQuickRedirect changeQuickRedirect3 = changeQuickRedirect;
            if (PatchProxy.isSupport(objArr2, null, changeQuickRedirect3, 2979355)) {
                i = ((Integer) PatchProxy.accessDispatch(objArr2, null, changeQuickRedirect3, 2979355)).intValue();
            } else {
                synchronized (g.class) {
                    f87925e++;
                    if (f87925e <= 0) {
                        f87925e = 1;
                    }
                    i2 = f87925e;
                }
                i = i2;
            }
            dVar.f = i;
        }
        this.f87924b.putInt(16, this.c.f);   //该类调用次数
        this.f87924b.putInt(20, this.c.g);  //固定
        byte[] bArr = new byte[this.c.f87920a];  // new  一个字节集数组
        this.f87924b.position(0);
        this.f87924b.get(bArr);    //把 this.f87924b 数据存放进bArr里面
        int F = F(bArr);                //CRC32  签名 存放进来的数据
        this.f87924b.putInt(12, F);  //把数据包的签名放进第12个位置
        this.c.f87922e = F;
        this.f87924b.position(0);
        this.f87924b.get(bArr);    // 把最终数据存放进bArr里面
        this.f87924b = null;
        return bArr;         //返回最终byte[]数据
    }

6.TCP 发送私信消息数据包分析完毕,其他功能也都差不多基本没啥大的变化

解析发送二进制数据包:

由于高版本有抽掉关键方法,接下来解析发送数据包和接收数据包的版本为:【10.20.3】
原始TCP私信消息数据包:{ 0, 0, 0, 211, 117, 48, 0, 26, 0, 21, 0, 0, 120, 35, 246, 110, 0, 0, 0, 0, 0, 0, 0, 0, 1, 145, 0, 0, 0, 0, 162, 43, 86, 195, 0, 175, 0, 0, 0, 175, 1, 145, 0, 1, 0, 21, 1, 0, 36, 48, 50, 102, 53, 101, 52, 48, 100, 45, 102, 49, 55, 53, 45, 55, 53, 97, 55, 45, 49, 54, 55, 57, 45, 54, 56, 99, 99, 102, 51, 56, 57, 51, 102, 48, 48, 0, 0, 0, 0, 162, 43, 86, 195, 0, 0, 0, 0, 174, 101, 177, 52, 0, 0, 0, 1, 0, 51, 0, 0, 0, 51, 1, 145, 0, 9, 0, 21, 0, 30, 228, 189, 160, 229, 165, 189, 229, 149, 138, 239, 188, 140, 230, 136, 145, 230, 152, 175, 232, 165, 191, 233, 163, 142, 230, 184, 184, 230, 136, 143, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 5, 67, 121, 100, 105, 97, 0, 0, 1, 141, 229, 167, 215, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

1. {0, 0, 0, 211}    //数据包的长度
2. {117, 48, 0, 26}   // 小端 数据标签 【1966080026】 私信消息标签
3. { 0, 21, 0, 0}   //  固定
4. {120, 35, 246, 110}   //CRC32  TCP数据包签名
5. {0, 0, 0, 0, 0, 0, 0, 0, 1, 145, 0, 0, 0, 0}   //固定一整段数据
6. {162, 43, 86, 195}   // 小端  该号的Chatid 
7. {0, 175, 0, 0, 0, 175, 1, 145, 0, 1, 0, 21, 1, 0}     // 两个字节 [175]   来源于整个【TCP数据的长度 - 36】
8. {36, 48, 50, 102, 53, 101, 52, 48, 100, 45, 102, 49, 55, 53, 45, 55, 53, 97, 55, 45, 49, 54, 55, 57, 45, 54, 56, 99, 99, 102, 51, 56, 57, 51, 102, 48, 48}  //长度为36的uuid
10. {0, 0, 0, 0}    //固定填充数据
11. {162, 43, 86, 195}   // 小端  该号的Chatid 
12.  {0, 0, 0, 0}    //固定填充数据
13.  {174, 101, 177, 52}    // 小端  对方的Chatid 
13.  {51, 0, 0, 0, 51, 1, 145, 0, 9, 0, 21, 0}    // 两个字节 [51]    来源于 【21 + 取字节集长度 (编码_UTF8编码 (content, ))】
13.  { 30, 228, 189, 160, 229, 165, 189, 229, 149, 138, 239, 188, 140, 230, 136, 145, 230, 152, 175, 232, 165, 191, 233, 163, 142, 230, 184, 184, 230, 136, 143}    //长度为30的 Content【你好啊,我是西风游戏】 私信信息内容
13.  {0, 0, 0, 0, 0, 13, 0, 0, 0, 0}   // 固定
14.  {5, 67, 121, 100, 105, 97}   //长度为5的昵称 【Cydia】 
15.  {0, 0, 1, 141, 229, 167, 215, 138}   // 小端  取13位的现行时间戳
16.  {0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}   //固定数据

解析接收二进制数据包:

接收消息数据包:{ 0, 0, 1, 14, 117, 48, 0, 28, 0, 21, 0, 0, 112, 217, 83, 80, 1, 212, 56, 119, 0, 0, 0, 0, 0, 0, 0, 0, 143, 244, 221, 46, 1, 20, 53, 189, 210, 27, 2, 240, 0, 0, 219, 0, 0, 0, 219, 1, 145, 0, 1, 0, 21, 1, 0, 36, 101, 53, 100, 54, 55, 50, 97, 56, 45, 52, 48, 48, 53, 45, 99, 50, 51, 49, 45, 98, 98, 56, 48, 45, 52, 55, 56, 98, 55, 51, 48, 102, 101, 101, 98, 99, 0, 0, 0, 0, 162, 43, 86, 195, 0, 0, 0, 0, 143, 244, 221, 46, 0, 0, 0, 1, 0, 51, 0, 0, 0, 51, 1, 145, 0, 9, 0, 21, 0, 30, 228, 189, 160, 229, 165, 189, 229, 149, 138, 227, 128, 130, 230, 136, 145, 230, 152, 175, 232, 165, 191, 233, 163, 142, 230, 184, 184, 230, 136, 143, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 5, 67, 121, 100, 105, 97, 0, 0, 1, 141, 229, 208, 96, 217, 20, 53, 189, 210, 27, 2, 240, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 240, 0, 0, 1, 141, 229, 61, 137, 52, 0, 0, 0, 41, 48, 49, 97, 57, 53, 53, 50, 52, 45, 101, 49, 57, 54, 45, 52, 50, 101, 55, 45, 98, 54, 54, 100, 45, 100, 102, 50, 49, 99, 98, 48, 52, 53, 97, 56, 98, 95, 49, 95, 50, 49, 0, 101, 220, 159, 215, 161, 218, 223, 55 }

目前只解析比较重要的数据:
1.{36, 101, 53, 100, 54, 55, 50, 97, 56, 45, 52, 48, 48, 53, 45, 99, 50, 51, 49, 45, 98, 98, 56, 48, 45, 52, 55, 56, 98, 55, 51, 48, 102, 101, 101, 98, 99} //36位的uuid
2.{162, 43, 86, 195}  //本号的Chatid 小端
3.{143, 244, 221, 46} //对方的Chatid 小端   大概就是这样了
4.{30, 228, 189, 160, 229, 165, 189, 229, 149, 138, 227, 128, 130, 230, 136, 145, 230, 152, 175, 232, 165, 191, 233, 163, 142, 230, 184, 184, 230, 136, 143}
 //长度为30的消息数据  对方回复的消息【你好啊。我是西风游戏】
重要的数据解析完毕。

至此,TCP协议三步走完了// 初始化密钥-->初始化token令牌-->私信协议

再次声明仅供学习交流 若侵犯了权益,麻烦管理帮忙删除,谢谢

下面附上协议交互:

Chatid:2720749251

2024年2月26日23时3分32秒 更新通讯密钥成功!

登陆聊天服务器:103.X.X.X:8500 | 连接是否成功: 真
========================================
当前心跳包发送:真
------------------------------------------------
本号发送消息:真 | 2024年2月26日23时4分

Content: 【你好啊,我是西风游戏,测试端嗯】
------------------------------------------------------------------
对方[2415189294]回复消息时间: 2024年2月26日23时4分14秒

Content:【我知道你是测试端,哎我也是测试端】
------------------------------------------------------------------

===================分割线=========================

Chatid:2415189294

2024年2月26日23时3分29秒 更新通讯密钥成功!

登陆聊天服务器:103.X.X.X:8500 | 连接是否成功: 真
========================================
当前心跳包发送:真
------------------------------------------------
对方[2720749251]回复消息时间: 2024年2月26日23时4分

Content:【你好啊,我是西风游戏,测试端嗯】
------------------------------------------------------------------
本号发送消息:真 | 2024年2月26日23时4分14秒

Content: 【我知道你是测试端,哎我也是测试端】
------------------------------------------------------------------

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
janken + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
影狼幽恋 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

nitian0963 发表于 2024-2-27 13:51
谢谢,学习中
qfxldhw 发表于 2024-2-27 13:54
oneline111 发表于 2024-2-27 14:13
wozhuwulou 发表于 2024-2-27 15:35
感谢分享
wbylll 发表于 2024-2-27 21:01
感谢,学习中
lzy541541 发表于 2024-3-4 11:24
收藏一波
kwy888 发表于 2024-3-21 20:11
感谢分享,学习中
yoga2joker 发表于 2024-5-13 16:27
谢谢分享!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 09:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表