某度网盘提取下载链接JS逆向分析(一)

发布时间:2024年01月22日

本次目标网址如下,使用base64解码后获得
aHR0cHM6Ly9wYW4uYmFpZHUuY29tL3MvMUZsaDBPeGpZamZJTFVZWUQzTm9fVnc=
链接提取码为:ly12

本次逆向分析分为上下两篇文章说明,一为讲解如何从原链接通过逆向拿到下载链接,二为逆向登录拿到cookie,因为在获取下载链接的过程中,是要登录百度网盘的账号的,本文在讲解提取的过程中,登录后的cookies先固定死,只讲解最后拿到的百度网盘链接,后面再讲解逆向登录拿到cookie

1、找到下载链接

下载链接其实非常好找,打开network,点击下载查看接口协议就能看到,如下图
在这里插入图片描述
将下载链接跟接口中比对查找后就能发现,与dlink字段的值一模一样,那么下载链接就在share这个接口里面

2、分析接口参数

我们将share接口复制成curl请求后,放到该网站解析
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ad8500f6d7a144a89bca7466207471bb.png

https://curlconverter.com/python/

通过转换成python代码后如下
在这里插入图片描述
那么本次需要分析的就是data参数和url链接参数

3、分析data参数

这些参数我们逐个研究,先从data参数入手,这里固定的参数就不再多说了,只说变化的参数,全局搜索extra字段, 通过试错查找,发现在这个位置生成
在这里插入图片描述
我们跟进s函数,发现就是取出cookie,那个extra值就是cookie中的BDCLND,由于之前说过,本文不涉及登录,cookie参数是固定的,所以这里就不再往下追究去找cookie的来源了

在这里插入图片描述
vcode_input是输入验证码的参数,vcode_str是请求验证码时附带的校验参数,需要和正确的验证码一起传回去,校验验证码是否正确,如下图,可以找到vcode_str的来源
在这里插入图片描述
接着看primaryid参数,还是跟栈查找,在这个位置
在这里插入图片描述
查找流程就不多说了,稍微根根就能找到,可以发现,primaryid就是shareid, uk就是share_uk,一下子解决两个参数,我们再往前跟栈找找,查看参数生成的位置
在这里插入图片描述
最终我们发现,这两个参数都是在请求网页时附带生成, 同样fid_list应该就是文件列表的id,也在加载网页时就附带了
在这里插入图片描述
至此,data参数已经分析完毕

4、分析链接参数

接着,我们看请求链接中的参数,我们重放请求后,最后确定,可变的参数如下

 f'https://pan.baidu.com/api/sharedownload?sign={sign}&timestamp={timestamp}&channel=chunlei&web=1&app_id={appid}&bdstoken={bdstoken}&logid={logid}&clienttype=0&jsToken={jsToken}&dp-logid={dplogid}'

sign和timestamp在tplconfig接口里面
在这里插入图片描述
appid是固定应用id,bdstoken在yundata里面
在这里插入图片描述
logid是cookie里的BAIDUID
dplogid是全局函数window.BpDataInstance.getDpLogId()
在这里插入图片描述
至此,所有加密参数已经找到

5、组装加密接口

加密接口组装流程如下,
初始化进入页面接口-获取sign接口-获取验证码接口-获取下载链接接口
按照流程,组装代码如下

response = session.get('https://pan.baidu.com/s/1Flh0OxjYjfILUYYD3No_Vw?pwd=ly12?', headers=headers)

# 使用正则表达式提取带有 window.jsToken 的 script 标签内容
pattern = r'<script\b[^>]*>([\s\S]*?)<\/script>'
matches = re.findall(pattern, response.text)

# 遍历匹配到的 script 标签内容
for match in matches:
    if 'window.jsToken' in match:
        # print(match)
        jsToken = urllib.parse.unquote(match)
        jsToken = jsToken.split('("')[1].split('")')[0]

# 遍历匹配到的 script 标签内容
for match in matches:
    if 'window.yunData' in match:
        # 使用正则表达式提取第二个自执行代码块
        pattern = r'!function\(\)\s*{([\s\S]*?)}\(\);'
        selfexecutes = re.findall(pattern, match)
        # 输出第二个自执行代码块
        for selfexecute in selfexecutes:
            if "window.yunData" in selfexecute:
                selfexecutefun = selfexecute


sign_url = 'https://pan.baidu.com/share/tplconfig?surl=' + download_param


sekey = urllib.parse.unquote(cookies.get("BDCLND"))

jsstr = execjs.compile(jsstr.replace("{selfexecutes}", selfexecutefun))
yunData = jsstr.call("get_yundata")
locals = jsstr.call("get_locals")

bdstoken = yunData.get("bdstoken")
fsid = locals.get('file_list')[0].get("fs_id")

# 获取sign接口
response = session.get(
    sign_url + f'&fields=sign,timestamp&channel=chunlei&web=1&app_id={appid}&bdstoken={bdstoken}&logid={logid}&clienttype=0&dp-logid={dplogid}',
    headers=headers,
)


sign = response.json().get("data").get("sign")
timestamp = response.json().get("data").get("timestamp")

# 请求验证码
response = session.get(
    f'https://pan.baidu.com/api/getvcode?prod=pan&t=0.2430438848136891&channel=chunlei&web=1&app_id={appid}&bdstoken={bdstoken}&logid={logid}&clienttype=0&dp-logid={dplogid}',
    headers=headers,
)
print(response.json())
vcode_str = response.json().get("vcode")
img = response.json().get("img")

# 下载验证码
response = session.get(img,
                       cookies=cookies,
                       headers=headers, )
with open('vcode.jpg', 'wb') as f:
    f.write(response.content)

# vcode_str = '3332423865633234636166333465663732323763363637363764323966666433666231363236383236373834303030303030303030303030303031373035353639333539FD63FF431D35E2B5D98E13D16C79AEA0'
print(1)
# 获取下载链接

data = {
    'encrypt': '0',
    'extra': '{"sekey":"%s"}' % sekey,
    'product': 'share',
    'vcode_input': 'H4DG',
    'vcode_str': vcode_str,
    'uk': yunData.get("share_uk"),
    'primaryid': yunData.get("shareid"),
    'fid_list': f'[{fsid}]',
    'path_list': '',
    'vip': '2',
}

response = session.post(
    f'https://pan.baidu.com/api/sharedownload?sign={sign}&timestamp={timestamp}&channel=chunlei&web=1&app_id={appid}&bdstoken={bdstoken}&logid={logid}&clienttype=0&jsToken={jsToken}&dp-logid={dplogid}',
    headers=headers,
    data=data,
)
print(response.text)
dlink = response.json().get('list')[0].get('dlink')
server_filename = response.json().get('list')[0].get('server_filename')

response = session.get(
    dlink,
    cookies=cookies,
    headers=headers,
)
print(response)
print(server_filename, len(response.content))
with open(server_filename, "wb") as f:
    f.write(response.content)

用到的js补环境如下,navigator实际上并没有用到那么多,我使用一键获取,懒得删用不着的变量了:

window = global;

navigator = {
    "vendorSub": "",
    "productSub": "20030107",
    "vendor": "Google Inc.",
    "maxTouchPoints": 0,
    "scheduling": {},
    "userActivation": {},
    "doNotTrack": null,
    "geolocation": {},
    "connection": {},
    "plugins": {
        "0": {
            "0": {},
            "1": {}
        },
        "1": {
            "0": {},
            "1": {}
        },
        "2": {
            "0": {},
            "1": {}
        },
        "3": {
            "0": {},
            "1": {}
        },
        "4": {
            "0": {},
            "1": {}
        }
    },
    "mimeTypes": {
        "0": {},
        "1": {}
    },
    "pdfViewerEnabled": true,
    "webkitTemporaryStorage": {},
    "webkitPersistentStorage": {},
    "hardwareConcurrency": 8,
    "cookieEnabled": true,
    "appCodeName": "Mozilla",
    "appName": "Netscape",
    "appVersion": "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "product": "Gecko",
    "language": "zh-CN",
    "languages": [
        "zh-CN",
        "zh"
    ],
    "onLine": true,
    "webdriver": false,
    "deprecatedRunAdAuctionEnforcesKAnonymity": false,
    "bluetooth": {},
    "clipboard": {},
    "credentials": {},
    "keyboard": {},
    "managed": {},
    "mediaDevices": {},
    "storage": {},
    "serviceWorker": {},
    "virtualKeyboard": {},
    "wakeLock": {},
    "deviceMemory": 8,
    "cookieDeprecationLabel": {},
    "login": {},
    "ink": {},
    "hid": {},
    "locks": {},
    "gpu": {},
    "mediaCapabilities": {},
    "mediaSession": {},
    "permissions": {},
    "presentation": {},
    "usb": {},
    "xr": {},
    "serial": {},
    "windowControlsOverlay": {},
    "userAgentData": {
        "brands": [
            {
                "brand": "Not_A Brand",
                "version": "8"
            },
            {
                "brand": "Chromium",
                "version": "120"
            },
            {
                "brand": "Google Chrome",
                "version": "120"
            }
        ],
        "mobile": false,
        "platform": "Windows"
    }
}

location = {
    "ancestorOrigins": {},
    "href": "https://pan.baidu.com/s/1TBy2gI-PUz2P_SWjCjq-ww?pwd=d1g1",
    "origin": "https://pan.baidu.com",
    "protocol": "https:",
    "host": "pan.baidu.com",
    "hostname": "pan.baidu.com",
    "port": "",
    "pathname": "/s/1TBy2gI-PUz2P_SWjCjq-ww",
    "search": "?pwd=d1g1",
    "hash": ""
}

document = {}

locals = {
	set: function(k, v){
		//console.log(k,v);
		this[k] = v
	},
	mset: function(v){
		this.data = v
	}
}



require("./bpdatajs-sdk-min-1.3.3.js")



if (window.BpData) {
	window.BpDataInstance = new BpData({
		serverId: 13328,
		from: 'main',
		page: 'share_common_page',
		parasitifer: 'web'
	})
}


{selfexecutes}



function getDpLogId(){
	/*
	for(var i = 0;i < 40;i ++){
		window.BpDataInstance.getDpLogId()
	}
	*/
	return window.BpDataInstance.getDpLogId()
}

function get_yundata(){
	return window.yunData;
}
function get_locals(){
	return locals.data;
}
function get_servertime(){
	return locals.servertime;
}


//console.log(locals);

最后,也能成功下载文件到本地
在这里插入图片描述

文章来源:https://blog.csdn.net/qq_36551453/article/details/135704235
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。