本帖最后由 Arcticlyc 于 2022-11-9 08:28 编辑
起因
在论坛冲浪时发现有人分享了一个很nice的网站:https://mmzztt.com/,又看到有uu在问如何获取图片地址,因此对其进行研究并写下帖子记录。
提醒:该网站现已限制最多浏览15张图片,想看更多需要下载app
看见有人问这个是用来干嘛的,因为网站每个图集打开只能看到第一张图片,后面的图片链接无法直接得到,本帖是逆向网站js获取每个图集里的图片链接地址
*** 但是由于现在限制了只能看15张图片,所以其实也只能获取到前15张图片的链接,我感觉前15张图片没什么好看的,所以主要是找到js解密的关键代码并分享出来,大家想爬的可以自己写代码爬取,现在已经能够获取到图片的链接,其他的应该也不是很困难 ***
逆向过程
当我f12打开控制台的时候,真的是一脸懵逼,这混淆得我真的想哭!!!一眼看去没有一个知道是啥的变量,只能硬着头皮上了。
首先打开是一个自动debugger,这个直接找到断点的起始处,用本地替换过掉,然后开始分析。刚开始我完全是自己琢磨,一看图片既不在源代码也没有ajax请求,找了好久才发现是js解密后直接得出图片链接,又花了很长时间才找到加密关键处。
但是,由于这个坑爹的混淆(一句代码甚至占好久行),我被引向了岔路,而且还搞了几个小时,最后本来打算放弃了,但是突然又发现已经有人分享过这个逆向方法了,一看,我中间那段找对了呀,于是重拾信心,根据原帖,修改(很小)部分代码,并测试成功。
原帖地址:http://www.konforever.xyz/2022/mmzztt-spider/
逆向分享
1. pid值,也就是网址后面的几个数字。
2. 根据原帖,图片采用AES加密,其中解密需要用到cacheSign,这个参数在源代码中可以找到,不过现在的位数有所变化,我对代码进行了修改。
3. IV值的获取并没有变化,仍然是原来的算法。
4. AES解密的密钥,key值的计算和原来不一样,经观察后面这一串字符应该是固定的,
结束
至此该网站js逆向结束,顺便附上js解密部分的代码。
[Python] 纯文本查看 复制代码 from typing import List
import binascii
import json
import re
import requests
from lxml import etree
from Crypto.Cipher import AES
from Crypto.Hash import MD5
def decrypt(pid: str|int, cache_sign: str) -> List[str]:
pid = int(pid)
IV = "".join([str(pid % i % 9) for i in range(2, 18)]).encode()
key = MD5.new((f"{pid}6af0ce23e2f85cd971f58bdf61ed93a6").encode()).hexdigest()[8:24].encode()
aes = AES.new(key, AES.MODE_CBC, IV)
result = aes.decrypt(binascii.a2b_hex(cache_sign)).rstrip()
result = re.findall(r'(\[.*\])', result.decode())[0]
return json.loads(result)
def get_cache_sign(pid: str|int) -> str|None:
url = "https://mmzztt.com/photo/{}".format(pid)
res = requests.get(url, headers={
"referer": "https://mmzztt.com/",
"user-agent": "Mozilla/5.0"
})
if res.status_code == 200:
html = etree.HTML(res.text)
return html.xpath("//body/comment()")[0].__str__()[68:-3]
if __name__ == '__main__':
pid = ''
res = get_cache_sign(pid)
resp = decrypt(pid, res)
print(resp) |