前情提要
最近在研究塔可夫的DMA辅+++助,想要直观显示游戏内各种垃圾的每日平均价格,又不想直接逆向游戏内市场的繁杂逻辑(懒,且并不是要获取实时价格),遂在UC上一通搜索找到了tarkov-market.com这个网站。
想着利用这个网站的数据搞个脚本每天缓存一遍平均价格存储在本地以供使用。
一番摸索发现此网站提供官方API但是要收费,5刀每月,还不能试用。
image.png (69.32 KB, 下载次数: 0)
下载附件
2023-6-30 13:45 上传
本着先体验后付费的精神(白嫖),本次逆向就开始了。
正篇
查未公开接口
先进页面,往下滚动发现是滚动刷新,判别是瀑布流加载。
image-2.png (493.75 KB, 下载次数: 0)
下载附件
2
2023-6-30 13:45 上传
按F12呼出控制台,切换到Network并点上Preserve log和
Disable Cache,然后清空一下刷新页面。
image-3.png (173.64 KB, 下载次数: 0)
下载附件
3
2023-6-30 13:45 上传
搜索一下12.7的弹药
image-1.png (292.18 KB, 下载次数: 0)
下载附件
1
2023-6-30 13:45 上传
哦豁,什么都没有,可能是加密了。直接点选XHR。
image-4.png (260.06 KB, 下载次数: 0)
下载附件
4
2023-6-30 13:45 上传
有点眉目,看看里面啥样
没有验签,舒服!
image-5.png (128.89 KB, 下载次数: 0)
下载附件
5
2023-6-30 13:45 上传
数据加密了
image-6.png (32.34 KB, 下载次数: 0)
下载附件
6
2023-6-30 13:45 上传
末尾是=符号,有可能是base64加密
image-7.png (27.9 KB, 下载次数: 0)
下载附件
7
2023-6-30 13:45 上传
找个在线解密碰碰运气,个人常用:Base64在线加解密;
什么鬼,看来是处理过的。也有可能不是base64加密,扒代码!
image-8.png (393.84 KB, 下载次数: 0)
下载附件
8
2023-6-30 13:45 上传
复制一下链接,不用复制后面的两个参,(已经回返的数据条数和每次返回的数据条数)
image-10.png (51.73 KB, 下载次数: 0)
下载附件
10
2023-6-30 13:45 上传
请求接口没有验签,不用回溯这个调用逻辑,直接对XHR下断点
image-9.png (17.04 KB, 下载次数: 0)
下载附件
9
2023-6-30 13:45 上传
image-11.png (78.14 KB, 下载次数: 0)
下载附件
11
2023-6-30 13:45 上传
搞定
image-12.png (44.46 KB, 下载次数: 0)
下载附件
12
2023-6-30 13:45 上传
往下滚动网页加载数据,网页断下
image-13.png (522.34 KB, 下载次数: 0)
下载附件
13
2023-6-30 13:45 上传
还在请求部分,跳出当前函数,Shift+F11,
image-14.png (30.03 KB, 下载次数: 0)
下载附件
14
2023-6-30 13:45 上传
跳到这里
image-15.png (392.43 KB, 下载次数: 0)
下载附件
15
2023-6-30 13:46 上传
下面开始看参数(回传的乱码)变化进行单步 F9
[ol]
image-16.png (105.37 KB, 下载次数: 0)
下载附件
16
2023-6-30 13:46 上传
image-17.png (38.83 KB, 下载次数: 0)
下载附件
17
2023-6-30 13:46 上传
image-18.png (51.8 KB, 下载次数: 0)
下载附件
18
2023-6-30 13:46 上传
image-19.png (38 KB, 下载次数: 0)
下载附件
19
2023-6-30 13:46 上传
image-20.png (112.26 KB, 下载次数: 0)
下载附件
20
2023-6-30 13:46 上传
[/ol]
有点东西了,下面的看起来像是处理Json的部分,我们重点看看
image-21.png (113.58 KB, 下载次数: 0)
下载附件
21
2023-6-30 13:46 上传
把XHR断电移除,在这里下个断
image-22.png (109.33 KB, 下载次数: 0)
下载附件
22
2023-6-30 13:46 上传
往下滚动网页加载数据,网页断下,这里就是解密的部分
image-23.png (209.3 KB, 下载次数: 0)
下载附件
23
2023-6-30 13:46 上传
看起来不难,就不扣JS代码,直接搞逻辑然后用Python重写, 我就在下面的代码上进行注释了(自下而上进行回溯),断点不要释放
const xa = String[mi(375)]
, km = xa(100 - 3) + xa(110 + 6) + xa(105 + 6) + xa(105 - 7)
, Tv = ()=>[(31 - 6) / (30 * 100 >> 9), parseInt(window[km](mi(385))), 36]
, Dv = e=>e.substring(...Tv().reverse()[mi(372)](1))
, bv = e=>{
const s = mi
, r = {
acjba: function(i, o) {
return i + o
},
GAVPm: function(i, o) {
return i
至此,已经逆向完成,我们简化一下。
[ol]
[/ol]
最终的n就是我们要获取的已经解密的json内容,下面用Python代码转写一下。不会的可以扔进ChatGpt,下面直接放Python代码:
import urllib.parse
import base64
def decrypt(input_string):
decrypt_text = None
try:
i = input_string[0:5] + input_string[10:]
i = base64.b64decode(i)
i = urllib.parse.unquote(i)
decrypt_text = loads(i)
except:
print('[-] ERROR When Parse')
pass
# print(decrypt_text)
return decrypt_text
逆向/Python重写JS解密逻辑
实际写爬虫进行爬取的时候发现网站有反爬机制,直接使用Python Request请求是搞不定的。具体机制请参考下面的链接,这里不再赘述。
反爬虫SSL TLS指纹识别和绕过JA3算法;
秉承着能懒就懒的原则,我给出两种方案:
--- 使用Selenium来请求,然后正则把加密内容给搞下来,代码如下(仅展现处理一页):
import undetected_chromedriver as uc
from time import sleep
from json import loads
from re import findall
import urllib.parse
import base64
def decrypt(input_string):
decrypt_text = None
try:
i = input_string[0:5] + input_string[10:]
i = base64.b64decode(i)
i = urllib.parse.unquote(i)
decrypt_text = loads(i)
except:
print('[-] ERROR When Parse')
pass
# print(decrypt_text)
return decrypt_text
def main():
options = uc.ChromeOptions()
# options.add_argument( '--headless' )
driver = uc.Chrome(options=options)
driver.get(url='https://tarkov-market.com/api/be/items?lang=en&search=&tag=&sort=change24&sort_direction=desc&trader=&skip=40&limit=20')
temp_text = driver.find_element('tag name', 'body').text
if len(temp_text)>= 300 and len(findall("\"result\":\"ok\"", temp_text)) >= 1:
with open('TarkovItemPrice.json', 'w', encoding='utf-8') as f:
f.write(decrypt(loads(temp_text)['items']))
else:
print("[-] Request failed...")
print("[+] Exit...")
_wait = input()
if __name__ == "__main__":
main()
--- 使用curl_cffi里魔改过TLS指纹的Request来请求,代码如下(仅展现处理一页):
import urllib.parse
import base64
from json import loads, dumps
from curl_cffi import requests
def decrypt(input_string):
decrypt_text = None
try:
i = input_string[0:5] + input_string[10:]
i = base64.b64decode(i)
i = urllib.parse.unquote(i)
decrypt_text = loads(i)
except:
print('[-] ERROR When Parse')
pass
# print(decrypt_text)
return decrypt_text
def main():
url = "https://tarkov-market.com/api/be/items?lang=en&search=&tag=&sort=change24&sort_direction=desc&trader=&skip=20&limit=20"
headers = {
'authority': 'tarkov-market.com',
'accept': '*/*',
'accept-language': 'en,zh-CN;q=0.9,zh;q=0.8',
'cache-control': 'no-cache',
'dnt': '1',
'pragma': 'no-cache',
'referer': 'https://tarkov-market.com/',
'sec-ch-ua': '"Google Chrome";v="110", "Chromium";v="110", "Not-A.Brand";v="24"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36'
}
temp_text = requests.get(url=url, headers=headers, impersonate="chrome110").text
temp_json = loads(temp_text)
with open('TarkovItemPrice.json', 'w', encoding='utf-8') as f:
f.write(dumps(decrypt(temp_json['items'])))
print("[+] Exit...")
_wait = input()
if __name__ == "__main__":
main()
总结
综合来说这个网站难度较低,逆向出了解密代码就可以写个遍历获取所有的数据了,可以设置个计划任务每天跑一遍就可以拿到最新的商品价格以供使用了。