某短视频(dy)创作者平台发布视频JS逆向学习(1)

【本文仅供学习,请勿用于非法用途,若非法使用概不负责】

前话

某音创作者平台视频发布大致上可分为三个部分:

  1. 视频上传资源申请。
  2. 视频上传。
  3. 视频发布表单提交。

本章节主要讲解视频上传资源申请相关接口,该部分主要向某音申请视频发布的存储地址以及视频VID等信息。

正文

经过debug发现(不会debug的评论区留言),视频上传资源申请主要为 https://vod.bytedanceapi.com/接口,且Action参数等于ApplyUploadInner,接口相关参数如下图所示
在这里插入图片描述
经过测试,发现主要校验且会变化的参数有 url中的参数 s, headers中的参数 AuthorizationX-Amz-DateX-Amz-Security-Token 共4个参数,下面我们一一分析。

通过搜索"ApplyUploadInner"和debug发现,参数加密的js文件是vender.c1933f70.js这个文件,具体核心代码如下:
在这里插入图片描述

可以看到Action、Version、SpaceName、FileType、IsInner 参数均是固定的,然后接着往下debug
在这里插入图片描述
当执行到t.addAuthorization方法之前,此时o对象的params参数已经设置完成(因为t.addAuthorization方法后跟了一个n.send(o)方法,从名字上可以看出后续就是发送请求操作了,具体细节可以自行去debug),而 o 对象的params又是从参数 i 中获得,接下来我们分析参数 i
在这里插入图片描述
通过debug发现到了该行时,i 对象参数仍然为几个固定值,之后仅跟着
i.user_id = this.config.userId), i.s = Math.random().toString(36).substr(2)
两个参数的赋值操作,user_id 的获取方式我们这里先不考虑,s 参数就是刚刚说到的其中一个变化值,该函数意为随机生成一个大于0小于1的浮点数,然后将该浮点数转为36进制数,再去掉小数前置的"0.“两个字符,最终分析下来其实就是一个随机生成11位由0-9a-z组成的一个字符串方法。这样我们就知道了第一个变化参数 s,接下来继续往后分析
在这里插入图片描述
在这里插入图片描述
由上面两张图可以看出,t.addAuthorization 方法为 o 对象填充 headers 属性,而 t.addAuthorization 函数需要传入"accessKeyId”,“*secretAccessKey”,“sessionToken” 参数,接来下我们继续debug分析
在这里插入图片描述
这里我们可以发现 this.currFileCtx.proxyStrToken 的值赋个了 A,而上面那三个参数均来自 Athis.currFileCtx.proxyStrToken,接下来我们找这三个参数
在这里插入图片描述
在这里插入图片描述
经过搜索发现是接口/web/api/media/upload/auth/v5/可以获取上面3个参数,该接口经过测试只有cookie为变化参数,意味着只要获取登录cookie即可调用该接口获取3个参数,接下来我们回到 t.addAuthorization 方法去分析具体设置 Headers 的方法
在这里插入图片描述
进入 t.addAuthorization 方法,发现首先通过当前时间计算出一个ISO的时间,格式为"yyyyMMddTHHmmssZ",由于我们这边时区为东八区,计算ISO时间时需要减少8个小时,接来下继续进入 this.addHeader 方法中分析
在这里插入图片描述
可以看到 Header 中的 “X-Amz-Date” 参数值就为上面计算出得ISO时间,而 “X-Amz-Date” 参数值为 “/web/api/media/upload/auth/v5/” 接口中的 sessionToken 值,到这里我们就只剩下请求头中的 Authorization 参数啦,接下来继续分析 Authorization 参数
在这里插入图片描述
可以看到 Authorization 参数由 this.authorization 方法获得,我们进入方法继续分析
在这里插入图片描述
可以看出 Authorization 由3部分组成,每个部分使用", " 分割(注意逗号后面含空格),其中第一部分值为 “AWS4-HMAC-SHA256 Credential=” + e.accessKeyId + “/20230520/cn-north-1/vod/aws4_request” 组成, e.accessKeyId 从 /web/api/media/upload/auth/v5/ 接口中可获取。
第二部分由 “SignedHeaders=x-amz-date;x-amz-security-token” 组成,其中 “x-amz-date;x-amz-security-token” 是 this.signedHeaders() 的值,该值经过测试为固定值。
第三部分由 “Signature=” + this.signature(e, t) 组成,接下来我们分析 this.signature(e, t) 方法。
在这里插入图片描述
可以看出由两部分组成,我们继续观察this.getSigningKey方法
在这里插入图片描述
发现基本上都是对a方法的复用,由于时间有限,这里不分析js算法具体原理,直接复制js、略加修改使其可执行,然后运行示例如下:
在这里插入图片描述
经过测试user_id参数未校验,所以这里直接省略了user_id参数,需要的也可自行补上。到这里我们所有参数都分析完成了,最终代码如下:


def random_s(lens=11):
    """
    随机生成s参数
    """
    digits = '0123456789'
    ascii_letters = 'abcdefghigklmnopqrstuvwxyz'
    l = digits + ascii_letters
    str_list = [random.choice(l) for i in range(lens)]
    random_str = ''.join(str_list)
    return random_str

def media_upload_auth_v5(cookie, **kwargs):
    """
    auth/v5
    主要获取AccessKeyId,SecretAccessKey 和 SessionToken
    """
    url = "https://creator.douyin.com/web/api/media/upload/auth/v5/"
    params = {
    
    
        "cookie_enabled": "true",
        "screen_width": "1920",
        "screen_height": "1080",
        "browser_language": "zh-CN",
        "browser_platform": "Win32",
        "browser_name": "Mozilla",
        "browser_version": "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
        "browser_online": "true",
        "timezone_name": "Asia/Shanghai",
    }
    headers = {
    
    
        'accept': 'application/json, text/plain, */*',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'no-cache',
        'cookie': cookie,
        'pragma': 'no-cache',
        'referer': 'https://creator.douyin.com/creator-micro/content/publish',
        'sec-ch-ua': '"Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36'
    }
    res = requests.get(url, params=params, headers=headers)
    # todo: 检查
    return res.json()

# 设置自己登录的cookie
cookie = 'XXXXX'

auth_data = media_upload_auth_v5(cookie)
print('认证数据: ', auth_data)

proxy_str_token = json.loads(auth_data["auth"])
print('proxyStsToken', proxy_str_token)

# 计算ISO时间
format_current_time = time.strptime(proxy_str_token["CurrentTime"], "%Y-%m-%dT%H:%M:%S+08:00")
iso_current_time = time.localtime(time.mktime(format_current_time) - 3600 * 8)
x_amz_date = time.strftime('%Y%m%dT%H%M%SZ', iso_current_time)

# 加载js
with open('../js/dy__video_Signature.js', 'r', encoding='utf-8') as f:
    js_ctx = execjs.compile(f.read())

# 获取随机11位的s参数
s = random_s()

# 固定
app_id = 2906
# 实时计算文件大小
file_size = 1174166

# 请求参数
params = {
    
    
    "Action": "ApplyUploadInner",
    "Version": "2020-11-19",
    "SpaceName": "aweme",
    "FileType": "video",
    "IsInner": 1,
    "FileSize": file_size,
    "app_id": app_id,
    "s": s,
}

# 封装js执行参数
e = {
    
    
    "accessKeyId": proxy_str_token["AccessKeyID"],
    "secretAccessKey": proxy_str_token["SecretAccessKey"],
    "sessionToken": proxy_str_token["SessionToken"],
}
# 计算authorization
authorization = ', '.join(
    [f"AWS4-HMAC-SHA256 Credential={
      
      proxy_str_token['AccessKeyID']}/{
      
      x_amz_date[:8]}/cn-north-1/vod/aws4_request",
     "SignedHeaders=x-amz-date;x-amz-security-token",
     f"Signature={
      
      js_ctx.call('getSignature', e, x_amz_date,1174166, s)}"
     ]
)

# 请求头
headers = {
    
    
    "Accept": "*/*",
    "Authorization": authorization,
    "Cache-Control": "no-cache",
    "Origin": "https://creator.douyin.com",
    "Pragma": "no-cache",
    "Referer": "https://creator.douyin.com/",
    "Sec-Ch-Ua": '"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"',
    "Sec-Ch-Ua-Mobile": "?0",
    "Sec-Ch-Ua-Platform": '"Windows"',
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "cross-site",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
    "x-amz-date": x_amz_date,
    "x-amz-security-token": proxy_str_token["SessionToken"],
}

res = requests.request('GET', 'https://vod.bytedanceapi.com/', params=params, data={
    
    }, headers=headers)

print("结果状态", res.status_code)
print("结果数据", res.text)

执行结果:
在这里插入图片描述
由于JS文件有600多行过长这里就不放出来了,可自行提取或者评论区留言找博主获取。

总结

创作者平台的发布视频第一部分的接口比较中规中矩,难度适中,比较适合拿来做基础练习,后续再继续分享后面步骤的学习记录。
今天的学习记录就到这啦~
最后再强调下哈,写这么多仅用于js逆向学习和分享,请勿用于不正当的用途哈~

猜你喜欢

转载自blog.csdn.net/qq_33129963/article/details/130780168