CC某V app加密分析及视频提取

查看 154|回复 11
作者:spcspcspcspcspc   
还是先感谢热心网友分享的APP,这几天有空就又出了一篇帖子,和上篇的思路基本相同。
程序中所有地址及数据均经过修改,不作为真实数据!仅提供分析方法!。
        程序分析第一步 抓包。
        请求内容类似
[color=]{"data":"nrDugWses删除一大段BdbYTixA5MQ==","handshake":"v20200610"}

        返回的内容为乱码,经仔细辨认十六进制中包含
[color=]1F8B0800
,这是
[color=]gzip
格式压缩。
        直接解压出来类似
[color=]{"code":200,"message":"操作成功","data":"ObzEZUE4删除一大段sJUQo0RI","handshake":"v20200610"}

        可以看到来回的信息里面data都经过加密了,一看就是很火的AES加密!假如你看不出来是什么加密方式,一步步来分析他。
        JADX打开app,搜索"data",发现出来200多条信息,我们换个关键词"handshake",结果只有一条。
[Java] 纯文本查看 复制代码 public static final String f26955g = "handshake";
        继续以
[color=]f26955g
为关键字搜索,出来2条。我们进另外一条看看
  [Java] 纯文本查看 复制代码     if (sVar.mo33077c() != 0) {            String a = JSONUtil.m36637a(new JSONObject(hashMap2));
            LogUtils.m14031b("===ParamsString: " + a);
            hashMap.put("data", AESUtils.m40156b(a));
        }
        hashMap.put(AbstractC4663a.f26955g, "v20200610");
        String a2 = JSONUtil.m36637a(hashMap);
        LogUtils.m14031b("===realParamsJson: " + a2);
        return b0Var.mo32465f().mo32478a(b0Var.mo32467h()).mo32473a(f26933d, RequestBody.m46225a(this.f26934a, String.valueOf(a2))).mo32479a();
    }
        上面果然出现了
[color=]"data"
,后面的
[color=]AESUtils.m40156b
就是加密函数了,CTRL再单击
[color=]m40156b
,跟进去看看:           
[Java] 纯文本查看 复制代码 public static String m40156b(String str) {        if (f28855c.equals("AES/ECB/NoPadding")) {
            while (str.getBytes().length % 16 != 0) {
                str = str + ' ';
            }
        }
        byte[] k = EncryptUtils.m15560k(str.getBytes(), f28856d.getBytes(), f28855c, null);
        return k != null ? new String(k) : "";
    }
}
        看到"AES/ECB/NoPadding"是不是很激动,但这不是加密方式,
[color=]f28855c
才是真正的加密方式,CTRL再单击
[color=]f28855c
[Java] 纯文本查看 复制代码  private static String f28855c = "AES/ECB/PKCS7Padding";
        所以真正的加密方式是"AES/ECB/PKCS7Padding",返回再跟进
[color=]EncryptUtils.m15560k
看看:
[Java] 纯文本查看 复制代码   public static byte[] m15560k(byte[] bArr, byte[] bArr2, String str, byte[] bArr3) {   
return m15513b(m15556j(bArr, bArr2, str, bArr3));
   }
        CTRL再单击
[color=]m15556j

[Java] 纯文本查看 复制代码  public static byte[] m15556j(byte[] bArr, byte[] bArr2, String str, byte[] bArr3) {  
return m15504a(bArr, bArr2, "AES", str, bArr3, true);
    }
        CTRL再单击
[color=]m15504a
   [Java] 纯文本查看 复制代码 private static byte[] m15504a(byte[] bArr, byte[] bArr2, String str, String str2, byte[] bArr3, boolean z) {  
                        SecretKey secretKey;
                              if ("DES".equals(str)) {
                    secretKey = SecretKeyFactory.getInstance(str).generateSecret(new DESKeySpec(bArr2));
                } else {
                    secretKey = new SecretKeySpec(bArr2, str);
                }
                Cipher instance = Cipher.getInstance(str2);
        
[color=]secretKey
就是密码,这一步中
[color=]str
为上面的
[color=]"AES"
,所以
[color=]bArr2
就是关键密码。
        一路反推回去其实就是
[color=]EncryptUtils.m15560k(str.getBytes(), f28856d.getBytes(), f28855c, null);
中的
[color=]f28856d

        CTRL再单击
[color=]f28856d
[Java] 纯文本查看 复制代码 private static String f28856d;
    static {
        String str;
        if (TextUtils.equals("release", "debug")) {
            str = TestUtil.getSecret2();
        } else {
            str = TextUtils.equals("release", "staging") ? TestUtil.getSecretPre() : TestUtil.getSecret();
        }
        f28856d = str;
    }这一步就是判断APP是测试版还是正式版使用不同密码,随便跟一个进去,例如CTRL再单击TestUtil.getSecretPre[Java] 纯文本查看 复制代码public class TestUtil {
    static {
        System.loadLibrary("security");
    }
    public static native String getSecret();
    public static native String getSecret2();
    public static native String getSecret3();
    public static native String getSecretPre();
    public static native String getSecretVP();
}loadLibrary是调用的系统"
[color=]security
"的模块,并没法直接看到明文。继续往下分析:直接用压缩软件把app解压,文件夹中搜索
[color=]security
,出现两个
[color=]libsecurity.so
,一个在\lib\arm64-v8a中,一个在lib\armeabi-v7a。打开IDA软件,把libsecurity.so拖进去,左侧列表就出现了
[color=]Java_com_niming_weipa_utils_TestUtil_getSecret
等函数,点击进去看看,右侧窗口F5,转为JAVA代码[Java] 纯文本查看 复制代码__int64 __fastcall Java_com_niming_weipa_utils_TestUtil_getSecret(__int64 a1)
{
  return (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)a1 + 1336LL))(a1, "0MDQRQgYI4a9e3Zns");
}以此类推,一共有
[color=]"A7D90#83B1o6!d1F6","4rKFwocME2SIp4Anftc","E8yC1EncqQ3ZrfWQg","0MDQRQgYI4a9e3Zns"
四种密码。直接一个个试试吧。其中有一个就是密码。把所有发送请求的数据解压成明文,还是采用JSON数据,其中
[color=]list/hot
的链接返回内容直接包含视频地址,
[color=]“is_free”
标签有的是0有的是1,不知道是不是收费和免费的意思,如果是那收费的也就都可以看了。
[color=]api/user/info
链接返回的数据应该是用户信息,其中
[color=]"coins":0和"is_vip":"n"
感觉可以伪造一下数据破解一下本地VIP。留给感兴趣的同学去研究吧。
当我们再次去请求数据的时候显示认证失败!!!看来还是有坑。仔细观察发现请求的头部参数里有个
[color=]X-TOKEN: 6rb+/wSXpc删除一大段S1JJZNQ30g7RvMmNJQE
[color=](下面关于
X-TOKEN的分析有错误,正确方法见文章末尾)再仔细观察发现在
[color=]auth/login/device
链接中返回的数据中包含有
[color=]TOKEN
的参数,所以可以先请求
[color=]auth/login/device
获取
[color=]X-TOKEN
的参数后,再加到协议头里,再请求
[color=]list/hot
链接就正常了。 至此app的加密分析就结束了。
因为没找到易语言"AES/ECB/PKCS7Padding"加密解密的模块或者算法,所以就没有深入研究,也没有成品。(即使有也不可能发布的!)  如果有易语言"AES/ECB/PKCS7Padding"加密解密的模块或者算法的请分享交流,谢谢!  

X-TOKEN的参数解密后数据为{"device_no":"e509-a93d-3e02-b39-205b6","device_type":"A","token":"eyJ0eXAiOiJKV1删除一大段QiLre1visa1s","version":"1.0.0"}
所以可以先请求
[color=]auth/login/device
获取
[color=]TOKEN
的参数后,替换掉上面的“
token
”参数,加密后数据给到X-TOKEN,再加到协议头里,再请求list/hot链接就正常了。邀请码得会员流程:伪造device_no(8个随机数-3个随机数-12个随机数),替换下列行中的999999999,[Asm] 纯文本查看 复制代码{"channel":"","code":"","device_no":"999999999","device_type":"A","version":"1.0.1"}加密后的数据替换下列行中的999999999,[Asm] 纯文本查看 复制代码{"data":"999999999","handshake":"v20200610"}附加协议头后发送 ***/app/api/auth/login/device,返回数据提取data数据解密,提取token数据,替换下列行中的999999999,device_no替换下列行中的88888888[Asm] 纯文本查看 复制代码{"device_no":"88888888","device_type":"A","token":"999999999","version":"1.0.1"}加密后的数据替换下列行中的999999999,[Asm] 纯文本查看 复制代码Accept-Language: zh-CN,zh;q=0.8
User-Agent: Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleDart/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17
Accept: application/json
X-TOKEN: 999999999
Content-Type: application/json; charset=utf-8
Connection: Keep-Alive
Accept-Encoding: gzip上面作为协议头,邀请码替换下行的666666作为数据[Asm] 纯文本查看 复制代码{"code":"666666"}发送**/app/api/user/bindcode返回信息提取message为“操作成功”就是成功邀请了一个账户。每邀请一个可以得3天VIP,可以累计叠加,永久会员不是梦

微软, 代码

逍遥一仙   


闷骚小贱男 发表于 2021-1-6 16:54
原来我一直用的M3U8下载器是大佬你的呀...上一次提醒我E2EE我没太注意.
这一次我去试了试.发现了一点问 ...

已帮你测试,易语言内部为gbk编码,如网站使用utf8编码,需要先转换下。套一个e2ee的文本编码转换即可。
文本编码转换 (“吾爱破解”, “GBK”, “UTF-8”)
spcspcspcspcspc
OP
  


闷骚小贱男 发表于 2021-2-23 16:00
[md]
好像输出变量都用字节集  再到文本能输出123123

我之前也遇到同样的问题,正确方法如下
[Erlang] 纯文本查看 复制代码e2ee.加密数据 (#算法_AES_128_CBC, “123123”, “ed0f0f7e7ae8d46f521076d61fffb555”, 结果, #填充方式_PKCS5, 到字节集 (“2f71a0c886360026”), #文本内容类型_Base64)
调试输出 (“加密:” + 结果)
e2ee.解密数据 (#算法_AES_128_CBC, Base64解码 (结果, ), “ed0f0f7e7ae8d46f521076d61fffb555”, 结果1, #填充方式_PKCS5, 到字节集 (“2f71a0c886360026”), #文本内容类型_原始内容)
调试输出 (“解密:” + 结果1)
加密后结果为Base64加密,必须先 Base64解码 (结果, ) ,最后的编码是 #文本内容类型_原始内容 ,这样才能解密原始信息。
感觉这个解密最后的参数 ‘文本输出方式’应该改为‘文本输入方式’才对,因该是个小BUG。
逍遥一仙   

易语言加解密建议使用E2EE->加解密对象。如有RSA需求,使用 RSA加解密 类
m_h   

https://www.cnblogs.com/midea0978/articles/1437257.html
关于PKCS5Padding与PKCS7Padding的区别  学习下填充字节区分方法。。
https://www.jianshu.com/p/a9add8119089
http://www.toocruel.net/aes-ecb/
不会java会点点C(百度)和pascal.
闷骚小贱男   

分享个自用的在线AES解密网站https://www.keylala.cn/aes
M3U8大佬说的E2EE中的AES加解密挺实用的。
四、易语言AES-CBC加解密源码(JS):

    原理:脚本组件调用
[color=]cryptoJS
达到AES加解密,默认是CBC模式
    最近的几期:某哩某哩和某岛都可以用这个加解密的
   
   
源码
下载地址:https://wwa.lanzouj.com/isazLjsiqfg 密码:52pj
spcspcspcspcspc
OP
  


逍遥一仙 发表于 2021-1-6 16:27
易语言加解密建议使用E2EE->加解密对象。如有RSA需求,使用 RSA加解密 类

谢谢指点,,我去试一试
spcspcspcspcspc
OP
  


m_h 发表于 2021-1-6 16:27
https://www.cnblogs.com/midea0978/articles/1437257.html
关于PKCS5Padding与PKCS7Padding的区别  学习 ...

多谢分享,回头仔细研究下
syrmb   

pkcs7和pkcs5是一样的
spcspcspcspcspc
OP
  


闷骚小贱男 发表于 2021-1-6 16:35
分享个自用的在线AES解密网站https://www.keylala.cn/aes

感谢分享,,非常好用!
您需要登录后才可以回帖 登录 | 立即注册