MXWXZ 发表于 2018-1-15 22:25

微信公众号资源抓取(数据包分析+源码)

本帖最后由 MXWXZ 于 2018-1-15 22:28 编辑

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

0x00 分析
首先通过复制微信自带浏览器的网页链接的方式把地址搞到,然后在电脑上访问,可以打开,然而我们点击听歌的时候出现了验证,只允许从微信浏览器访问。

进一步分析网页源码可以看出每个歌曲有一个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/GetUrlByFil ... 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下下来就行
#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
      namestart=r.text.find(u"、",start)
      nameend=r.text.find("\">",namestart)
      name=r.text
      lst=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
      downurl=downurl.replace('\\u0026','&')
      fpath = os.path.join('1',lst+".m4a")
      print 'Download '+lst+".m4a...",
      urllib.urlretrieve(downurl,fpath)
      print 'Done!'

搞定收工!

凌风者 发表于 2018-11-12 16:38

哈哈,学习了,上厕所也能解决问题~
多谢分享,留痕记录下,回头需要了来学习怎么提取东西的思路

情有可原 发表于 2018-1-15 22:35

看着有点深奥,先留下了,慢慢看,感谢

一粒米饭叔 发表于 2018-1-15 22:43

慢慢学习

kk1212 发表于 2018-1-15 23:07

厉害,表现出色

gunxsword 发表于 2018-1-15 23:14

不错,感谢分享!

psp7456 发表于 2018-1-15 23:40

厉害,学习了!谢谢分享

神奇林 发表于 2018-1-16 09:02

学习一下,谢谢楼主分享

zealred 发表于 2018-1-16 10:25

学习一下,感谢分享。

kolar 发表于 2018-1-16 11:31

打分的一个,论上厕所的重要性,笑死了。

SSHZDR 发表于 2018-1-16 16:04

公众号自传音频我一般都是用IDM直接下载
页: [1] 2 3 4 5
查看完整版本: 微信公众号资源抓取(数据包分析+源码)