news 2026/4/23 11:07:13

新版喜马拉雅Ollvm混淆Signature参数解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
新版喜马拉雅Ollvm混淆Signature参数解析

案例为最新版某马拉雅,可在豌豆夹下载

抓包

发送验证码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

POST /mobile/sms/v3/send HTTP/2

host: passport.ximalaya.com

cookie: 1&_device=android&d13a02e8-8efe-3427-80d8-e9347afe3e63&9.4.21;channel=and-f5;impl=com.ximalaya.ting.android;osversion=29;fp=009527657x2222q22264v0500700000000000000000000000000000000000;device_model=Pixel+2+XL;XIM=;c-oper=%E6%9C%AA%E7%9F%A5;net-mode=WIFI;res=1440%2C2712;AID=YTBiNTZmNjE1NTc2ODcyYQ==;manufacturer=Google;XD=SwmCBcM0DUJdkboCzp7x4FOk8Sp6aAtdSin4EsgNbx7+LoTgvWvpnD0fJ9tPskX9e1UXnLxL3Bn06ANSvQ+LCerM3eC5cDACyylaE7O3AW2dCDBfUBXa7UlnA6pbyIEe;xm_grade=0;specialModeStatus=0;

cookie2: $version=1

accept: */*

user-agent: ting_9.4.21(Pixel+2+XL,Android29)

x-tk: TACaS_-ndE6AuiO_jQngNjpNHr-PmPYLLD6cS5y7RNafhjt4EGQcET4NNoJs_RgxpBcO8_6aq6Dos-dtDmhvp9dYDhJKt9jb20ueGltYWxheWEudGluZy5hbmRyb2lkITEuMy4yNyE5LjQuMjEuMyFiPXBhc3Nwb3J0JnM9bG9naW4mdT0w

http_dns_address: old,d_s=false;d_g=true;d_f=true;d_i=false;p=false;h=false

content-type: application/json; charset=utf-8

content-length: 1165

accept-encoding: gzip

{"fdsOtp":"{}",

"biz":"1",

"signature":"e4cf26b5e716127762507811a4c747cf8e127a6f",

"mobile":"",

"sendType":"1",

"nonce":"0-224742D9E414bf681cef6aa5dfb1440934eba4d3a13a82532c3cbca33a3d8a"}

我们主要分析signature参数,signature长度为40,大概率为SHA1

逆向分析

发送验证码参数signature

首先搜索请求体字段中的fdsOtp定位关键代码

总共有三个,分别对应不同的登录形式,我们只关注验证码登录即可

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

privatevoidb(String str2) {

HashMap map =newHashMap();

if(AnonymousClass11.this.f72593c !=null) {

if(AnonymousClass11.this.f72593c.containsKey("mobile")) {

map.put("mobile", (String) AnonymousClass11.this.f72593c.get("mobile"));

}

map.put("sendType", (String) AnonymousClass11.this.f72593c.get("sendType"));

}

map.put("nonce", str);

if(!TextUtils.isEmpty(str2)) {

map.put("fdsOtp", str2);

}

map.put(com.alipay.sdk.app.statistic.c.f5786b, AnonymousClass11.this.f72592b +"");

map.put("signature", LoginRequest.b(AnonymousClass11.this.f72594d, map));

LoginRequest.f72585b = System.currentTimeMillis();

LoginRequest.a(AnonymousClass11.this.f72594d, k.a().j(), map, AnonymousClass11.this.f72591a,newcom.ximalaya.ting.android.loginservice.b.a<BaseResponse>() {// from class: com.ximalaya.ting.android.loginservice.LoginRequest.11.1.2

@Override// com.ximalaya.ting.android.loginservice.b.a

/* renamed from: a, reason: merged with bridge method [inline-methods] */

publicBaseResponse b(String str3)throwsException {

return(BaseResponse)newGson().fromJson(str3, BaseResponse.class);

}

});

}

可以发现signature参数的生成与代码

1

map.put("signature", LoginRequest.b(AnonymousClass11.this.f72594d, map));

有关,追踪,最终定位到

最终定位到此处代码,发现需要分析so层实现内容(login_encrypt),为了更清楚的分析,我们需要先了解进入so层前传入的参数是什么形式,

打印传入的参数,内容为:

1

2

3

4

5

z = false

str = biz=1&fdsOtp={"captcha_id":"3723312ce42a04b5c0b40e605a882037","lot_number":"b48afede55594f09ba5c82b9593b7402","pass_token":"a6d1832f7fe4a37776e5b5d610b2c45f42dd2d00007f061f3c4e20613a67f22a","gen_time":"1764764163","captcha_output":"2Z76G2CapbcJxb3z0NRv6M3hvdvpPpJiZYrOHqnYCvDSbFN1VW0MwSEZ3bzVLqngdIUnBFLqkqeiuyHwBeNxxkik34W9dQ5VNZm9JK-HSYpcxrp0NAOilcOY2Hvd1fNbL1gaiSbmgIg2vkSkBKcNidZdAs6JYmiWSCWjxwaE_iQXvm1gZABlsGsilYp-owYg05gxV5FZ70aYkw5cjkllOPITxWc_B7js3HAoApNEamZuLa0mKyHoTKcpRf41IXVgauvjOHYhM2nXeiif08NADj8Ho4NaELWsS2qZD01zZNtT0AWOZuE_z85Kgy3XHDHKm6hNryiY_0XtMaVPUWHalIbmumT1UetSWnZmhOnaxiQfob3m4-9gSby6csz3TM_EgSoRlWbM_cA7aDcQ8uapUlDXi3caucce-a7rHF31LnJOdVcWw-0OS13zo-xh-cD0qkilsQ3wPKe94ESLrSFxR2W8Avfuin5zYpWW49U6cllffSicGk4B7fKO0mkVZMrHl9E5KxX0n4zG4-cED9B4kasrOrbirl8rWEQjFgVwUog="}&mobile=epMimImhTRIy8xX0F3mQa5ccuLd7UtpUEwpkLKp6KYE87t/GhiVYaGzhkFvctWeBhYP8xqpKEzwo

co/J+Zl6fOlaSRCa/3VGkQswp+W0eaZw9JXTSpFTj7yX6sB17qgQIecCwT4z1WpcK85lwyY6iSvE

8Ml8sVmq/VHvc6FI7fQ=

&nonce=0-3E044F385FFB3fa71dad20ad2190576fdf24e4d639e8b3a3b76fbbc3ba03ec&sendType=1&

发现so层代码将近2500行,存在Ollvm混淆

我们从头开始分析代码

修正函数头之后,先分析前几行代码

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

69

70

71

72

73

74

75

76

77

78

79

80

81

82

int*__fastcall sub_10F8(inta1,inta2)

{

inti;// r0

intv4;// r4

intv5;// r9

unsignedintv6;// r0

intv7;// r2

boolv8;// zf

intv9;// r2

int*v12;// [sp+4h] [bp-34h]

boolv13;// [sp+12h] [bp-26h]

boolv14;// [sp+13h] [bp-25h]

intv15;// [sp+14h] [bp-24h]

boolv16;// [sp+1Bh] [bp-1Dh]

v13 = (((x_149 * (x_149 - 1)) ^ 0xFFFFFFFE) & (x_149 * (x_149 - 1))) == 0;

v14 = y_150 < 10;

v12 = &y_150;

for( i = 642638909; ; i = 1890200666 )

{

LABEL_14:

while( i <= 642638908 )

{

i = 1448165231;

if( v16 )

i = -1518418466;

if( i <= -64863450 )

{

while( 1 )

{

LABEL_3:

while( i == -2015175878 )

{

v4 = (*(int(__fastcall **)(int,void*))(*(_DWORD *)a1 + 24))(a1, &unk_1B010);

(*(void(__fastcall **)(int,int,char*,char*))(*(_DWORD *)a1 + 132))(a1, v4, &byte_1B02F, &byte_1B040);

(*(void(__fastcall **)(int,int))(*(_DWORD *)a1 + 92))(a1, v4);

i = -957104787;

}

if( i != -957104787 )

break;

v5 = (*(int(__fastcall **)(int,void*))(*(_DWORD *)a1 + 24))(a1, &unk_1B010);

v15 = (*(int(__fastcall **)(int,int,char*,char*))(*(_DWORD *)a1 + 132))(

a1,

v5,

&byte_1B02F,

&byte_1B040);

v16 = v15 == 0;

(*(void(__fastcall **)(int,int))(*(_DWORD *)a1 + 92))(a1, v5);

v6 = (~(x_149 * (x_149 - 1)) | 0xFFFFFFFE) + 1;

v7 = -2015175878;

if( y_150 < 10 != (v6 == 0) )

v7 = -64863449;

v8 = v6 == 0;

i = v7;

if( v8 )

i = -64863449;

if( y_150 >= 10 )

i = v7;

if( i > -64863450 )

gotoLABEL_14;

}

i = 1890200666;

v12 = (int*)&unk_19B64;

}

}

if( i == 642638909 )

{

v9 = -2015175878;

if( (v13 ^ v14) << 31 )

v9 = -957104787;

i = v9;

if( v14 )

i = -957104787;

if( !v13 )

i = v9;

gotoLABEL_3;

}

if( i != 1448165231 )

break;

v12 = (int*)(*(int(__fastcall **)(int,int,int))(*(_DWORD *)a1 + 136))(a1, a2, v15);

}

returnv12;

}

可以看到存在一定程度的混淆,去除控制流垃圾

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// case i == -2015175878:

v4 = (*(int(__fastcall **)(int,void*))(*(_DWORD *)a1 + 24))(a1, &unk_1B010);

(*(void(__fastcall **)(int,int,char*,char*))(*(_DWORD *)a1 + 132))(a1, v4, &byte_1B02F, &byte_1B040);

(*(void(__fastcall **)(int,int))(*(_DWORD *)a1 + 92))(a1, v4);

i = -957104787;

// case i == -957104787:

v5 = (*(int(__fastcall **)(int,void*))(*(_DWORD *)a1 + 24))(a1, &unk_1B010);

v15 = (*(int(__fastcall **)(int,int,char*,char*))(*(_DWORD *)a1 + 132))(

a1,

v5,

&byte_1B02F,

&byte_1B040);

v16 = v15 == 0;

(*(void(__fastcall **)(int,int))(*(_DWORD *)a1 + 92))(a1, v5);

按照JNI模式解析,大概率为

1

2

3

4

jclass clazz = (*env)->FindClass(env,"xxx");// &unk_1B010

jmethodID mid = (*env)->GetMethodID(env, clazz,"name","sig");// &byte_1B02F, &byte_1B040

(*env)->DeleteLocalRef(env, clazz);

v16 = (mid == 0);

查看一下对应的内存地址,是否为类名

可以看到字符串被混淆了,根据交叉引用寻找

发现存在解密代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# asc_1B010 原始密文字节

ida_chars = [

0xFC, 0xF3, 0xF9, 0xEF, 0xF2, 0xF4, 0xF9, 0xB2, 0xFE, 0xF2,

0xF3, 0xE9, 0xF8, 0xF3, 0xE9, 0xB2, 0xDE, 0xF2, 0xF3, 0xE9,

0xF8, 0xE5, 0xE9, 0xCA, 0xEF, 0xFC, 0xED, 0xED, 0xF8, 0xEF,

0x9D,

]

def decode(data):

out = []

forb in data:

# 按 C 里的写法: dst = ~( (b & 0x9D) | (~b & 0x62) );

# 再按 unsignedchar截断到 8 位

v = ~((b & 0x9D) | (~b & 0x62)) & 0xFF

out.append(v)

returnbytes(out)

plain = decode(ida_chars)

print("hex :", plain.hex())

try:

print("ascii:", plain.decode("ascii"))

except UnicodeDecodeError:

print("ascii decode failed")

#android/content/ContextWrapper

其他解密也是相同的,这样我们就知道了这个函数其实就是获取包名,脚本写为Idapython脚本更方便

发现都是进行比较,我们解密另一个参数即可,还是按照刚才的方法

1

2

3

4

5

6

7

8

byte_1B310-byte_1B32A 为

com.ximalaya.android.sleep

aJfdQDhehphfzYh 为

com.ximalayaos.pad[00]

byte_1BA00

com.ximalaya.huibenguan.android[00]

byte_1B330

com.ximalaya.android.sleep.dev\x00

可以看到所有的strcmp就是和硬编码的包名比较,所以我们需要找到对应的包名

最终是在一千一百多行发现

发现比较成功之后,会设置v13=1825021717,这个v13就是状态机,觉得下一步会执行什么代码,因此我们追踪if(v13==1825021717)的代码即可

这两个地址解密的数据为:

1

2

byte_1B510 解密后为;MOBIL-V1-PRODUCT-1

aD7dgkjj1K1g5Gk 解密后为:7D74899B338B4F348E2383970CC09991E8E8D8F2BC744EF0BEE94D76D718C0894

可以发现设置v13的状态为2590219376,继续跟进发现没有搜到,这时候可以切换为十六进制形式0x9A639C70发现找到了对应代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

elseif( v13 <= -1520500360 )

{

if( v13 == 0x9A639C70 )// = -1704747920

{

v261 = v228;// 保存 key 字符串

v262 = v230;// 保存标志位

v260 = v5;// 保存 "MOBIL-V1-PRODUCT-1" 之类

v239 = (char*)(*v231)->GetStringUTFChars(v231, str, 0);// jstring str -> char*

v13 = 923489355;

v14 = v15;

if( !v230 )

v13 = 816144671;// v230==0 时,状态改成 816144671

}

}

所以我们继续跟进新的状态

1

2

3

4

5

6

7

8

9

10

11

12

13

if( v13 == 816144671 )// 这里

{

v13 = 3581685779;

if( (~(x_153 * (x_153 - 1)) | 0xFFFFFFFE) == 0xFFFFFFFF )

v13 = 909332025;

v97 = 0;

if( y_154 < 10 )

v97 = 1;

else

v13 = 3581685779;

if( v97 != ((~(x_153 * (x_153 - 1)) | 0xFFFFFFFE) == -1) )

v13 = 909332025;

}

寻找有没有等于3581685779和909332025的

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

elseif( v13 == 909332025 )

{

v53 =strlen(v260);// 这个值为MOBIL-V1-PRODUCT-1

v54 = (char*)malloc(v53);

qmemcpy(v54, v260,strlen(v260) - 1);

v54[-(1 -strlen(v260))] = 0;// 复制的时候去除最后一位

v55 =strlen(v261);// 这个值为7D74899B338B4F348E2383970CC09991E8E8D8F2BC744EF0BEE94D76D718C0894

v56 = (char*)malloc(v55);

qmemcpy(v56, v261,strlen(v261) - 1);// 复制的时候去除最后一位

v56[strlen(v261) - 1] = 0;

v57 =strlen(c_str) - 123099768;

v58 =strlen(v54);

v59 =strlen(v56) + v58 + v57 + 123099769;// v59等于三段字符串总长度加\0

v60 =malloc(v59);

memset(v60, 0, v59);

strcat((char*)v60, c_str);// 拼接待签名原始数据

strcat((char*)v60, v54);// 拼接版本标识

strcat((char*)v60, v56);// 拼接key字符串

v240 = (int)(*v231)->NewStringUTF(v231, (constchar*)v60);

free(v54);

v61 = v56;

v12 = 1215952980;

free(v61);

free(v60);

v13 = -713281517;

if( (~(x_153 * (x_153 - 1)) | 0xFFFFFFFE) == 0xFFFFFFFF )

v13 = -1769657914;

v62 = 0;

if( y_154 < 10 )

v62 = 1;

else

v13 = -713281517;

v14 = v15;

if( v62 != ((~(x_153 * (x_153 - 1)) | 0xFFFFFFFE) == -1) )

v13 = -1769657914;

}

所以我们现在需要追踪v240

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

elseif( v13 > -1771541319 )

{

if( v13 != -1771541318 )

{

v45 = v240;

LABEL_360:

v13 = 493313113;

v223 = (char*)v45;

v14 = v15;

continue;

}

v208 = v231;

(*v231)->DeleteLocalRef(v231, (jobject)v254);

(*v208)->DeleteLocalRef(v208, (jobject)v242);

v257 = (int)(*v208)->CallObjectMethod(v208, (jobject)v246, (jmethodID)v245);

v209 = ((int(__fastcall *)(JNIEnv *))(*v208)->ExceptionCheck)(v208);

v13 = -1805937577;

v21 = v209 == 0;

v14 = v15;

if( !v21 )

v13 = 1741960892;

}

状态转移:v240 存进 v223,状态 v13 = 493313113

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

if( v13 == 493313113 )

{

v263 = v223;// ① 保存前面构造好的 jstring 指针

v189 = (~(x_153 * (x_153 - 1)) | 0xFFFFFFFE) + 1;

v190 = -1326811784;

if( y_154 < 10 != (v189 == 0) )

v190 = -925493942;

v21 = v189 == 0;

v13 = v190;

v14 = v15;

if( v21 )

v13 = -925493942;

if( y_154 >= 10 )

v13 = v190;

}

这两个新状态都可以找到,一个是加密后检查,一个是加密,我贴上加密的

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

elseif( v13 == -1326811784 )

{

v226 = v14;

v69 = v231;

v70 = (int)(*v231)->FindClass(v231, &byte_1BCA0);

v71 = (int)(*v69)->GetMethodID(v69, (jclass)v70, &byte_1BCB1, &byte_1B040);

v72 = (int)(*v69)->CallObjectMethod(v69, v263, (jmethodID)v71);

v73 = (int)(*v69)->GetMethodID(v69, (jclass)v70, &byte_1B29F, &byte_1B2B0);

CallObjectMethod = (*v231)->CallObjectMethod;

v75 = (int)(*v69)->NewStringUTF(v69, &byte_1BCBD);

CallObjectMethod(v231, (jobject)v72, (jmethodID)v73, v75);

v76 = (int)(*v69)->FindClass(v69, &byte_1BCD0);

v77 = (int)(*v69)->GetMethodID(v69, (jclass)v76, &byte_1B126, &byte_1B27E);

(*v69)->GetMethodID(v69, (jclass)v76, aJ, byte_1BCF0);

(*v69)->GetMethodID(v69, (jclass)v76, &byte_1BD1E, &byte_1B040);

(*v69)->NewObject(v69, (jclass)v76, (jmethodID)v77);

v12 = 1215952980;

(*v69)->GetMethodID(v69, (jclass)v76, aJ, &byte_1BD30);

v78 = (int)(*v69)->FindClass(v69, &byte_1BD50);

v79 = (int)(*v69)->GetStaticMethodID(v69, (jclass)v78, &byte_1B079, byte_1BD70);

v80 = (int)(*v69)->NewStringUTF(v69, &byte_1BDA2);

(*v69)->CallStaticObjectMethod(v69, (jclass)v78, (jmethodID)v79, v80);

(*v69)->ExceptionCheck(v69);

v13 = -925493942;

v14 = v226;

}

全部解密

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

elseif( v13 == -1326811784 )

{

v226 = v14;

v69 = v231;

v70 = (int)(*v231)->FindClass(v231, &byte_1BCA0);// java/lang/String

v71 = (int)(*v69)->GetMethodID(v69, (jclass)v70, &toUpperCase, &byte_1B040);// ()Ljava/lang/String;

v72 = (int)(*v69)->CallObjectMethod(v69, v263, (jmethodID)v71);

v73 = (int)(*v69)->GetMethodID(v69, (jclass)v70, &getBytes, &byte_1B2B0);// (Ljava/lang/String;)[B

CallObjectMethod = (*v231)->CallObjectMethod;

v75 = (int)(*v69)->NewStringUTF(v69, &byte_1BCBD);// utf-8

CallObjectMethod(v231, (jobject)v72, (jmethodID)v73, v75);

v76 = (int)(*v69)->FindClass(v69, &byte_1BCD0);// java/lang/StringBuilder

v77 = (int)(*v69)->GetMethodID(v69, (jclass)v76, &byte_1B126, &byte_1B27E);// 第三个参数为:<init>\x00([B)V\x00generatePublic\x00 第四个参数()V\x00write\x00toByteArrayÿ([B\x00close\x00getBytes\x00

(*v69)->GetMethodID(v69, (jclass)v76, append, byte_1BCF0);// (Ljava/lang/String;)Ljava/lang/StringBuilder;

(*v69)->GetMethodID(v69, (jclass)v76, &toString, &byte_1B040);// ()Ljava/lang/String;RSA

(*v69)->NewObject(v69, (jclass)v76, (jmethodID)v77);

v12 = 1215952980;

(*v69)->GetMethodID(v69, (jclass)v76, append, &byte_1BD30);// (I)Ljava/lang/StringBuilder;

v78 = (int)(*v69)->FindClass(v69, &byte_1BD50);// java/security/MessageDigest

v79 = (int)(*v69)->GetStaticMethodID(v69, (jclass)v78, &getInstance, byte_1BD70);// (Ljava/lang/String;)Ljava/security/MessageDigest;

v80 = (int)(*v69)->NewStringUTF(v69, &byte_1BDA2);// SHA-1updatedigest

(*v69)->CallStaticObjectMethod(v69, (jclass)v78, (jmethodID)v79, v80);

(*v69)->ExceptionCheck(v69);

v13 = -925493942;

v14 = v226;

}

可以看到进行了SHA1,现在我们需要搞清楚的就是

喂给 update 的 byte[] 是谁,digest 出来的 byte[] 是如何变成最终 sign

所以这时候重新考虑Hook

上面我们已经知道调用了java层的这么多方法,因此可以每个方法都试试,我这里选择的是hook toUpperCase

下面是输出

1

2

3

4

5

6

========== [toUpperCase] ==========

输入: biz=1&fdsOtp={"captcha_id":"3723312ce42a04b5c0b40e605a882037","lot_number":"43d0fb9d6ceb4d34b77f6998203fb7c3","pass_token":"cd28f0a8e166dd870f589c36bc43986fde88ceef418c92b6b3e8dfa1097ce027","gen_time":"1764831091","captcha_output":"2Z76G2CapbcJxb3z0NRv6M3hvdvpPpJiZYrOHqnYCvDSbFN1VW0MwSEZ3bzVLqngN4RJMRn1V6Uvj9gAHrgeznYrystLCzuDzpheGrXmtoInaTm_JIaayivXrDqJd1xrqxIqbMWmFj8RSFvxBFc2R1M8Ape_b6WdHTrf1BeQtjEN_sdWrJTbi48cbT6ayPbqPDU8vDchMd1tgXZDBKZhoFm3ANOcDQs_SP2GqsZANRo3sZR_X2sZQhGD2EgaJvrnlfLOTcZ8kDIPGOSQyoSEyNF6R1NuWtETfRTicTxTsj8b55gDWy72e16ItCupfEoQDye8zYIaHQ1UIg4TnXxFK1aTtqGFi551e-zcyIuQnTHqMAdNtIrac0khlYn8tfPFmpkkhJCa69hR-gcGFI_qvHCeFa4ab0xjeGbRNVosEfhxp3yBbv8tbPbZ-ObfR0LN3qYS8y1JPmB3EvamKHSmU7h76fVjRfZEyM-8UhIyzz5VJit0xT970VxEGgEqJ_ZE-7FBeXmrmFycDqjAN32aZYLKfE6y9WDHtwgu2D9vbbY="}&mobile=H+FK2BFDCnb7eyJ+5Y6MZ3Du/2lwuHI3wK9RnyE+g4VKStBxb/EyvBP4mudzGTeKKZFD1PZoJarJ

OoK9xq9LPSaQ+tialKCMq++5PmJLiiEkU6kqVdtqQVs0w9BKiakZKh+HH60bCpDVGTqFbhn4i/Sf

4W+bADoG3LzJGco9Vy4=

&nonce=0-4EE56BEBDE87cdb8b25529f4c7b2f9c8158d18e3ef90b13cff9725b5d652c4&sendType=1&MOBILE-V1-PRODUCT-7D74899B338B4F348E2383970CC09991E8E8D8F2BC744EF0BEE94D76D718C089

====================================

此时Signature参数的生成也很清晰了

1

2

输入 = 参数按字母排序拼接 +"MOBILE-V1-PRODUCT-"+"7D74899B338B4F348E2383970CC09991E8E8D8F2BC744EF0BEE94D76D718C089"

signature = SHA1(输入.toUpperCase().getBytes("UTF-8"))

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 14:36:17

基于强化学习的AI工具使用优化方法解析

基于强化学习的AI工具使用优化方法解析 【免费下载链接】tinker-cookbook Post-training with Tinker 项目地址: https://gitcode.com/GitHub_Trending/ti/tinker-cookbook 在人工智能技术快速发展的今天&#xff0c;大型语言模型如何有效利用外部工具来完成复杂任务已成…

作者头像 李华
网站建设 2026/4/16 21:11:59

Wan2.2 Fun-VACE视频生成技术完整指南:从入门到精通

Wan2.2 Fun-VACE视频生成技术完整指南&#xff1a;从入门到精通 【免费下载链接】WanVideo_comfy_fp8_scaled 项目地址: https://ai.gitcode.com/hf_mirrors/Kijai/WanVideo_comfy_fp8_scaled 视频创作领域迎来革命性突破&#xff01;Wan2.2 Fun-VACE模型作为阿里巴巴P…

作者头像 李华
网站建设 2026/4/22 17:33:20

Hilo跨浏览器游戏开发完整指南:解决兼容性痛点的终极方案

Hilo跨浏览器游戏开发完整指南&#xff1a;解决兼容性痛点的终极方案 【免费下载链接】Hilo A Cross-end HTML5 Game development solution developed by Alibaba Group 项目地址: https://gitcode.com/gh_mirrors/hi/Hilo 你是否曾经为HTML5游戏在不同浏览器中的表现差…

作者头像 李华
网站建设 2026/4/17 9:05:35

30、Red Hat系统安全配置与故障排除指南

Red Hat系统安全配置与故障排除指南 1. 自我测试相关知识 在Red Hat系统中,有许多关于系统安全和服务配置的重要知识点,通过以下自我测试问题可以帮助我们更好地理解这些内容。 1.1 使用tcp_wrappers保护服务 问题1 :如果在 /etc/hosts.allow 中允许某个服务,而在 …

作者头像 李华
网站建设 2026/4/18 18:54:04

还在为文件管理烦恼?oil.nvim让文件操作像编辑文本一样简单

还在为文件管理烦恼&#xff1f;oil.nvim让文件操作像编辑文本一样简单 【免费下载链接】oil.nvim Neovim file explorer: edit your filesystem like a buffer 项目地址: https://gitcode.com/gh_mirrors/oi/oil.nvim 你是不是经常在Neovim中打开多个文件标签页&#x…

作者头像 李华
网站建设 2026/4/17 8:29:02

3天速成Vue留言板开发:从零构建完整单页应用

3天速成Vue留言板开发&#xff1a;从零构建完整单页应用 【免费下载链接】vue-demo Vue.js 示例项目 简易留言板。本项目拥有完善的文档说明与注释&#xff0c;让您快速上手 Vue.js 开发 SPA。Webpack / ES6 Babel / Vue Router / (Vue Resource?) / (Vue Validator?) / (V…

作者头像 李华