app 版本:5.0.0
设备:K40 刷 piexl 11 rom
抓包工具:Charles
反汇编工具:JEB、JADX、IDA
inject:frida
POST /v1/api/app/login/doLogin HTTP/1.1
X-OsVersion: 30
User-Agent: Mo
zilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1
X-RandomNum: 54736
X-Access-Token: 00871d5df0d4f51efb5883b3b2fd2359
platform: android
X-Ca-Signature-Headers: X-Ca-Timestamp,X-Ca-Key,X-Ca-Nonce
Authorization:
X-OS: Android
c_appVersion: 5.0.0
X-App-ID: CSDN-APP
X-App-Theme: day
content-type: application/json; charset=UTF-8
X-Ca-Signature: BqhPpXbobBOndykiyCtOVK06GHLkfLbs1y4B3Ek0gnY=
X-ConnectionType: WIFI
UserToken:
X-TimeStamp: 1671939318488
Cookie: UserName=;UserToken=
X-Ca-Key: 203789067
Accept: application/json
X-Device-ID: aid0f0fef992b53479187546b3c621157f0
wToken: e447_5rU5WWYQegPo5EMOZSnKzF4YPtJSetwo+lGrEUrtZaKEe73GkiTOoE83PLp0yivsi4pZV7HySc+lbsebppMqHlXmQwVLx0vrlQpYC0b99vOYBRZWnVbeMhLZ4WUuAAKH/V07WkNSNXORUsgHumLj1BZZ7x1riK8beahdp9ctmSwP3AdA/sZA4OkzEVF4rJ+G6nwyyGcI/JLoRH0/1hPUT91sdBKKA64yj1QKRAZuJjsX9WRcqo9xYgfcJDnpqVnhObGQD96CfSok8z8d9otv+Fl6ULZrddvcnvzs6cJhjuW3ryBn151Xat/2CU/9EXUEKG3e0g4/K9rEaDRb2JhDGEDwIj+Qd5RU1uaBKxS/7jlSVq8wQ7x3qVVN1tHqS4AXhVow6eMABT6PArcEfkFm42bwXOFWsAUd5C7uGvHGIlTGytU6Vx/CJPwPvCuSffef5mQL7daszEzN+zQJ9VjxgOrjKXkDVkt6O6UpyA+1u3lowOqUaSPK6u2vND/Xqus7&ff4b_85475962D8E15A4E7AE60ED42FF3568E8EDB86EE620E495591
X-DeviceModel: Redmi M2012K11AC
version: 5.0.0
X-Ca-Nonce: be0eca5c-e959-4b0f-b4e7-22e00118157e
X-Ca-Timestamp: 1671939318489
X-Sign: 70B21B02FD0EFD2353F0D7F4F2E7CDB6FC1C3C42
Host: passport.csdn.net
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 95
{"pwdOrVerifyCode":"123456","loginType":"1","userIdentification":"17750659921","checkAli":true}
意料之中一大堆参数,反复几次总结需分析的参数应该为以下几个:
X-Sign、wToken、X-Ca-Signature、X-Access-Token、X-Ca-Timestamp
先搜索 X-Sign,就一处:
跟进得:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
public static
Map
<String, String> z(String url,
Map
<String, String> requestMap) {
String
str
;
String a2
=
wo3.a(CSDNApp.csdnApp);
HashMap hashMap
=
new HashMap();
hashMap.put(
"platform"
,
"android"
);
hashMap.put(
"version"
, xn3.u());
hashMap.put(
"c_appVersion"
, xn3.u());
if
(!TextUtils.isEmpty(it3.g())) {
hashMap.put(
"JWT-TOKEN"
, it3.g());
no3.a(
"==JWT-TOKEN=="
, it3.g());
}
hashMap.put(
"Authorization"
, StringUtils.isEmpty(it3.g()) ? "
" : "
Bearer "
+
it3.g());
hashMap.put(
"X-Device-ID"
, a2);
hashMap.put(
"X-OS"
,
"Android"
);
hashMap.put(
"X-App-ID"
,
"CSDN-APP"
);
hashMap.put(
"X-Access-Token"
, MD5.md5(a2
+
"AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656"
));
hashMap.put(
"X-OsVersion"
, Build.VERSION.SDK_INT
+
"");
String str2
=
Build.BRAND
+
Operators.SPACE_STR
+
Build.MODEL;
int
length
=
str2.length();
for
(
int
i
=
0
; i < length; i
+
+
) {
char charAt
=
str2.charAt(i);
if
((charAt <
=
31
&& charAt !
=
'\t'
) || charAt >
=
127
) {
str2.replace(charAt,
' '
);
}
}
hashMap.put(
"X-DeviceModel"
, str2);
hashMap.put(
"X-ConnectionType"
, yp3.b(CSDNApp.csdnApp));
hashMap.put(
"UserToken"
, StringUtils.isEmpty(it3.q()) ? "" : it3.q());
hashMap.put(
"X-App-Theme"
, CSDNApp.isDayMode ?
"day"
:
"night"
);
int
c2
=
xn3.c(
10000
,
99999
);
String str3
=
new Date().getTime()
+
"";
try
{
str
=
mq3.a(a2
+
c2
+
str3
+
zf1.o);
} catch (DigestException e2) {
e2.printStackTrace();
str
=
"";
}
hashMap.put(
"X-Sign"
,
str
);
hashMap.put(
"X-RandomNum"
, c2
+
"");
hashMap.put(
"X-TimeStamp"
, str3);
StringBuilder sb
=
new StringBuilder();
sb.append(
"UserName="
);
sb.append(it3.p());
sb.append(
";UserToken="
);
sb.append(StringUtils.isEmpty(it3.q()) ? "" : it3.q());
hashMap.put(IWebview.COOKIE, sb.toString());
if
(!StringUtils.isEmpty(url) && requestMap !
=
null && requestMap.containsKey(
"category"
)) {
hashMap.put(
"X-PageKey"
,
"blog."
+
requestMap.get(
"category"
));
hashMap.put(
"X-Path"
,
"app.csdn.net/blog/"
+
requestMap.get(
"category"
));
}
if
(!StringUtils.isEmpty(url) && url.equals(s22.G0)) {
hashMap.put(
"X-PageKey"
, vr3.Q6);
hashMap.put(
"X-Path"
,
"app.csdn.net/blog/detail"
);
if
(requestMap !
=
null && requestMap.containsKey(
"from"
)) {
hashMap.put(
"X-Referer"
,
"blog."
+
requestMap.get(
"from"
));
}
}
hashMap.put(
"User-Agent"
, CSDNApp.csdnApp.userAgent
+
" CSDNApp/"
+
xn3.u()
+
"(Android)wToken/0.0.1"
);
try
{
hashMap.put(
"wToken"
, TigerTallyAPI.vmpSign(
1
, str3.getBytes(
"UTF-8"
)));
} catch (UnsupportedEncodingException e3) {
e3.printStackTrace();
}
return
hashMap;
}
|
pretty nice,很多参数都在这里,那就从上往下分析:
hashMap.put("platform", "android"); // 固定值
hashMap.put("version", xn3.u()); // 固定值
hashMap.put("c_appVersion", xn3.u()); // 固定值
hashMap.put("Authorization", StringUtils.isEmpty(it3.g()) ? "" : "Bearer " + it3.g()); // 无用,请求头中为空
hashMap.put("X-Device-ID", a2); // a2 在 String a2 = wo3.a(CSDNApp.csdnApp);
hook wo3.a看看
1
2
3
4
5
6
7
8
9
10
11
12
|
function main() {
Java.perform(function () {
var wo3
=
Java.use(
"wo3"
);
wo3[
"a"
].implementation
=
function (context) {
console.log(
'a is called'
+
', '
+
'context: '
+
context);
var ret
=
this.a(context);
console.log(
'a ret value is '
+
ret);
return
ret;
};
});
}
setImmediate(main)
|
结果:
a is called, context: net.csdn.csdnplus.CSDNApp@dc96acb
a ret value is aid0f0fef992b53479187546b3c621157f0
多次 hook 该值并没有改变,查看不同数据包的内容也是一样的,但在 Java 层仅分析到 aid 复制点,后面数据同一设备都是一样的,怀疑是消息散列值,有可能是 DeviceID 或者 UUID,有在 Java 层看到,但 hook 不到,往下分析:
hashMap.put("X-OS", "Android"); // 固定值
hashMap.put("X-App-ID", "CSDN-APP"); // 固定值
hashMap.put("X-Access-Token", MD5.md5(a2 + "AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656")); // a2 就是上面的 X-Device-ID 再进行加盐处理后进行 MD5 加密
复现一下:
1
2
3
4
5
6
7
8
9
10
11
|
from
hashlib
import
md5
def
encrypt_md5(mes):
new_md5
=
md5()
# 这里必须用encode()函数对字符串进行编码,不然会报 TypeError: Unicode-objects must be encoded before hashing
new_md5.update(mes.encode(encoding
=
'utf-8'
))
# 加密
return
new_md5.hexdigest()
if
__name__
=
=
'__main__'
:
print
(encrypt_md5(
'aid0f0fef992b53479187546b3c621157f0AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656'
))
|
结果 00871d5df0d4f51efb5883b3b2fd2359,校验无误,继续往下:
hashMap.put("X-OsVersion", Build.VERSION.SDK_INT + ""); // sdk 版本吧,可随机的样子
hashMap.put("X-DeviceModel", str2); // 通过上面获取来的,分析一下就是手机 + 手机名称
hashMap.put("X-ConnectionType", yp3.b(CSDNApp.csdnApp)); // 网络连接类型
hashMap.put("UserToken", StringUtils.isEmpty(it3.q()) ? "" : it3.q()); // 抓包为空值,放弃
hashMap.put("X-App-Theme", CSDNApp.isDayMode ? "day" : "night"); // 主题模式
hashMap.put("X-Sign", str);
str 是上面计算来的,拿来分析下
1
2
3
4
5
6
7
8
9
|
int
c2
=
xn3.c(
10000
,
99999
);
String str3
=
new Date().getTime()
+
"";
try
{
str
=
mq3.a(a2
+
c2
+
str3
+
zf1.o);
} catch (DigestException e2) {
e2.printStackTrace();
str
=
"";
}
hashMap.put(
"X-Sign"
,
str
);
|
c2: 10000 - 99999 之间的随机值;
str3:时间戳转字符串;
a2:上面分析过为 X-Device-ID 值;
zf1.o:跟进查看为定值:public static final String o = "F403F982CA92F73AC142D50FFA69853D";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public static String a(String decrypt) throws DigestException {
try
{
MessageDigest messageDigest
=
MessageDigest.getInstance(
"SHA-1"
);
messageDigest.update(decrypt.getBytes());
byte[] digest
=
messageDigest.digest();
StringBuffer stringBuffer
=
new StringBuffer();
for
(byte b : digest) {
String hexString
=
Integer.toHexString(b &
255
);
if
(hexString.length() <
2
) {
stringBuffer.append(
0
);
}
stringBuffer.append(hexString);
}
return
stringBuffer.toString().toUpperCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new DigestException(
"签名错误!"
);
}
}
|
SHA1算法,先 hook 再还原:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function main() {
Java.perform(function () {
var mq3
=
Java.use(
"mq3"
);
mq3[
"a"
].implementation
=
function (decrypt) {
console.log(
'a is called'
+
', '
+
'decrypt: \n'
+
decrypt);
var ret
=
this.a(decrypt);
console.log(
'a ret value is '
+
ret);
return
ret;
};
});
}
setImmediate(main)
/
/
frida
-
FU
-
l CSDN
/
csdn.js
|
结果:
a is called, decrypt:
aid0f0fef992b53479187546b3c621157f0709751671957807054F403F982CA92F73AC142D50FFA69853D
a ret value is E11539C9183644EEB69C7FEBAC1D58A2D874895C
还原:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
hashlib
# 使用sha1加密算法,返回str加密后的字符串
def
sha1_secret_str(s:
str
):
sha
=
hashlib.sha1(s.encode(
'utf-8'
))
encrypts
=
sha.hexdigest()
return
encrypts.upper()
if
__name__
=
=
'__main__'
:
# 待加密的字符串
s
=
'aid0f0fef992b53479187546b3c621157f0709751671957807054F403F982CA92F73AC142D50FFA69853D'
res
=
sha1_secret_str(s)
print
(res)
|
结果:E11539C9183644EEB69C7FEBAC1D58A2D874895C 校验无误,继续往下分析:
hashMap.put("X-RandomNum", c2 + ""); // 10000 - 99999 之间的随机值;
hashMap.put("X-TimeStamp", str3); // str3:时间戳转字符串;
hashMap.put(IWebview.COOKIE, sb.toString()); // 看抓包结果应该是 Cookie 值,对照结果 UserName=;UserToken= 啥操作没做,应该是要登录后才有值也是固定值
hashMap.put("User-Agent", CSDNApp.csdnApp.userAgent + " CSDNApp/" + xn3.u() + "(Android)wToken/0.0.1");
对照其抓包内容:CSDNApp.csdnApp.userAgent 获取设备 header,xn3.u() 获取 app 版本号
1
2
|
/
/
Mozilla
/
5.0
(Linux; Android
11
; M2012K11AC Build
/
RQ3A.
211001.001
; wv) AppleWebKit
/
537.36
(KHTML, like Gecko) Version
/
4.0
Chrome
/
108.0
.
5359.128
Mobile Safari
/
537.36
CSDNApp
/
5.0
.
0
(Android)wToken
/
0.0
.
1
hashMap.put(
"wToken"
, TigerTallyAPI.vmpSign(
1
, str3.getBytes(
"UTF-8"
)));
|
看到 wToken 就有点不好的预感,应该是阿里安全的,前段时间很火的某box就是用的这个,跟进看看,最终定位到:
1
|
private static native String _genericNt3(
int
i, byte[] bArr);
|
so 层了,放着先看看别的参数吧,这块代码,能解决的参数都解决了,但 X-Ca-Signature 没在这出现,jadx 再搜跟到以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private static
Map
<String, String> c(StringBuilder strBuilder,
Map
<String, String> headerParams) {
if
(ft3.b() !
=
1
) {
headerParams.put(
"X-Ca-Stage"
, ft3.b()
=
=
2
?
"TEST"
:
"PRE"
);
}
try
{
Mac mac
=
Mac.getInstance(
"HmacSHA256"
);
byte[] bytes
=
y12.c.getBytes(
"UTF-8"
);
mac.init(new SecretKeySpec(bytes,
0
, bytes.length,
"HmacSHA256"
));
String
str
=
new String(Base64.encodeBase64(mac.doFinal(strBuilder.toString().getBytes(
"UTF-8"
))));
headerParams.put(
"X-Ca-Signature"
,
str
);
no3.a(
"==HmacSHA256=="
,
str
);
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
} catch (InvalidKeyException e3) {
e3.printStackTrace();
} catch (NoSuchAlgorithmException e4) {
e4.printStackTrace();
}
return
headerParams;
}
|
不难看出该值是通过 HmacSHA256 加密后再进行 Base64 编码后得到的结果,其 key 值为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public static final String c
=
"0u94vkvsewic9kkgsp1r3nuq3ir0lv3n"
;
hook 看看要加密 strBuilder 有啥:
function main() {
Java.perform(function () {
var r12
=
Java.use(
"r12"
);
r12[
"c"
].implementation
=
function (strBuilder, headerParams) {
console.log(
'strBuilder: \n'
+
strBuilder);
var ret
=
this.c(strBuilder, headerParams);
var keyset
=
ret.keySet();
var result
=
"";
var it
=
keyset.iterator();
while
(it.hasNext()) {
var keystr
=
it.
next
().toString();
var valuestr
=
ret.get(keystr).toString();
console.log(keystr)
console.log(valuestr)
result
+
=
valuestr;
}
return
ret;
};
});
}
setImmediate(main)
/
/
frida
-
FU
-
l CSDN
/
csdn.js
|
结果:
strBuilder:
POST
application/json
application/json; charset=UTF-8
X-Ca-Key:203789067
X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5a
X-Ca-Timestamp:1671963564343
/v1/api/app/login/doLogin
其中 X-Ca-Key 是个定值:
headerParams.put("X-Ca-Key", y12.b);
public static final String b = "203789067";
X-Ca-Nonce 为 UUID 值:
headerParams.put("X-Ca-Nonce", UUID.randomUUID().toString());
X-Ca-Timestamp 为时间戳。
python还原算法,与抓包结果一直:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
from
hashlib
import
sha256
import
hmac, base64
def
get_sign(data, key):
key
=
key.encode(
'utf-8'
)
message
=
data.encode(
'utf-8'
)
sign
=
base64.b64encode(hmac.new(key, message, digestmod
=
sha256).digest()).decode()
print
(sign)
return
sign
if
__name__
=
=
'__main__'
:
# 待加密的字符串
s
=
"POST"
+
"\n"
+
\
"application/json"
+
"\n"
+
\
"\n"
+
\
"application/json; charset=UTF-8"
+
"\n"
+
\
"\n"
+
\
"X-Ca-Key:203789067"
+
"\n"
+
\
"X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5a"
+
"\n"
+
\
"X-Ca-Timestamp:1671963564343"
+
"\n"
+
\
"/v1/api/app/login/doLogin"
k
=
'0u94vkvsewic9kkgsp1r3nuq3ir0lv3n'
res
=
get_sign(s, k)
print
(res)
|
抓包结果:QJYeguZxkE+ZojwTP0rIJ+IzjaSHI82uR2y0xOIG35U=
到这几乎参数都解决了,剩个 so 层的 wtoken,在 Java 层能够定位到:com/aliyun/TigerTally/TigerTallyAPI,其中,要找的就是 libtiger_tally.so 了:
1
2
3
|
static {
System.loadLibrary(
"tiger_tally"
);
}
|
阿里安全。。。。,换思路做吧,不想折腾,想了想,我直接 rpc 调用不就好了。
frida rpc 脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
var response
=
null;
Java.enumerateClassLoaders({
onMatch: function (loader) {
try
{
if
(loader.findClass(
"com.aliyun.TigerTally.TigerTallyAPI"
)) {
Java.classFactory.loader
=
loader;
response
=
Java.use(
"com.aliyun.TigerTally.TigerTallyAPI"
)
}
else
{
}
} catch (error) {
}
}, onComplete: function () {
}
});
function stringToByte (
str
) {
var ch, st, re
=
[];
for
(var i
=
0
; i <
str
.length; i
+
+
) {
ch
=
str
.charCodeAt(i);
st
=
[];
do {
st.push( ch &
0xFF
);
ch
=
ch >>
8
;
}
while
( ch );
re
=
re.concat(st.reverse());
}
return
re;
}
function getwwoken(data){
var result
=
response._genericNt3(
1
, stringToByte(data));
return
result;
}
rpc.exports
=
{
getwtoken:getwwoken
}
|
补环境:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
import
time
import
hmac
import
uuid
import
random
import
base64
from
hashlib
import
sha256, md5, sha1
def
get_x_osversion():
return
"30"
def
get_x_os():
return
"android"
def
get_x_appid():
return
"CSDN_APP"
def
get_x_app_theme():
return
"day"
def
get_x_connection_type():
return
"WIFI"
def
get_x_timestramp():
return
str
(
int
(time.time()
*
1000
))
def
get_x_device_model():
return
"Redmi M2012K11AC"
def
get_x_ca_Signature_Headers():
return
"X-Ca-Timestamp,X-Ca-Key,X-Ca-Nonce"
def
get_User_Agent():
return
"Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1"
def
get_x_ca_nonce():
return
str
(uuid.uuid4())
def
get_x_device_id():
return
"aid0f0fef992b53479187546b3c621157f0"
def
get_access_token():
X_Access_Token
=
"aid0f0fef992b53479187546b3c621157f0AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656"
md5_mes
=
md5(X_Access_Token.encode())
return
md5_mes.hexdigest()
x_timestramp
=
get_x_timestramp()
x_ca_nonce
=
get_x_ca_nonce()
def
get_x_randomnum():
return
str
(random.randint(
10000
,
99999
))
def
get_x_ca_signature():
data
=
"POST"
+
"\n"
+
\
"application/json"
+
"\n"
+
\
"\n"
+
\
"application/json; charset=UTF-8"
+
"\n"
+
\
"\n"
+
\
"X-Ca-Key:203789067"
+
"\n"
+
\
"X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5a"
+
"\n"
+
\
"X-Ca-Timestamp:1671963564343"
+
"\n"
+
\
"/v1/api/app/login/doLogin"
key
=
"0u94vkvsewic9kkgsp1r3nuq3ir0lv3n"
.encode(
"utf-8"
)
message
=
data.encode(
"utf-8"
)
sign
=
base64.b64encode(hmac.new(key, message, digestmod
=
sha256).digest())
return
str
(sign,
'utf-8'
), x_timestramp, x_ca_nonce
def
get_xsign():
xsign_mes
=
get_x_device_id()
+
get_x_randomnum()
+
x_timestramp
+
"F403F982CA92F73AC142D50FFA69853D"
return
sha1(xsign_mes.encode(
"utf-8"
)).hexdigest().upper()
|
远程调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
import
frida
from
login_env
import
*
import
requests
def
on_message(message, data):
print
(
"[%s] => %s"
%
(message, data))
def
inject_hook():
session
=
frida.get_usb_device().attach(
'net.csdn.csdnplus'
)
with
open
(
'CSDN/rpc.js'
,
'r'
) as f:
js_code
=
f.read()
script
=
session.create_script(js_code)
script.on(
'message'
, on_message)
script.load()
return
script
def
message(message, data):
if
message[
"type"
]
=
=
'send'
:
print
(
"[*] {0}"
.
format
(message[
'payload'
]))
else
:
print
(message)
def
req():
url
=
"https://passport.csdn.net/v1/api/app/login/doLogin"
headers
=
{
"X-OsVersion"
:
"30"
,
"User-Agent"
:
"Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1"
,
"X-RandomNum"
: get_x_randomnum(),
"X-Access-Token"
: get_access_token(),
"platform"
:
"android"
,
"X-Ca-Signature-Headers"
:
"X-Ca-Timestamp,X-Ca-Key,X-Ca-Nonce"
,
"Authorization"
: "",
"X-OS"
:
"Android"
,
"c_appVersion"
:
"5.0.0"
,
"X-App-ID"
:
"CSDN-APP"
,
"X-App-Theme"
:
"day"
,
"content-type"
:
"application/json; charset=UTF-8"
,
"X-Ca-Signature"
: get_x_ca_signature()[
0
],
"X-ConnectionType"
:
"WIFI"
,
"UserToken"
: "",
"X-TimeStamp"
: get_x_ca_signature()[
1
],
"X-Ca-Key"
:
"203789067"
,
"Accept"
:
"application/json"
,
"X-Device-ID"
: get_x_device_id(),
"wToken"
: res,
"X-DeviceModel"
:
"Redmi M2012K11AC"
,
"version"
:
"5.0.0"
,
"X-Ca-Nonce"
: get_x_ca_signature()[
2
],
"X-Ca-Timestamp"
: get_x_ca_signature()[
1
],
"X-Sign"
: get_xsign(),
"Host"
:
"passport.csdn.net"
,
"Connection"
:
"Keep-Alive"
,
"Accept-Encoding"
:
"gzip"
,
}
data
=
{
"pwdOrVerifyCode"
:
"123456"
,
"loginType"
:
"1"
,
"userIdentification"
:
"17750659921"
,
"checkAli"
:
"true"
}
response
=
requests.post(url, headers
=
headers,json
=
data)
print
(response.text)
if
__name__
=
=
'__main__'
:
rpc_script
=
inject_hook()
res
=
rpc_script.exports.getwtoken(get_x_ca_signature()[
1
])
req()'''
|
结果,校验一致:
{"message":"用户名或密码错误","status":false,"code":"1039"}
更多【 安卓协议逆向 cxdx 分析与实现】相关视频教程:www.yxfzedu.com