【2020-11-26】不扣JS系列之某医保服务平台数据获取

64 篇文章 97 订阅
20 篇文章 18 订阅


前言

地址:aHR0cHM6Ly9mdXd1Lm5oc2EuZ292LmNuL25hdGlvbmFsSGFsbFN0LyMvc2VhcmNoL2RydWctZGlyZWN0b3J5

这个是某个小粉丝私信发的一个网站,过了好久才着手解决,大概看了下,JS加密挺复杂的,零零散散扣了几千行JS还是没扣完整,所以干脆就换个方式,不扣JS了


一、页面分析

1.请求参数加密

主要加密参数是encData和signData,直接搜索一个signData
在这里插入图片描述

找到signData的加密位置,下断点调试一下,并改写成自己的方法

在这里插入图片描述

signData主要加密逻辑在这里

o.doSignature(i, h, {hash: !0})
其中,i='appCode=T98HPCGN5ZVVQBS8LZQNOAEXVI9GYHKQ&data={"drugType":"1","pageNum":"1","pageSize":"10"}&encType=SM4&signType=SM2&timestamp=1606374010&version=1.0.0&key=NMVFVILMKT13GEMD3BKPKCTBOQBPZR2P'
i中的appCode和key是定制,只需改变pageNum、timestamp

在这里插入图片描述

encData请求参数加密位置,然后调试进去找主要加密方法
在这里插入图片描述


这里主要是t参数和返回的请求加密数据A(g(l, u), t).toUpperCase()

其中w函数的加密参数e.data.data && JSON.stringify(e.data.data)如下,请求时只需改变pageNum、pageSize即可
'{"q":"","drugLv":"","dosformName":"","drugType":"1","pageNum":1,"pageSize":10}'

A(g(l, u), t).toUpperCase() 函数中的l、u均为定值,不需要管他

在这里插入图片描述


2.响应参数encData解密

var n = e.from(t.data.data.encData, "hex")
t.data.data.encData 参数为响应的encData加密数据


var i = function(t, n) {
                    var i = s.decrypt(n, t)
                      , r = i[i.length - 1];
                    return i = i.slice(0, i.length - r),
                    e.from(i).toString("utf-8")
                }(g(l, u), n)
i为解密后的数据           

在这里插入图片描述


二、修改JS

分析好了加密参数逻辑后,将他们改写成自己的JS方法

1.请求signData加密

添加如下代码
在这里插入图片描述

2.请求encData加密

添加如下代码
在这里插入图片描述

3.返回encData解密

添加如下代码
在这里插入图片描述


4.使用charles拦截并修改JS

app.bcb0f797.js下载并添加之前说的几个全局变量,使用charles进行拦截
在这里插入图片描述


4.使用Flask+selenium形成自己的加密和解密接口

Flask代码:

import json
import re
from selenium import webdriver
from flask import Flask, request
import requests

options = webdriver.ChromeOptions()
options.add_argument('--headless')  # 开启无界面模式
options.add_argument('--disable-gpu')  # 禁用显卡
driver = webdriver.Chrome(options=options, executable_path='D:\chromedriver\chromedriver.exe')
driver.get('https://fuwu.nhsa.gov.cn/nationalHallSt/#/search/drug-directory')

app = Flask(__name__)
app.debug = False


def get_sign(sign): 
    js = """
        return get_signData('{}');
    """.format(sign)
    decrypt_data = driver.execute_script(js)
    return decrypt_data

def get_enc(enc):
    js = """
        return get_enc('{}');
    """.format(enc)
    decrypt_data = driver.execute_script(js)
    return decrypt_data

def get_data(sign,enc,timestamp):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'contentType': 'application/x-www-form-urlencoded',
        'sec-ch-ua': '"Chromium";v="86", "\\"Not\\\\A;Brand";v="99", "Google Chrome";v="86"',
        'Accept-Language': 'zh-CN,zh;q=0.9',
    }
    data = {"data": {"data": {
        "encData": enc},
        "appCode": "T98HPCGN5ZVVQBS8LZQNOAEXVI9GYHKQ", "version": "1.0.0", "encType": "SM4", "signType": "SM2",
        "timestamp": int(timestamp),
        "signData": sign}}
    response = requests.post('https://fuwu.nhsa.gov.cn/ebus/fuwu/api/nthl/api/drug/searchDrug', headers=headers,data=json.dumps(data), verify=False)
    # print(response.text)
    data = response.json()['data']['data']['encData']
    print(data)
    js = """
        return get_decData('{}');
    """.format(data)
    decrypt_data = driver.execute_script(js)
    return decrypt_data

@app.route('/get_res', methods=['GET'])
def fuwu():
    sign_data = request.args.get("sign")
    enc_data = request.args.get("enc")
    timestamp = re.compile('timestamp=(.*?)&').findall(sign_data)[0]
    sign = get_sign(sign_data) # 药品 'appCode=T98HPCGN5ZVVQBS8LZQNOAEXVI9GYHKQ%26data={"drugType":"1","pageNum":"1","pageSize":"10"}%26encType=SM4%26signType=SM2%26timestamp=1606358425%26version=1.0.0%26key=NMVFVILMKT13GEMD3BKPKCTBOQBPZR2P'
    enc = get_enc(enc_data)    # 药品 '{"q":"","drugLv":"","dosformName":"","drugType":"1","pageNum":1,"pageSize":10}'
    decrypt_data = get_data(sign,enc,timestamp)
    print(sign,enc,timestamp)
    print(decrypt_data)
    return decrypt_data


if __name__ == '__main__':
    app.run()


请求接口代码:

import requests

headers = {
    'sec-ch-ua': '"Chromium";v="86", "\\"Not\\\\A;Brand";v="99", "Google Chrome";v="86"',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Language': 'zh-CN,zh;q=0.9',
}

page = '1'
params = (
    ('sign', 'appCode=T98HPCGN5ZVVQBS8LZQNOAEXVI9GYHKQ&data={"drugType":"1","pageNum":"'+page+'","pageSize":"10"}&encType=SM4&signType=SM2&timestamp=1606358425&version=1.0.0&key=NMVFVILMKT13GEMD3BKPKCTBOQBPZR2P'),
    ('enc', '{"q":"","drugLv":"","dosformName":"","drugType":"1","pageNum":'+page+',"pageSize":10}'),
)

response = requests.get('http://127.0.0.1:5000/get_res', headers=headers, params=params)
print(response.text)
for data in response.json()['list']:
    print(data)


三、结果

网页数据:
在这里插入图片描述
接口数据:
在这里插入图片描述

四、小结

又时候碰到JS加密不一定非要跟他死扣,你可能扣个几小时抠出来,可别人早已经把数据都爬完了,所以这种方式挺适合业务上的跟进,如果是想要学习提高自己还是建议不要用这个方法

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿J~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值