吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8495|回复: 77
上一主题 下一主题
收起左侧

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

  [复制链接]
跳转到指定楼层
楼主
DeathMeeting 发表于 2023-6-30 13:58 回帖奖励

新人发帖,请多指教

前情提要

最近在研究塔可夫的DMA辅+++助,想要直观显示游戏内各种垃圾的每日平均价格,又不想直接逆向游戏内市场的繁杂逻辑(懒,且并不是要获取实时价格),遂在UC上一通搜索找到了tarkov-market.com这个网站。

想着利用这个网站的数据搞个脚本每天缓存一遍平均价格存储在本地以供使用。

一番摸索发现此网站提供官方API但是要收费,5刀每月,还不能试用。

本着先体验后付费的精神(白嫖),本次逆向就开始了。

正篇

查未公开接口

先进页面,往下滚动发现是滚动刷新,判别是瀑布流加载。

按F12呼出控制台,切换到Network并点上Preserve log和
Disable Cache,然后清空一下刷新页面。

搜索一下12.7的弹药

哦豁,什么都没有,可能是加密了。直接点选XHR。

有点眉目,看看里面啥样

没有验签,舒服!

数据加密了

末尾是=符号,有可能是base64加密

找个在线解密碰碰运气,个人常用:Base64在线加解密

什么鬼,看来是处理过的。也有可能不是base64加密,扒代码!

复制一下链接,不用复制后面的两个参,(已经回返的数据条数和每次返回的数据条数)

请求接口没有验签,不用回溯这个调用逻辑,直接对XHR下断点

搞定

往下滚动网页加载数据,网页断下

还在请求部分,跳出当前函数,Shift+F11,

跳到这里

下面开始看参数(回传的乱码)变化进行单步 F9

  1. 一次F9
  2. 二次F9
  3. 三、四、五次F9
  4. 六次F9
  5. 七次F9

有点东西了,下面的看起来像是处理Json的部分,我们重点看看

把XHR断电移除,在这里下个断

往下滚动网页加载数据,网页断下,这里就是解密的部分

看起来不难,就不扣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 << o
        }
    };
    let n = null;
    try {
        let i = e;
        i = r[s(378)](Dv(i), i[s(383)](r[s(384)](3, 2) - 2)), 
        // 3. r是 {acjba: function(i, o), GAVPm: function(i, o)}, r[s(378)]是 "acjba", i[s(383)]是substring(), r[s(384)]是(i,o){return i<<o},r[s(384)](3, 2) - 2是个固定值=10;
        // 4. Dv(i)这个函数可以看到前面进行了一系列处理,带入一下就是i.substring(...Tv().reverse()[mi(372)](1)); 继续简化;
        // 5. 其中的Tv()是个固定值, 结果为[5, 0, 36]。mi(372)是"slice";
        // 6. 综合一下就是[5, 0, 36].reverse()["slice"](1),输出就是一个列表[0, 5],则Dv(i)=i.substring(0, 5)
        // 7. 则i= r["acjba"](i.substring(0, 5), i.substring(10))。由于r["acjba"]等于拼接两个传入字符串,进一步简化i= i.substring(0, 5) + i.substring(10)
        i = window[km](i), // 2.  window[km]在控制台打一下发现是atob(),不用太纠结看前面的代码;
        n = JSON[s(379)](decodeURIComponent(i)) // 1. s(379)是parse,先使用decodeURIComponent()对i进行解码,然后json解析;
    } catch {}
    return n

至此,已经逆向完成,我们简化一下。

  1. 取得接口返回的Json里面的items字符串e
  2. i = e
  3. i = i.substring(0, 5) + i.substring(10)
  4. i = atob(i)
  5. n = Json.parse(decodeURIComponent(i))

最终的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()

总结

综合来说这个网站难度较低,逆向出了解密代码就可以写个遍历获取所有的数据了,可以设置个计划任务每天跑一遍就可以拿到最新的商品价格以供使用了。

免费评分

参与人数 27吾爱币 +29 热心值 +23 收起 理由
wenhua13 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
chuan9 + 1 + 1 谢谢@Thanks!
maodadayo + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
guzhiduxiu + 1 我很赞同!
winooxx + 1 + 1 我很赞同!
笙若 + 1 + 1 谢谢@Thanks!
doublexixi + 1 我很赞同!
Iamfather + 1 + 1 谢谢@Thanks!
procurve + 1 + 1 谢谢@Thanks!
Pinenut666 + 2 + 1 厉害啊,这个思路很有参考价值,学习了!
Asmcod + 1 + 1 正好有用,我也DMA正需要这个,感谢,接下来可以做价值分界了
4everlove + 1 + 1 谢谢@Thanks!
Charleshzh + 1 + 1 我很赞同!
RippleSky + 1 谢谢@Thanks!
寒尘丶Coldust + 1 + 1 用心讨论,共获提升!
初七的果子狸 + 2 + 1 谢谢@Thanks!
按F进入坦克 + 1 + 1 谢谢@Thanks!
shiquda + 1 + 1 谢谢@Thanks!
sunnylds7 + 1 + 1 热心回复!
下载寂寞 + 2 + 1 我想说的是,作为一个塔科夫老玩家,能嫖你的科技木么。或者做你下线???
北冥鱼 + 2 + 1 我很赞同!
蓝纹鲸 + 1 + 1 改日·学习
ondwww + 1 我很赞同!
叶无道 + 1 + 1 热心回复!
KUBSU + 1 用心讨论,共获提升!
coverme + 1 我很赞同!
wystudio + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
cycle233 发表于 2023-8-26 13:46
用js简化了下加密
推荐
 楼主| DeathMeeting 发表于 2023-7-3 11:12 |楼主
oxding 发表于 2023-7-3 11:03
直接请求api好像会是防爬虫把 这个咋绕过

是的 会校验tls指纹 所以不要用python的request来

使用curl_cffi这个包来请求,这个包就是过tls指纹检测的
沙发
KUBSU 发表于 2023-6-30 16:01
3#
zhanghong 发表于 2023-6-30 16:23
太棒了,过程很清楚,很好
4#
bloy123 发表于 2023-6-30 16:37
这个确实牛逼 但是不会用啊。。。。
5#
u2000 发表于 2023-6-30 16:55
太高端了。。。玩不好啊
6#
GalaWorm 发表于 2023-6-30 17:30
牛逼7u欲哭要看
7#
palapha 发表于 2023-6-30 21:43
大佬厉害,但还是不太明白
8#
 楼主| DeathMeeting 发表于 2023-6-30 22:47 |楼主
palapha 发表于 2023-6-30 21:43
大佬厉害,但还是不太明白

哪里看不懂我可以给你解答的
9#
 楼主| DeathMeeting 发表于 2023-6-30 22:48 |楼主
zhanghong 发表于 2023-6-30 16:23
太棒了,过程很清楚,很好

哈哈哈哈哈哈哈 工作习惯 过奖了
10#
LRking 发表于 2023-7-1 01:08
每天跑一遍全部的信息,不会被注意到吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 18:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表