某无名视频App协议逆向
2020-01-31 05:34:08 Author: bbs.pediy.com(查看原文) 阅读量:472 收藏

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

2020-1-24 01:04 680

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生成 用户登录->信息注册->请求加密->响应解密->播放视频

2020安全开发者峰会(2020 SDC)议题征集 中国.北京 7月!


文章来源: https://bbs.pediy.com/thread-257367.htm
如有侵权请联系:admin#unsafe.sh