本帖所包含的内容仅限技术交流和学习研究使用,禁止用于其他用途!因使用不当造成的一切后果与本人无关!

家里有长辈喜欢听一个微信公众号里面的养生歌曲,觉得每次只能在微信中听很麻烦(据说是为了防盗版啥的),想把文件搞出来就方便多了。于是乎本人进行了一番尝试,成功提取出了文件。
其他的资源可以参考修改,理论上也可以获取。

0x00 分析

首先通过复制微信自带浏览器的网页链接的方式把地址搞到,然后在电脑上访问,可以打开,然而我们点击听歌的时候出现了验证,只允许从微信浏览器访问。
1.png
进一步分析网页源码可以看出每个歌曲有一个filesn,点击事件就是把filesn提交给一个GetUrlByFilesn的文件,检查后返回真实地址。

0x01 抓包

原本想通过改Referer和UA的方法直接在电脑上访问,不过貌似现在微信把这个给封了,算了简单起见还是直接抓手机包吧。这里我用的是Fiddler,其他工具应该大同小异。

  • 因为是https网页,我们需要装个插件CertMaker for iOS and Android
  • 打开Fiddler,点击菜单栏上的Tools-Fiddler Options-HTTPS,勾选上Decrypt HTTPS traffic,然后重启Fiddler
  • 打开手机,访问本机内网IP+8888,点击You can download the FiddlerRoot certificate安装证书即可

下面开始干活!
先看看失败和成功的返回值:

{"redirect":null,"code":"00001","msg":"请在微信客户端打开","mess":"请在微信客户端打开","data":null,"debug":null}
{"redirect":null,"code":"ok","msg":"操作成功","mess":"操作成功","data":"http://xxx.com/xxx.xxx?sign=xxx\u0026t=xxx","debug":null}

这里有一个sign值每次不同大概是验证。
接着是成功的包大概长这样(经过处理):

POST https://xxx.com/ajax/GetUrlByFilesn_xxx?from=%E5%BE%AE%E4%BF%A1&filesn=xxx HTTP/1.1
Host: xxx.com
Connection: keep-alive
Content-Length: 0
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Linux; Android 7.0; PIC-AL00 Build/HUAWEIPIC-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043806 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/en
Referer: https://xxx.com/file_a_list?classsn=xxx
Accept-Encoding: gzip, deflate
Accept-Language: en,en-US;q=0.8,zh-CN;q=0.6
Cookie: ASP.NET_SessionId=xxx; wx_openid_xxx=xxx; wx_unionid_xxx=xxx; is_funs_v4=1; cookie_from=dongfang; funsalert_isshowed=yes; token_xxx=xxx; access_token_xxx=xxx; token=xxx; access_token=xxx; wx_usersn_xxx=xxx; media_count=46

于是我们先构造一个相同的包发出去,OK,成功了!

0x02 绕弯路

这里还是我没仔细看绕的弯路,记下来吧。
获得了真实地址然而直接访问是403的!我以为是防盗链的原因折腾了半天,居然连Referer伪造都不行?然后因为用的是H5 audio标签来播放的,也没有什么缓存文件可以给我提取,我甚至试过wireshark抓音频流包来搞,结果发现因为SSL的原因文件怎么都是无效……
当我没辙的时候上了个厕所,回来突然发现URL中的\u0026不就是&么?改了一下访问,成功了……我靠!参数错了给个提示不就行了搞个403……

0x03 批量处理

接下来就没什么问题了,下下来的文件也可以自动播放,用py写个爬虫把文件下下来就行,先获取所有的filesn和歌曲名的对应,然后将每个file下下来就行

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
#coding=utf-8
import requests
import urllib
import os

while 1:
mainurl = raw_input("url:")
r = requests.get(mainurl)
i=0
lst={}
cks={}
hed={}
while 1:
start=r.text.find("o\" filesn=\"",i)
if start==-1:
break
sn=r.text[start+11:start+43]
namestart=r.text.find(u"、",start)
nameend=r.text.find("\">",namestart)
name=r.text[namestart+1:nameend]
lst[sn]=name
i=start+11
for key in lst:
cks['ASP.NET_SessionId']='xxx'
cks['wx_openid_xxx']='xxx'
cks['wx_unionid_xxx']='xxx'
cks['is_funs_v4']='1'
cks['cookie_from']='dongfang'
cks['funsalert_isshowed']='yes'
cks['token_xxx']='xxx'
cks['access_token_xxx']='xxx'
cks['token']='xxx'
cks['access_token']='xxx'
cks['wx_usersn_xxx']='xxx'
cks['media_count']='46'
hed['User-Agent']="Mozilla/5.0 (Linux; Android 7.0; PIC-AL00 Build/HUAWEIPIC-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043806 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/en"
r = requests.post('https://xxx.com/ajax/GetUrlByFilesn_xxx?from=%E5%BE%AE%E4%BF%A1&filesn='+key,headers = hed, cookies=cks )
stat=r.content.find("ta\":\"")
end=r.content.find("\",\"debug")
downurl=r.content[stat+5:end]
downurl=downurl.replace('\\u0026','&')
fpath = os.path.join('1',lst[key]+".m4a")
print 'Download '+lst[key]+".m4a...",
urllib.urlretrieve(downurl,fpath)
print 'Done!'

搞定收工!