塔科夫市场API逆向【tarkov-market.com】

查看 81|回复 9
作者:DeathMeeting   
新人发帖,请多指教
前情提要
最近在研究塔可夫的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]
  • 一次F9


    image-16.png (105.37 KB, 下载次数: 0)
    下载附件
    16
    2023-6-30 13:46 上传
  • 二次F9


    image-17.png (38.83 KB, 下载次数: 0)
    下载附件
    17
    2023-6-30 13:46 上传
  • 三、四、五次F9


    image-18.png (51.8 KB, 下载次数: 0)
    下载附件
    18
    2023-6-30 13:46 上传
  • 六次F9


    image-19.png (38 KB, 下载次数: 0)
    下载附件
    19
    2023-6-30 13:46 上传
  • 七次F9


    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]
  • 取得接口返回的Json里面的items字符串e
  • i = e
  • i = i.substring(0, 5) + i.substring(10)
  • i = atob(i)
  • n = Json.parse(decodeURIComponent(i))
    [/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()
    总结
    综合来说这个网站难度较低,逆向出了解密代码就可以写个遍历获取所有的数据了,可以设置个计划任务每天跑一遍就可以拿到最新的商品价格以供使用了。

    下载次数, 下载附件

  • tomxiong   

    比较好的教学文,步骤清晰,做爬虫解密的参考价值大,也可供加密方参考未来如何防范。
    KUBSU   

    强啊大佬
    zhanghong   

    太棒了,过程很清楚,很好
    bloy123   

    这个确实牛逼 但是不会用啊。。。。
    u2000   

    太高端了。。。玩不好啊
    GalaWorm   

    牛逼7u欲哭要看
    palapha   

    大佬厉害,但还是不太明白
    DeathMeeting
    OP
      


    palapha 发表于 2023-6-30 21:43
    大佬厉害,但还是不太明白

    哪里看不懂我可以给你解答的
    DeathMeeting
    OP
      


    zhanghong 发表于 2023-6-30 16:23
    太棒了,过程很清楚,很好

    哈哈哈哈哈哈哈 工作习惯 过奖了
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部