首页
社区
课程
招聘
[原创]某无名视频App协议逆向
发表于: 2020-1-24 01:04 8760

[原创]某无名视频App协议逆向

2020-1-24 01:04
8760

0x00 说明

随便找了一个视频app进行了逆向分析,分享一下协议破解过程,大佬勿喷 (#^.^#)


0x01逻辑分析

1、apk分析


apk进行了加壳保护,砸壳如下


app逻辑基本上都在这个source-5871984.dex中,重点看一下这个dex


2、 请求抓包分析

用户登录

request


response


请求和响应进行了加密,通过对dex进行关键字搜索找到加解密函数


解密函数如下

   private static SecretKeySpec m68do(String str) {
        byte[] bArr;
        if (str == null) {
            str = "";
        }
        StringBuffer stringBuffer = new StringBuffer(16);
        stringBuffer.append(str);
        while (stringBuffer.length() < 16) {
            stringBuffer.append("0");
        }
        if (stringBuffer.length() > 16) {
            stringBuffer.setLength(16);
        }
        try {
            bArr = stringBuffer.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            bArr = null;
        }
        return new SecretKeySpec(bArr, "AES");
    }
    private static byte[] c(byte[] bArr, String str, String str2) {
        try {
            SecretKeySpec secretKeySpec = m68do(str);
            IvParameterSpec dp = dp(str2);
            Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
            instance.init(2, secretKeySpec, dp);
            return instance.doFinal(bArr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    private static IvParameterSpec dp(String str) {
        byte[] bArr;
        if (str == null) {
            str = "";
        }
        StringBuffer stringBuffer = new StringBuffer(16);
        stringBuffer.append(str);
        while (stringBuffer.length() < 16) {
            stringBuffer.append("0");
        }
        if (stringBuffer.length() > 16) {
            stringBuffer.setLength(16);
        }
        try {
            bArr = stringBuffer.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            bArr = null;
        }
        return new IvParameterSpec(bArr);
    }

    public static String p(String str, String str2, String str3) {
        byte[] bArr;
        String str4;
        try {
            bArr = hexString2Bytes(str);
        } catch (Exception e) {
            e.printStackTrace();
            bArr = null;
        }
        byte[] c2 = c(bArr, str2, str3);
        if (c2 == null) {
            return null;
        }
        try {
            str4 = new String(c2, "UTF-8");
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
            str4 = null;
        }
        return str4;
    }

    public static byte[] hexString2Bytes(String str) {
        if (isSpace(str)) {
            return null;
        }
        int length = str.length();
        if (length % 2 != 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("0");
            sb.append(str);
            str = sb.toString();
            length++;
        }
        char[] charArray = str.toUpperCase().toCharArray();
        byte[] bArr = new byte[(length >> 1)];
        for (int i = 0; i < length; i += 2) {
            bArr[i >> 1] = (byte) ((b(charArray[i]) << 4) | b(charArray[i + 1]));
        }
        return bArr;
    }

    private static int b(char c2) {
        if (c2 >= '0' && c2 <= '9') {
            return c2 - '0';
        }
        if (c2 >= 'A' && c2 <= 'F') {
            return (c2 - 'A') + 10;
        }
        throw new IllegalArgumentException();
    }

    private static boolean isSpace(String str) {
        if (str == null) {
            return true;
        }
        int length = str.length();
        for (int i = 0; i < length; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

keyFromJNI

viFromJNI

使用方法:
p(asString, keyFromJNI, viFromJNI)

密文
2593194C061134517AAD27E8DBE5421F795A486AF409F823715A36810114EF9056078D9CC978A00C93C7AD6C885506B8AAFE23AE69279F7FAD794437FBBF35BD7876D4C9255D0FF5790B1A54359BC7573F5BDFC430AC20063955557028CFF18A
解密
{"token_id":"2652308","token":"834b2815a8739569f1b38a25027c337b","serverCode":"20190705-17"}
并进行了preferences存储

后续所有请求都使用了token、token_id并进行请求加密

例如列表请求

request


request_key=234A4D14B2693D1ABB7AFD62E132CEDC -- > {"pid":"1"}

response

解密如下

ps:后续的视频的详情使用了vod_id进行请求,然后进行播放,很简单这里就不进一步展示了。

例如检查更新,哦哦 明文的,略过。


0x03 总结

1、这个视频app进行的防护比较典型 加壳+协议加密

2、用户信息是以android客户端进行的token生成 用户登录->信息注册->请求加密->响应解密->播放视频





[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 3
支持
分享
最新回复 (13)
雪    币: 6890
活跃值: (8949)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
2
瑟瑟发抖。。。
2020-1-24 16:13
0
雪    币: 11015
活跃值: (7199)
能力值: ( LV12,RANK:214 )
在线值:
发帖
回帖
粉丝
3
无名侠 瑟瑟发抖。。。
哇塞 无名大佬来啦
2020-1-24 19:39
0
雪    币: 0
活跃值: (130)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主砸壳怎么砸的?
2020-1-31 13:31
0
雪    币: 11015
活跃值: (7199)
能力值: ( LV12,RANK:214 )
在线值:
发帖
回帖
粉丝
5
天路 楼主砸壳怎么砸的?
我用的易开发 
2020-1-31 14:11
0
雪    币: 0
活跃值: (130)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
neilwu 我用的易开发
易开发能脱壳?不是吧
2020-2-2 12:31
0
雪    币: 11015
活跃值: (7199)
能力值: ( LV12,RANK:214 )
在线值:
发帖
回帖
粉丝
7
天路 易开发能脱壳?不是吧
可以啊 fdex也可以脱
2020-2-2 12:48
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
怎么转成源代码的?
2020-2-3 20:29
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
支持下
2020-3-6 10:55
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
请教下最后视频有个防盗链,实际访问.....index.m3u8?wsSecret=a8df6b97b903864313410213863f69c1&wsTime=1591761000这样带上时间戳和加密结果才有效,用time做的MD5加密,怎么破解这个加密规则?
2020-6-18 10:12
0
雪    币: 11015
活跃值: (7199)
能力值: ( LV12,RANK:214 )
在线值:
发帖
回帖
粉丝
11
wx_彭靖 请教下最后视频有个防盗链,实际访问.....index.m3u8?wsSecret=a8df6b97b903864313410213863f69c1&wsTime=1591761000这样带上 ...
逆向呗
2020-6-18 14:20
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
neilwu 逆向呗

试一下

最后于 2020-8-18 10:02 被wx_彭靖编辑 ,原因:
2020-6-19 12:14
0
雪    币: 19878
活跃值: (4912)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
支持一下
2020-6-20 19:29
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
neilwu 逆向呗

弄出来了

最后于 2020-8-18 10:01 被wx_彭靖编辑 ,原因:
2020-6-23 14:04
0
游客
登录 | 注册 方可回帖
返回
//