开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 138|回复: 1
收起左侧

[技术文章] 蓝奏云直链下载协议分析

[复制链接]
结帖率:50% (1/2)
发表于 昨天 15:06 | 显示全部楼层 |阅读模式   浙江省杭州市
本帖最后由 我本尘埃 于 2026-5-20 15:12 编辑

蓝奏云直链下载协议分析

最近有个需求要批量下载蓝奏云分享的文件,网上搜了一圈都是些过时的接口或者要钱的解析站,干脆自己抓包走一遍。

环境:Chrome + F12,最后用 Python requests 复现。


一、文件夹密码验证,拿文件列表

链接 ****,打开是个密码框,输入 61tx。

切到 Network 看 XHR,密码提交后走了这么个请求:

POST https://wwbwz.lanzoul.com/filemoreajax.php?file=13512492

lx=2&fid=13512492&uid=5173976&pg=1&rep=0&t=1779256017&k=76a1cce0138a64290d289b19f20cdfbf&up=1&ls=1&pwd=61tx

返回的 json:

{
  "zt": 1,
  "info": "sucess",
  "text": [{
    "id": "iX9ow3pt9ali?webpage=U2JWNgpgBmtWMlAzVDYGMVI6Um5VdgU1VWo...",
    "name_all": "GlassKeep-Setup-2.0.0.exe",
    "size": "85.7 M"
  }]
}

文件 id 在里面了,拼一下就是详情页地址:https://wwbwz.lanzoul.com/iX9ow3pt9ali?webpage=...

提交参数里的 fid、uid、t、k 怎么来的?右键看页面源码,这些值都在一段 script 里,大概是:

var ib0cv3 = '1779257519';   // t 参数的值
var _gyoww = 'c7d18967cd...'; // k 参数的值
...
data: { 't': ib0cv3, 'k': _gyoww, ... }

这里有个坑:变量名不是固定的。我隔几分钟刷新,ib0cv3 变成了 ixy9pq,再过一会又变了。所以不能直接正则写死变量名。

怎么搞?先正则匹配 't': 变量名, 这段,拿到变量名,再回头去找这个变量的赋值,这样它怎么变都不怕。

t_var = re.search(r"'t'\s*:\s*(\w+)\s*,", html).group(1)
t_val = re.search(rf"{t_var}\s*=\s*'(\d+)'", html).group(1)

二、文件详情页,过反爬

拿到文件 id 之后直接 GET 详情页,结果返回的不是页面,是一大段混淆的 js:

var arg1='BFED7AE7961FBD5E4E5B456DC5E30DEA57A3833D';
(function(a,c){var G=a0j,d=a();while(!![]){...}})(...);
document.cookie='acw_sc__v2='+v+';...';document.location.reload();

一看就知道是阿里云 WAF 的那套 acw_sc 反爬。这套东西逻辑不复杂,就是:

  1. 服务端给一个 40 位的 hex 串 (arg1)
  2. 按一个固定的位置表重新排列字符
  3. 和一个固定密钥逐字节 XOR
  4. 结果写到 cookie acw_sc__v2,然后 location.reload()

反正我只需要结果,直接把这俩常量从 js 里抠出来写进 Python:

ACW_M = [0xF,0x23,0x1D,0x18,0x21,0x10,0x1,0x26,0xA,0x9,0x13,0x1F,
         0x28,0x1B,0x16,0x17,0x19,0xD,0x6,0xB,0x27,0x12,0x14,0x8,
         0xE,0x15,0x20,0x1A,0x2,0x1E,0x7,0x4,0x11,0x5,0x3,0x1C,
         0x22,0x25,0xC,0x24]

ACW_P = "3000176000856006061501533003690027800375"

# 算法还原
q = [''] * 40
for x in range(40):
    for z in range(40):
        if ACW_M[z] == x + 1:
            q[z] = arg1[x]
u = ''.join(q)
v = ''
for i in range(0, 40, 2):
    val = int(u[i:i+2], 16) ^ int(ACW_P[i:i+2], 16)
    v += f'{val:02x}'

# 写入 session 的 cookie,重试 GET 就能拿到正常页面了

这关过了之后,页面里就能拿到两个关键东西:

  • fid = 286947778——文件的数字 id
  • 一个 iframe 的 src:/fn?VzEAals0AGxWNlQ7UzNTZVE8BzVRNgAkB...

三、iframe 里的签名,换 CDN 下载地址

这个 iframe 点进去是个单独的页面,里面有一段 js:

var wp_sign = 'AGZRb1prAjNRWAc4BzcHOwBoAz4DagM4ADNVZFI5UGZTa1MiWnM...';
var ajaxdata = 'QcSp';
var kdns = 1;

然后页面加载完自动发了一个 AJAX:

POST https://wwbwz.lanzoul.com/ajaxm.php?file=286947778

action=downprocess&websignkey=QcSp&signs=QcSp&sign={wp_sign}&websign=2&kd=1&ves=1

返回值:

{
  "zt": 1,
  "dom": "https://developer3.lanrar.com",
  "url": "?BGJRbw08VGUIAQY+AzZUOAE+VW1eRgRqAmRQJVZ5WhACZwA...",
  "inf": 0
}

直链地址 = dom + "/file/" + url 拼起来就行了。注意这个 inf 字段,0 表示不用验证,直接用。

在同一个 session 里 GET 这个地址,直接返回文件流:

HTTP 200
Content-Type: application/octet-stream
Content-Disposition: attachment; filename*=UTF-8''GlassKeep-Setup-2.0.0.exe
Content-Length: 89825826
Accept-Ranges: bytes

支持 Range,断点续传也没问题。


四、inf ≠ 0 的情况——CDN 有个验证页

偶尔会遇到 inf 不是 0 的情况,这时候 GET 那个 CDN 地址会返回一个验证页面,大概长这样:

系统发现您的网络异常,需要验证后下载文件
[验证并下载]

页面 js 里有三个参数:

'file': 'VDxRcgkgVHBUcQpmUygGKFtkD3JfZQo5Bi9bKgI7UTIHYFdl...',
'el': 2,
'sign': 'ADFRMV40AWwDZwNgAGIGN1Y+UmVfYQ=='

然后 POST 到同域名的 ajax.php,带上这三个参数,返回的 json 里 url 字段就是真实下载地址。

resp = session.post(cdn_domain + "/ajax.php", data={
    "file": file_param, "el": el_val, "sign": sign_val
})
real_url = resp.json()["url"]

这个验证页面看起来是 CDN 那边做的人机校验,不过只要把参数提出来直接 POST 就行,几行代码的事。


整个流程理一遍就是:

分享链接
  ↓ GET 页面 → 正则提 fid/uid/t/k (变量名自适应)
  ↓ POST filemoreajax.php + 密码
文件列表 [id, name, size]
  ↓ GET /文件id
  ↓ 遇到反爬 → 算 acw_sc__v2 cookie → 重试
  ↓ 从页面提 fid + iframe src
  ↓ GET iframe → 提 wp_sign
  ↓ POST ajaxm.php + wp_sign
CDN 下载地址
  ↓ inf=0 → 直接 GET → 文件流 (支持 Range 断点续传)
  ↓ inf≠0 → 验证页 → POST ajax.php → 换真实链接 → GET

回头看其实不算复杂,就是反爬那关要稍微绕一下。那套 acw_sc 的映射表和密钥应该是跟域名绑定的,wwbwz.lanzoul.com 这套测试下来没变过,直接写死了用。

整个流程用 Python 跑下来,85.7M 的文件大概 13 秒左右下完,速度还不错。

评分

参与人数 1好评 +1 收起 理由
是永乐哟 + 1 直接回到学习的时候了

查看全部评分

签到天数: 21 天

发表于 昨天 19:44 | 显示全部楼层   河南省许昌市
好像不用算吧  我记得直接能在静态取到所有的参数  并且302重定向地址 然后在返回里就是直链
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表