某音乐app登录协议分析
抓包后需要对params
,pk
,t1
,t2
,t3
,key
这几个参数进行分析
搜索字段关键词后得到t1(token) t2(machineIdCode) clienttime_ms
这三个参数是在com.kugou.common.useraccount.entity.q
中生成的
t3
是在com.kugou.framework.specialradio.d.b.a
中生成的
dfid plat pk username support_third support_multi support_verify key dev gitversion params
是在com.kugou.common.useraccount.b.ad$b.rW_
中生成的
t1
t1
是调用getToken
生成的,此函数最后会调用一个native函数com.kugou.common.player.kugouplayer.j._d
对应的是libj.so
在JNI_Onload
中调用register_kugou_player_mediautilsextra
注册的,对应的函数就是cc::d(_JNIEnv *,_jobject *,_jobject *)
cc::d
会调用f4
函数,并且f4
传入的参数v5
是一个std::string
类型,随后调用std::string::c_str()
并传入NewStringUTF
返回一个jstring,对应的就是t1
的值
参照cc::d
调用std::string::c_str()
的方式用frida实现
function std_string_c_str(std_string){
var ret
if ((std_string.readU64() & 1) != 0 ){
ret = std_string.add(8 * 2).readPointer()
}
else{
ret = std_string.add(1)
}
return ret
}
经过对f4
的分析后对各个关键函数进行hook和打印,最后的t1
生成过程如下。
- 尝试打开
/data/user/0/com.kugou.android/files/test.txt
文件失败 - 调用
f5
返回时间戳 - 调用
h15
并将"|" + 时间戳
作为参数传入 - 调用
h14
进行aes加密,input为"|" + 时间戳
,key为fd387891254e6cedc4019ca0061ea6d9
,iv为c4019ca0061ea6d9
,输出为aes加密 f4
的返回值就是aes
加密的结果,也就是t1
的值
验证一下算法
t2
t2
也是调用native函数生成的,对应的是cc::e(_JNIEnv *,_jobject *,_jobject *)
,同样对各个关键函数进行hook,t2
的生成过程如下。
- 调用
getAndroidId
返回androidId并进行md5 - 调用
getSafeDeviceId
返回SafeDeviceId
并进行md5 - 获取
android.os.Build.MODEL
- 获取时间戳
- 调用
h14
进行aes加密,key为ce1e88d78dff2132dbfbb91af0ea9ca7
,iv为dbfbb91af0ea9ca7
,输入为之前获取信息拼接的结果,输出为aes加密结果也就是t2
的值
验证一下算法
t3
t3就是将输入的一些值进行base64
key
key
是通过传入一个字符串进行rsa加密得到的
hook 整个生成过程如下,其会将appid
,appkey
,versionCode
和时间戳进行连接后进行md5,md5结果就是key
的值
pk
pk
是将一个字符串进行rsa加密
hook 整个生成过程如下,待加密数据是一个时间戳和一个随机生成的key的js的格式,rsa公钥是MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIAG7QOELSYoIJvTFJhMpe1s/gbjDJX51HBNnEl5HXqTW6lQ7LC8jr9fWZTwusknp+sVGzwd40MwP6U5yDE27M/X1+UR4tvOGOqp94TJtQ1EPnWGWXngpeIW5GxoQGao1rmYWAu6oi1z9XkChrsUdC6DJE5E221wf/4WLFxwAtRQIDAQAB
,加密结果就是pk
的值
params
params
是通过AES加密生成的
hook 整个生成过程如下,待加密数据是username
,clienttime_ms
和pwd
的js的格式,aes的key是pk.key
的md5值,iv是pk.key
的md5值得后16个字节,最后得加密结果就是params
的值