O**O 游戏中心 APP 排行榜数据安卓逆向参数分析 sign、sg、oak
声明:本文只作学习研究,禁止用于非法用途,否则后果自负,敏感信息已做了加密隐藏,如有侵权,请告知删除,谢谢!
前言
目标是采集游戏排行榜中的游戏排行榜数据,需要准备一台安卓 root 后的后手机,配置完证书,准备好逆向工具。
抓包界面截图:
抓包内容截图:
目标请求:
import requests
url='https://api-cn.game.***.com/card/game/v1/rank/new?size=10&start=0'
headers={
"refresh_times": "0",
"CDO-GSLB": "1",
"rt": "0",
"page-id": "454",
"romver": "-1",
"User-Agent": "Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2F2201%2F130701",
"sign": "d607ed64c231bf6a8ac18a9e0c2c9a30",
"nw": "1",
"pid": "1000",
"enter-id": "1",
"snippetVersion": "5",
"locale": "zh-CN;CN",
"sg": "0902eb1bb12c1dbf7605bc083141da8f",
"cpuAbilist": "arm64-v8a,armeabi-v7a,armeabi",
"oak": "6486ed42c86ecc09",
"id":"2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7",
"rcm": "1",
"ocp":"stat#1_ABTEST#14_usage#3_ai#0_main#24_community#1_preload#1_network#0_desktopspace#3_search#2_download#1_h5preload#1_homepage#1",
"ocs": "Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701",
"Accept": "application/x2-protostuff; charset=UTF-8",
"ch": "2201",
"appversion": "13.7.1",
"token": "-1",
"pkg-ver": "-1",
"t": "1717377995077",
"t-request-id": "e1f888a20d7e9fd***7fed87face3f",
"appid": "Xiaomi#1000#CN",
"pull_refresh": "0",
"compressTool": "zstd-1.5.2-2",
"child": "NULL",
"Host": "api-cn.game.xxxxx.com",
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip"
}
res=requests.get(url,headers=headers)
print(res.text)
经过分析对 headers 中部分重要参数进行对应说明
参数 | 参数说明 | 抓包获取的值 |
sign | 签名1 | d607ed64c231bf6a8ac18a9e0c2c9a30 |
sg | 签名2 | 0902eb1bb12c1dbf7605bc083141da8f |
oak | 签名密钥key | 6486ed42c86ecc09 |
也就是说我们搞清楚 sign、sg、oak 的生成规则就能完成请求模拟
正文
下面我们开始对 apk,进行逆向用到那些工具也会介绍
jadx-gui: jadx-gui 是一种基于 jadx 项目的图形界面工具,用于反编译Android 应用程序的工具。通过使用jadx-gui,开发人员可以打开 APK(Android应用程序包)文件,并查看其反编译的源代码。
用 jadx-gui 打开 apk 查看加密生成位置
点击搜索,搜索关键字"sign" 找到相关代码 进行分析查看
搜索到相关代码,方法 addSign 并发现这里对 headers 进行了添加,可以看出 m20754c 就是 sign 是通过 OcsTool.m20754c 方法生成的。我们右击该方法跳到声明处看下。
函数跳转到 native 层,so 文件名称:libocstool.so
so文件是unix(一个系统的名字)的动态连接库,是二进制文件,作用相当于windows下的.dll文件
有兴趣的可以去了解下 so 文件的加载过程,本文不再赘述。
找到 libocstool.so 文件,使用 ida 打开,找到签名生成函数,可以先用 jadx 导出资源文件
IDA Pro是目前很棒的静态反编译软件,是反编译者不可缺少的利器.巨酷的反编译软件,它可以更好的反汇编和更有深层分析.可以快速到达指定代码位置.
这里主义 IDA 有 32 位和 64 位之分,对应能打开的文件也不一样,加载时会提示
这时候更好 64 位进行打开
在这里俺 ctrl+f 进行搜索 定位到 so 中的映射方法,点击_c 看下逻辑
点击后按 f5 切换视图
下面就是考验 C 语言基础的时候了
可以很明显看出 MD5 关键字,我们也可以在 sign 的格式中大概猜出是 md5
还记得 m20754c 传入了什么吗
String m20754c = OcsTool.m20754c(append.toString(), append.length());
一个字符串 和 字符串的长度
可以看出
v20 = _JNIEnv::GetMethodID(v26, v21, “update”, “([B)V”);
v19 = _JNIEnv::GetMethodID(v26, v21, “digest”, “()[B”);
v5 = _JNIEnv::NewStringUTF(v26, “MD5”);
v18 = _JNIEnv::CallStaticObjectMethod(v26, v21, v4, v5);
是 v4 代码 md5 这里可以看出是吧 md5 的加密方法赋值给了 v18,update 应该是用来添加加密参数的的也就是 v20
所以 _JNIEnv::CallVoidMethod(v26, v18, v20, v6); 例这种就是吧 v6 添加到 md5 的加密参数中那么 v6 是什么呢 v6 = _JNIEnv::NewByteArray(v26, 48); 是开辟了一个 48 位的内存地址创建指定长度的 byte 数组。然后把 k2 放了进去 可 k2 是什么呢
右击 k2 jump
有个 init_keys 和 init_keys2 函数,我们先看下 init_keys2
看得出 k k2 是由 v6=a1 生成的 a1 是传参 那我们右击 init_keys2 跳到 jump 转到调用处看看
往上跳上层后跳到了 init_keys
可以看出传入的参数是 v4 和 v3 而 这俩参数是判断应用包名得到的
那么我们的参数就是
v4 = “6486ed42c86ecc09”;
v3 = “a83c3e95c524ac6a3af81e3e12314dd295”;
接着我们回到 init_keys2 看下 k 和 k2 如何生成的
__int64 __fastcall init_keys2(char *a1, char *a2)
{
__int64 result; // x0
int j; // [xsp-2Ch] [xbp-2Ch]
signed int i; // [xsp-24h] [xbp-24h]
char *v5; // [xsp-20h] [xbp-20h]
char *v6; // [xsp-18h] [xbp-18h]
v6 = a1;
v5 = a2;
k = malloc(17LL);
result = malloc(49LL);
k2 = result;
for ( i = 0; i < 16; ++i )
{
*(_BYTE *)(k + i) = v6[i];
*(_BYTE *)(k2 + i) = *(_BYTE *)(k + i);
}
*(_BYTE *)(k + 16) = 0;
for ( j = 0; j < 16; ++j )
{
*(_BYTE *)(k2 + j + 16) = v5[j + 18];
*(_BYTE *)(k2 + j + 32) = v5[j + 2];
}
*(_BYTE *)(k2 + 48) = 0;
return result;
}
python 模拟还原一下分析一下看出 k 就是 v6
而 k2 就是 v5 v6 拼接的
key2='6486ed42c86ecc09'
key2=key2+'0'*(48-len(key2))
print(key2)
v="a83c3e95c524ac6a3af81e3e12314dd295"
key2=list(key2)
v=list(v)
for j in range(16):
# print(key2[16+j],v[j + 18])
key2[16+j]=v[j + 18]
key2[32+j]=v[j + 2]
print(''.join(key2))
# 6486ed42c86ecc0900000000000000000000000000000000
# 6486ed42c86ecc09f81e3e12314dd2953c3e95c524ac6a3a
好得到了 k2 我们回到 md5 加密的_c 中
目前知道 md5(k2)
这里添加了第二个参数是我们传过来的第一个字符串参数我们这里 a3
目前知道 md5(k2+a3)
这里看出 v24+48 而 v24 指向我们传过来的参数 a4 也就是 len(a3)
目前知道 md5(k2+a3+(len(a3)+48))
最后加载了一字符串常量
OBSCURE_CODE
双击跟进去能找到
那我们现在总结一下
sign=md5(k2+a3+(len(a3)+48)+OBSCURE_CODE)
oka=6486ed42c86ecc09=k
还差一个 sg
我们回到jadx看下sg 是传入到那个方法
可以看到sg 调用了m20750a这个方法进行了加密并且传入了一下参数和sign
/* renamed from: a */
public static String m20750a(Request request, String str, String str2, String str3) {
return m20755d((str + request.getRequestHeader().get("Accept") + m20749a(request.getMethod()) +
str2).toLowerCase(), str3);
}
/* renamed from: d */
public static native String m20755d(String str, String str2);
/* renamed from: a */
private static String m20749a(int i) {
return i != 1 ? i != 2 ? i != 4 ? "get" : TtmlNode.TAG_HEAD : "put" : "post";
}
可以看出是调用了m20755d这个方法并且传入了 几个参数 这个对应着_d我们回到ida看下
可以看出这里调用了md5对a3+k+a4+len(a3+k+a4) 进行了加密
后面又对这个加密结果的byte字节数据数组%10 然后再相加 最后去这个结果的个位=v24
然后用v24%5 取对应两个字符串数组的对应元素
并且判断v24的结果采用那种加密方式,一种是md5 另一种是v37对应的SHA1 加密参数是
a3+v21+v20+len(a3+v21+v20)
到这里我们总结一下sg获取的过程是竖线对传入的参数进行Md5加密后 然后获取加密结果的校验位 通过校验位获取校验数组中的字符串 再根据校验位现在不同的加密方法 既md5 sha1
到目前为止我们已经获取获取到了 需要的三个参数的加密方法和过程,下面我们要寻找加密这三个参数 传入了那些值,由于oak是固定值 我们这里只需要关心sign sg
这里我们去hook addSign
jadx 显示的包名是package okhttp3.internal.tls; 类名是ady 方法名是addSign 直接去hook定位不到
点击这里能发现混淆后的包名a.a.a.ady 这样就能定位到了
hook的方法众多frida xposed 等 这里不过多介绍
时间:2024-0
6-05 11:36:54
类名:a.a.a.ady
日志名称:已拦截-addSign(Request,String,long,String)
参数1
参数类型:com.nearme.network.proto.a
参数值:com.nearme.network.proto.a@23c2cfa
参数2
参数类型:java.lang.String
参数值:Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701
参数3
参数类型:java.lang.Long
参数值:1717558614167
参数4
参数类型:java.lang.String
参数值:2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7
返回结果类型:void
返回结果值:null
我们回顾下sign=md5(k2+a3+(len(a3)+48)+OBSCURE_CODE)
k2 OBSCURE_CODE 都是固定值 只要看a3就行
k2=6486ed42c86ecc09f81e3e12314dd2953c3e95c524ac6a3a
OBSCURE_CODE=STORENEWMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANYFY/UJGSzhIhpx6YM5KJ9yRHc7YeURxzb9tDvJvMfENHlnP3DtVkOIjERbpsSd76fjtZnMWY60TpGLGyrNkvhHAo9yURpPQoI0eg3SLFmTEI/MUiPRCwfwYf2deqKKlsmMSysYYHX9JiGzQuWiYZaawxprSuiqDGvAYEAtQ0QV00gGABISljNMy5aeDBBTSBWG2OjxJhxLRbndZM81OsMFysgC7dq+bUS6ke1YrDWgsoFhRxxTtx/2gDYciGp/c/h0Td5pGw7T9W6zo2xWI5oh1WyTnn0Xj17O9CmOk4fFDpJ6bapL+fyDy7gkEUChJ9+p66WSAlsfUhJ2TECQQD5sFWMGE2IiEuz4fIPaDrNST***/ZpZ7VzB2tcG7GyZRx5YORbZmX1jR7l3H4F98MgqCGs88w6FKnCpxDK3AkEA225CphAcfyiH0ShlZxEXBgIYt3V8nQuc/g2KJtiV6eeFkxmOMHbVTPGkARvt5VoPYEjwPTg43oqTDJVtlWagyQJBLno9aHNExvznyD4/pR4hec6qqLNgMyIYMfHCl6d3UodVvC1HO1/nMPl+4GvuRnxuoBtxj/PTe7AlUbYPMCQQDOkf4sVv58tqslO+I6JNyHy3F5RCELtuMUR6rG5x46FLqqwGQbO8ORq+m5IZHTV/Uhr4h6GXNwDpVW0gBAkAp/v3tPI1riz6UuG0I6uf5er26yl5evPyPrjrD299L4Qy/1EIunayC7JYcSGlR01+EDYYgwUkec+QgrRC/NstV
a3 是传入的append 既new StringBuilder(str).append(j).append(str2).append(str4).append(str3);
str=Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701
j=时间戳=1717558614167
str2=2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7
str4=/card/game/v1/rank/new
str3=size=10&start=0
len(a3)+48=281
python 模拟获取下
from spiderx import sx
def get_Sign(url):
k2='6486ed42c86ecc09f81e3e12314dd2953c3e95c524ac6a3a'
OBSCURE_CODE='STORENEWMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANYFY/UJGSzhIhpx6YM5KJ9yRHc7YeURxzb9tDvJvMfENHlnP3DtVkOIjERbpsSd76fjtZnMWY60TpGLGyrNkvuV40L15JQhHAo9yURpP***3SLFmTEI/MUiPRCwfwYf2deqKKlsmMSysYYHX9JiGzQuWiYZaawxprSuiqDGvAgMBAAECgYEAtQ0QV00gGABISljNMy5aeDBBTSBWG2OjxJhxLRbndZM81OsMFysgC7dq+bUS6ke1YrDWgsoFhRxxTtx/2gDYciGp/c/h0Td5pGw7T9W6zo2xWI5oh1WyTnn0Xj17O9CmOk4fFDpJ6ba***gkEUChJ9+p66WSAlsfUhJ2TECQQD5sFWMGE2IiEuz4fIPaDrNSTHeFQQr/ZpZ7VzB2tcG7GyZRx5YORbZmX1jR7l3H4F98MgqCGs88w6FKnCpxDK3AkEA225CphAcfyiH0ShlZxE***8nQuc/g2KJtiV6eeFkxmOMHbVTPGkARvt5VoPYEjwPTg43oqTDJVtlWagyQJBAOvEeJLno9aHNExvznyD4/pR4hec6qqLNgMyIYMfHCl6d3UodVvC1HO1/nMPl+4GvuRnxuoBtxj/PTe7AlUbYPMCQQDOkf4sVv58tqslO+I6JNyHy3F5RCELtuMUR6rG5x46FLqqwGQbO8ORq+m5IZHTV/Uhr4h6GXNwDQRh1EpVW0gBAkAp/v3tPI1riz6UuG0I6***l5evPyPrjrD299L4Qy/1EIunayC7JYcSGlR01+EDYYgwUkec+QgrRC/NstV'
str1='Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701'
j=sx.获取_URL_QUERY(url).split('&ts=')[-1]
str2='2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7'
str4=sx.获取_PATH(url)
str3=sx.获取_URL_QUERY(url).split('&ts=')[0]
a3=str1+j+str2+str4+str3
print(k2+a3+str(len(a3)+48)+OBSCURE_CODE)
return sx.加密_MD5(k2+a3+str(len(a3)+48)+OBSCURE_CODE)
url = "https://api-cn.game.***.com/card/game/v1/rank/new?size=10&start=0&ts=1717572906855"
print(get_Sign(url))
#e01d294a4e2a243b1024e14ad104241b
sg 先看传入了那几个参数
str5=url编码(str4+str3)
accept=‘application/x2-protostuff; charset=UTF-8’
getMethod=‘get’
str2=‘2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7’
j=时间戳=1717558614167
a3=str5+accept+getMethod+str2+j 后转小写
a4=Sign
k=‘6486ed42c86ecc09’
MD5(a3+k+a4+str(len(a3+k+a4)))
后面根据这个结果获取校验位
然后在获取校验数组中的字符串
然后再根据校验位选择加密算发
python 模拟
# 传入了两个参数一个是sign
def get_sg(url):
k='6486ed42c86ecc09'
str4=sx.获取_PATH(url)
str3=sx.获取_URL_QUERY(url).split('&ts=')[0]
j=sx.获取_URL_QUERY(url).split('&ts=')[-1]
str2='2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7'
str5=sx.url编码(str4+str3).replace('/','%2f')
# sx.urlencode
accept='application/x2-protostuff; charset=UTF-8'
getMethod='get'
a3=(str5+accept+getMethod+str2+j).lower()
a4=get_Sign(url)
# print(a3)
# 先对传入的a3,a4 md5加密获取校验位
m5=sx.加密_MD5(a3+k+a4+str(len(a3+k+a4)))
print(m5)
# sx.by
v23=0
# 将字符串编码为字节对象
for i in bytearray(m5.encode("utf-8")):
print(i)
v23=v23+(abs(i)%10)
v24=v23%10
print(v23,v24)
sgk=[ "cab2f5d9***4eea71",
"3e8d4f1c***a6e09",
"c5ca81b***91663db",
"517e950***d031cb",
"f87***121dba1cf23"][::-1]
sgsk=[ "d9275c219e852***b5e60cb5ceccd523b5",
"6bf7d491e5ab***931f91eb4c9a1640",
"0ca3e6b70c***c4cf53ead33d158e83",
"464c604***069a3e585d8bfe3b90",
"f1184b1998***d10aa5b8dd039ef8f"] [::-1]
v21=sgk[v24%5]
v20=sgsk[v24%5]
print(a3+v21+v20+str(len(a3+v21+v20)))
# print(v24)
if v24 >=5:
return sx.加密_SHA1( a3+v21+v20+str(len(a3+v21+v20)))
else:
return sx.加密_MD5( a3+v21+v20+str(len(a3+v21+v20)))
完整调用代码
import gzip
import time
import requests
url = "https://api-cn.game.***.com/card/game/v1/rank/new?size=10&start=0"
from spiderx import sx
def get_Sign(url):
k2='6486ed42c86ecc09f81e3e12314dd2953c3e95c524ac6a3a'
OBSCURE_CODE='STORENEWMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANYFY/UJGSzhIhpx6YM5KJ9yRHc7YeURxzb9tDvJvMfENHlnP3DtVkOIjERbpsSd76fjtZnMWY60***rNkvuV40L15JQhHAo9yURpPQoI0eg3SLFmTEI/MUiPRCwfwYf2deqKKlsmMSysYYHX9JiGzQuWiYZaawxprSuiqDGvAgMBAAECgYEAtQ0QV00gGABISljNMy5aeDBBTSBWG2OjxJhxLRbndZM***ysgC7dq+bUS6ke1YrDWgsoFhRxxTtx/2gDYciGp/c/h0Td5pGw7T9W6zo2xWI5oh1WyTnn0Xj17O9CmOk4fFDpJ6bapL***EA225CphAcfyiH0ShlZxEXBgIYt3V8nQuc***V6eeFkxmOMHbVTPGkARvt5VoPYEjwPTg43oqTDJVtlWagyQJBAOvEeJLno9aHNExvznyD4/pR4hec6qqLNgMyIYMfHCl6d3UodVvC1HO1/nMPl+4GvuRnxuoBtxj/PTe7AlUbYPMCQQDOkf4sVv58tqslO+I6JNyHy3F5RCELtuMUR6rG5x46FLqqwGQbO8ORq+m5IZHTV/U***h6GXNwDQRh1EpVW0gBAkAp/v3tPI1riz6UuG0I6uf5er26yl5evPyPrjrD299L4Qy/1EIunayC7JYcSGlR01+EDYYgwUkec+QgrRC/NstV'
str1='Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701'
j=sx.获取_URL_QUERY(url).split('&ts=')[-1]
str2='2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7'
str4=sx.获取_PATH(url)
str3=sx.获取_URL_QUERY(url).split('&ts=')[0]
a3=str1+j+str2+str4+str3
# print(k2+a3+str(len(a3)+48)+OBSCURE_CODE)
return sx.加密_MD5(k2+a3+str(len(a3)+48)+OBSCURE_CODE)
# 传入了两个参数一个是sign
def get_sg(url):
k='6486ed42c86ecc09'
str4=sx.获取_PATH(url)
str3=sx.获取_URL_QUERY(url).split('&ts=')[0]
j=sx.获取_URL_QUERY(url).split('&ts=')[-1]
str2='2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7'
str5=sx.url编码(str4+str3).replace('/','%2f')
# sx.urlencode
accept='application/x2-protostuff; charset=UTF-8'
getMethod='get'
a3=(str5+accept+getMethod+str2+j).lower()
a4=get_Sign(url)
# print(a3)
# 先对传入的a3,a4 md5加密获取校验位
m5=sx.加密_MD5(a3+k+a4+str(len(a3+k+a4)))
print(m5)
# sx.by
v23=0
# 将字符串编码为字节对象
for i in bytearray(m5.encode("utf-8")):
# print(i)
v23=v23+(abs(i)%10)
v24=v23%10
# print(v23,v24)
sgk=[ "cab2f***d94d4eea71",
"3e8d4f1c***aa6e09",
"c5ca81b03***663db",
"517e95007dd031cb",
"f8730121dba1cf23"][::-1]
sgsk=[ "d9275c219***52eb5e60cb5ceccd523b5",
"6bf7d491e5ab9da2931***eb4c9a1640",
"0ca3e6b70***0fc4cf53ead33d158e83",
"464c6045b59a3***69a3e585d8bfe3b90",
"f1184b1998cc***d10aa5b8dd039ef8f"] [::-1]
v21=sgk[v24%5]
v20=sgsk[v24%5]
# print(a3+v21+v20+str(len(a3+v21+v20)))
# print(v24)
if v24 >=5:
return sx.加密_SHA1( a3+v21+v20+str(len(a3+v21+v20)))
else:
return sx.加密_MD5( a3+v21+v20+str(len(a3+v21+v20)))
t=str(int(time.time()*1000))
# print(t)
# t='1717579661756'
# 1717581525911
headers={
"sign": get_Sign(url+'&ts='+t),
"sg":get_sg(url+'&ts='+t),
"refresh_times": "0",
"CDO-GSLB": "1",
"rt": "0",
"page-id": "454",
"romver": "-1",
"User-Agent": "Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2F2201%2F130701",
"nw": "1",
"pid": "1000",
"enter-id": "1",
"snippetVersion": "5",
"locale": "zh-CN;CN",
"cpuAbilist": "arm64-v8a,armeabi-v7a,armeabi",
"oak": "6486ed42c86ecc09",
"id": "2112#ea832cefcd7173c8a3fe8cd5b7b275cf#82374ccde246ea12a880ed874be5335f04189155b692e08ff418e6ca5e4f28f7",
"rcm": "1",
"ocp": "stat#1_ABTEST#14_usage#3_ai#0_main#24_community#1_preload#1_network#0_desktopspace#3_search#2_download#1_h5preload#1_homepage#1",
"ocs": "Xiaomi%2F2201123C%2F31%2F12%2FUNKNOWN%2F1000%2FSKQ1.211006.001+test-keys%2F130701",
"Accept": "application/x2-protostuff; charset=UTF-8",
"ch": "2201",
"appversion": "13.7.1",
"token": "-1",
"pkg-ver": "-1",
"t":t,
"t-request-id": "23cd4ab76e7b090***f957b0940636",
"appid": "Xiaomi#1000#CN",
"pull_refresh": "0",
"compressTool": "zstd-1.5.2-2",
"child": "NULL",
"Host": "api-cn.game.XXXX.com",
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip"
}
# print(headers)
response = requests.get(url, headers=headers)
response.encoding='utf-8_sig'
# print([response.text])
import re
games=re.findall('RankResourceDto.*?\x1a.(.*?)\x08\(\x000\x00:',response.text)
for game in games:
print('--------')
print(game)
结束~~~ ablbld~~~