-
-
[原创]某无名视频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作者讲授!