翼度科技»论坛 编程开发 python 查看内容

逆向 Virustotal 搜索接口 X-VT-Anti-Abuse-Header

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
搜索示例

搜索 123,网页地址为:https://www.virustotal.com/gui/search/123/comments

请求接口
  1. GET /ui/search?limit=20&relationships%5Bcomment%5D=author%2Citem&query=123 HTTP/1.1
  2. Accept-Encoding: gzip, deflate, br, zstd
  3. Accept-Ianguage: en-US,en;q=0.9,es;q=0.8
  4. Accept-Language: zh-CN,zh;q=0.9
  5. Cache-Control: no-cache
  6. Connection: keep-alive
  7. Cookie: _gid=GA1.2.1662779803.1728383656; _ga=GA1.2.686372046.1728383655; _gat=1; _ga_BLNDV9X2JR=GS1.1.1728383655.1.1.1728383759.0.0.0
  8. DNT: 1
  9. Host: www.virustotal.com
  10. Pragma: no-cache
  11. Referer: https://www.virustotal.com/
  12. Sec-Fetch-Dest: empty
  13. Sec-Fetch-Mode: cors
  14. Sec-Fetch-Site: same-origin
  15. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
  16. X-Tool: vt-ui-main
  17. X-VT-Anti-Abuse-Header: MTgwNjgyNDI1ODItWkc5dWRDQmlaU0JsZG1scy0xNzI4MzgzNzYxLjMxMg==
  18. accept: application/json
  19. content-type: application/json
  20. sec-ch-ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"
  21. sec-ch-ua-mobile: ?0
  22. sec-ch-ua-platform: "Windows"
  23. x-app-version: v1x304x0
复制代码
注意观察,其中发现参数:X-VT-Anti-Abuse-Header 需要逆向,目测是 base64 加密,这个参数的含义也很明确——“反滥用头”。在编写爬虫的代码层的实现时,尽量将 User-Agent、X-Tool、x-app-version 补全,因为它们是网站特有的亦或者常见的反爬识别参数。
值得注意的是,X-Tool、x-app-version 是固定值,x-app-version 需要定期去官网查看一下更新,不更新可能也行,自行测试。
也就是说,目前我们得到如下 Headers:
  1. {
  2.     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
  3.     'X-Tool': 'vt-ui-main',
  4.     'x-app-version': 'v1x304x0',
  5. }
复制代码
开始逆向

接下来,逆向 X-VT-Anti-Abuse-Header,总体没啥难度,不过这个网站具备反调试措施(无法断点调试、无法从请求的启动器回溯),这个反调试我没有去解决,而是通过直接查找。
搜索 X-VT-Anti-Abuse-Header,可得到:

直接进入该 js 文件中:

可以看到,我们的目标参数由方法 r.computeAntiAbuseHeader() 计算而来。全局搜索 computeAntiAbuseHeader:

序号1为我们所需的,也就是函数的实现,序号2为该函数的调用,也就是上方的 X-VT-Anti-Abuse-Header 来源。进入 1 所在的 js 文件。

可以看到,这个方法真的非常简单,不需要任何回溯和断点,可以直接的手搓出来。这个网站典型的将反爬中的防君子不防小人做得很好。言归正传,这个方法:

  • 首先获取当前时间的秒级时间戳
  • 然后生成一个介于 1e10 和 5e14 之间略大的随机数,如果生成的数小于 50,则返回 "-1",否则返回该数的整数部分
  • 最后将生成的随机数、固定字符串 "ZG9udCBiZSBldmls"(意为 "不要作弊")和当前时间戳拼接并进行 base64 加密
有趣的一点是:
  1. > atob('ZG9udCBiZSBldmls ')
  2. < 'dont be evil'
复制代码
固定的字符串告诉我们不要作恶……这尼玛绝了,哈哈哈哈
加密实现
  1. # header.py
  2. import base64
  3. import random
  4. import time
  5. def computeAntiAbuseHeader():
  6.     e = time.time()
  7.     n = 1e10 * (1 + random.random() % 5e4)
  8.     raw = f'{n:.0f}-ZG9udCBiZSBldmls-{e:.3f}'
  9.     res = base64.b64encode(raw.encode())
  10.     return res.decode()
  11. if __name__ == '__main__':
  12.     print(computeAntiAbuseHeader())
复制代码
结束了吗?

看到这里你以为结束了?oh~不,还差一点点,尽管你有了上述的分析和实现,你发现你怎么请求都没用!数据还是不给你,为啥?
再次将你的视线挪移到请求接口中:
  1. Accept-Ianguage: en-US,en;q=0.9,es;q=0.8
  2. Accept-Language: zh-CN,zh;q=0.9
复制代码
此处有个容易忽略的老6请求头:Accept-Ianguage,好了,到此才算结束了,看一下下方完整的代码示例吧。
  1. """
  2. 翻页采集实现
  3. 2024年9月27日 solved
  4. https://www.virustotal.com/gui/
  5. """
  6. import time
  7. import requests
  8. import header
  9. from urllib.parse import urlencode, urlparse
  10. base_url = "https://www.virustotal.com/ui/search"
  11. initial_params = {
  12.     "limit": 20,
  13.     "relationships[comment]": "author,item",
  14.     "query": "baidu"
  15. }
  16. proxies = {
  17.     'http': None,
  18.     'https': None
  19. }
  20. def build_url(url, params):  # ☆
  21.     return urlparse(url)._replace(query=urlencode(params)).geturl()
  22. def get_headers():
  23.     return {
  24.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
  25.         'X-Tool': 'vt-ui-main',
  26.         'X-VT-Anti-Abuse-Header': header.computeAntiAbuseHeader(),
  27.         'x-app-version': 'v1x304x0',
  28.         'accept-ianguage': 'en-US,en;q=0.9,es;q=0.8'
  29.     }
  30. def fetch_data(url):
  31.     response = requests.get(url, headers=get_headers(), proxies=proxies)
  32.     return response.json()
  33. def process_data(data):
  34.     for item in data['data']:
  35.         print(f"ID: {item['id']}, Type: {item['type']}")
  36. # 主循环
  37. next_url = build_url(base_url, initial_params)
  38. while next_url:
  39.     print(f"Fetching: {next_url}")
  40.     json_data = fetch_data(next_url)
  41.     # 检查是否有数据
  42.     if not json_data.get('data'):
  43.         print("No more data.")
  44.         break
  45.     # 处理当前页面的数据
  46.     process_data(json_data)
  47.     # 获取下一页的 URL
  48.     next_url = json_data.get('links', {}).get('next')
  49.     if not next_url:
  50.         print("No more pages.")
  51.         break
  52.     time.sleep(1)
  53. print("Finished fetching all pages.")
复制代码
来源:https://www.cnblogs.com/gupingan/p/18452325
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
来自手机

举报 回复 使用道具