爬虫逆向实战(二十八)--某税网第一步登录

news2025/1/18 13:50:06

一、数据接口分析

主页地址:某税网

1、抓包

通过抓包可以发现登录接口是factorAccountLogin
在这里插入图片描述

2、判断是否有加密参数

  1. 请求参数是否加密?
    通过查看载荷模块可以发现有一个datagram 和 一个signature加密参数
    在这里插入图片描述
  2. 请求头是否加密?
    通过查看“标头”模块可以发现,请求头中有DeviceidentynoX-App-ClientidX-Temp-Info三个加密参数
    在这里插入图片描述
  3. 响应是否加密?
    登录失败是无加密,登录成功时datagram是加密参数
  4. cookie是否加密?

二、加密位置定位

1、加密参数以及部分请求头

(1)看启动器

查看启动器发现里面包含异步,所以无法正确找到加密位置
在这里插入图片描述

(2)搜索关键字

通过搜索关键字datagram=可以发现在请求拦截器中会对datagram进行赋值,并且此处还有signature参数以及部分请求头,所以此处大概率是加密位置。
在这里插入图片描述
在此处下断点,发现可以断住,并且生成位置就在上方,所以此处就是加密位置
在这里插入图片描述

2、请求头Deviceidentyno

搜索关键字

通过搜索关键字Deviceidentyno可以找到设置请求头的位置。
在这里插入图片描述

3、响应解密

因为定位到的加密位置是在请求拦截器中,所以解密位置大概率会在响应拦截器中,我们可以在请求拦截器的js文件中搜索interceptors.response就可以找到响应拦截器的位置。并且可以发现,在响应拦截器中确实有解密操作。
在这里插入图片描述

三、扣js代码

1、本地存储

我们在扣js代码时,可以发现网站会从本地缓存中取出一些数据,但是其中只有new_key16clientIdnatureuuid是有值的,其他都是空。同时我们可以看到,网站将new_key16取出的值赋值给了a,然后在下方代码中,又判断a是否为空,如果为空就使用Object(A["b"])()方法生成,所以我们就可以直接将这个生成方法扣出,使用这个方法生成。clientId仔细观察可以发现,这个值是固定不变的,可以写死。所以我们只需要关心natureuuid即可。
在这里插入图片描述
进入控制台的“应用”标签页中的“本地存储空间”,将本地存储全部清除
在这里插入图片描述
然后对localStorage.setItem进行hook
hook代码:

var my_setItem = localStorage.setItem;
localStorage.setItem = function (key, value) {
    if (key == 'natureuuid'){
        debugger
    }
    return my_setItem.call(localStorage, key, value);
};

运行hook代码,再次点击登录,发现可以断住
在这里插入图片描述
接着调试执行,可以发现设置natureuuid的位置,同时可以看出这段代码是在回调中执行的。
在这里插入图片描述
再次观察发包可以发现,网站是请求了一个getPublicKey接口,返回了uuidpublicKey,虽然目前来看我们没有用到publicKey,但是肯定是有用到的地方,所以我们也先保存一下。
在这里插入图片描述

2、请求流程

当我们将本地存储清空之后,再次登录可以发现,网站是发送了三个请求,先请求了getPublicKey和sendSm4这两个接口之后才请求了登录接口。
在这里插入图片描述
所以我们在请求登录之前也需要先请求这两个接口。
观察这两个接口的“载荷”,可以发现这两个接口携带的参数与登录接口是一样的,只不过其中的数据不同,同时,网站在请求前两个接口时,也会经过我们上面定位出来的加密位置,只不过datagram的生成不太一样,前两个接口只是转成了json字符串,只有登录接口才加密。
在这里插入图片描述
在观察前两个接口的发包过程时,可以发现第一个接口getPublicKey的datagram就只是一个空字典,然后转成json字符串。但是,网站在给sendSm4接口发包时,是有数据的,而且还有一个我们不知道的参数secret
在这里插入图片描述
我们通过搜索关键字的方式,搜索secret:就可以找到生成位置了,同时这个参数生成的时候还用到了之前通过请求getPublicKey接口获取到的publicKey
在这里插入图片描述

3、坑

在对这三个请求发包时,使用的new_key16以及deviceIdentyNo的值都要使用同一个。

4、加密算法

通过扣js代码可以发现,网站使用了sm2、sm4以及HmacSHA256三种加密算法,解密时使用的是sm4解密,而且这些算法都是标准算法,所以我们可以直接使用标准模块进行加解密。

四、源代码

JavaScript源码:

const {sm2, sm4} = require("sm-crypto");
const CryptoJS = require("crypto-js");

function func_i(e, t) {
    var n, a, r = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""), i = [];
    if (t = t || r.length,
        e)
        for (n = 0; n < e; n++)
            i[n] = r[0 | Math.random() * t];
    else
        for (i[8] = i[13] = i[18] = i[23] = "-",
                 i[14] = "4",
                 n = 0; n < 36; n++)
            i[n] || (a = 0 | 16 * Math.random(),
                i[n] = r[19 == n ? 3 & a | 8 : a]);
    return i.join("")
}


function object_A_d(e, t) {
    r = sm4.encrypt(e, t);
    return r
}

function object_A_i(e) {
    for (var t = "", n = 0; n < e.length; n++)
        "" === t ? t = e.charCodeAt(n).toString(16) : t += e.charCodeAt(n).toString(16);
    return t
}

function object_A_a(e, t) {
    var n = CryptoJS.HmacSHA256(e, t).toString();
    return n
}

function object_A_e(e, t) {
    r = sm4.decrypt(e, t);
    return r
}

function padZero(num) {
    return num < 10 ? "0" + num : num;
}

var clientId = 's44fftt3bc634tcab4teasbaasba7ft4'

function get_headers(natureuuid, ded) {
    if (!ded) {
        ded = func_i(32)
    }
    var t = {
        headers: {},
    }
    t.headers["deviceIdentyNo"] = ded;
    t.headers["X-APP-CLIENTID"] = clientId
    if (natureuuid) {
        t.headers["X-TEMP-INFO"] = natureuuid
    }
    return [t.headers, ded]
}
var v = 'GwdK^R4q'
function get_params(t_data, is_get_key, g) {
    if (!g) {
        g = func_i(16, 61)
    }
    var currentDate = new Date();
    var formattedDate = currentDate.getFullYear() +
        padZero(currentDate.getMonth() + 1) +
        padZero(currentDate.getDate()) +
        padZero(currentDate.getHours()) +
        padZero(currentDate.getMinutes()) +
        padZero(currentDate.getSeconds());

    c = {}

    p = g.substring(0, 8) + v
    u = ""
    c["zipCode"] = "0"
    if (is_get_key) {
        c["encryptCode"] = "0";
        c.datagram = JSON.stringify(t_data);
    } else {
        f = JSON.stringify(t_data);
        u = object_A_d(f, object_A_i(p));
        c.datagram = u;
        c["encryptCode"] = "2";
    }
    c["timestamp"] = formattedDate
    c["access_token"] = ""
    c["signtype"] = "HMacSHA256"
    c["signature"] = object_A_a(c["zipCode"] + c["encryptCode"] + u + c["timestamp"] + c["signtype"], g)
    return [c, g]
}

function func_l(e, t, a) {
    if (t) {
        var i = sm2.doEncrypt(e, t, a);
        return i
    }
    return ""
}

function get_secret(pubkey, g) {
    new_key16 = g
    secret = func_l(new_key16, pubkey, 1)
    return secret
}

function get_data(g, datagram) {
    var a = g.substring(0, 8) + v;
    return object_A_e(datagram, object_A_i(a))
}

Python源码:

"""
Author:陈帅超
Email:912917367@qq.com
Date: 2023/8/29 16:25
"""
import json

import execjs
import requests


class Spider:
    def __init__(self):
        self.session = requests.session()
        self.session.headers = {
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Authorization": "",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Content-Type": "application/json",
            "Origin": "https://tpass.jiangsu.chinatax.gov.cn:8443",
            "Pragma": "no-cache",
            "Referer": "https://tpass.jiangsu.chinatax.gov.cn:8443/",
            "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/116.0.0.0 Safari/537.36",
            "X-LANG-ID": "null",
            "X-NATURE-IP": "",
            "X-SM4-INFO": "0",
            "X-TICKET-ID": "null",
            "hUid": "",
            "sec-ch-ua": "^\\^Chromium^^;v=^\\^116^^, ^\\^Not)A;Brand^^;v=^\\^24^^, ^\\^Google",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "^\\^Windows^^"
        }
        with open('reverse.js', 'r', encoding='utf-8') as f:
            self.js_obj = execjs.compile(f.read())
        self.uuid = ''
        self.publicKey = ''
        self.g = ''
        self.ded = ''

    def get_public_key(self):
        url = "https://tpass.jiangsu.chinatax.gov.cn:8443/sys-api/v1.0/auth/oauth2/getPublicKey"
        headers2 = self.js_obj.call('get_headers', self.uuid)
        self.ded = headers2[0]
        self.session.headers = headers2[0] | self.session.headers
        data = self.js_obj.call('get_params', {}, True)
        self.g = data[1]
        response = self.session.post(url, json=data[0])
        datagram = json.loads(response.json()['datagram'])
        self.uuid = datagram['uuid']
        self.publicKey = datagram['publicKey']
        print('uuid:', self.uuid)
        print('publicKey:', self.publicKey)

    def send_sm4(self):
        url = "https://tpass.jiangsu.chinatax.gov.cn:8443/sys-api/v1.0/auth/white/sendSm4"
        headers2 = self.js_obj.call('get_headers', self.uuid, self.ded)
        self.session.headers = headers2[0] | self.session.headers
        secret = self.js_obj.call('get_secret', self.publicKey, self.g)
        data = self.js_obj.call('get_params', {'uuid': self.uuid, 'secret': secret}, True, self.g)
        response = self.session.post(url, json=data[0])

        print(response.text)
        print(response)

    def login(self):
        t_data = {
            "client_id": 's44fftt3bc634tcab4teasbaasba7ft4',
            "account": '登录用户名',
            "password": '登录密码',
            "redirect_uri": "https://etax.jiangsu.chinatax.gov.cn/sso/kxLogin/authorize",
            "creditCode": '税号'
        }
        url = "https://tpass.jiangsu.chinatax.gov.cn:8443/sys-api/v1.0/auth/enterprise/quick/factorAccountLogin"
        headers2 = self.js_obj.call('get_headers', self.uuid, self.ded)
        self.session.headers = headers2[0] | self.session.headers
        data = self.js_obj.call('get_params', t_data, False, self.g)
        response = self.session.post(url, json=data[0])

        response_data = self.js_obj.call('get_data', self.g, response.json()['datagram'])
        print(response_data)


if __name__ == '__main__':
    s = Spider()
    s.get_public_key()
    s.send_sm4()
    s.login()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/951666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Flutter】下载安装Flutter并使用学习dart语言

前言 安装flutter, 并使用flutter内置的dartSDK学习使用dart语言。 编辑器&#xff1a; Android Studio fluuter 版本 : flutter_windows_3.13.1 内置dartSDK : 3.1.0 dart路径路径&#xff1a; flutter安装路径\bin\cache\dart-sdk 安装Flutter 下载安装包 flutter下载地址…

QT 界面相关操作

1> 创建自定义类时需要指定父类 2> 第一个界面的相关操作 #include "widget.h" #include<iostream> //printf #include<QDebug> //qDebuf #include<QIcon> //图标的头文件 using namespace std; //coutWidget::Widget(QWidget *…

【注册岩土】Python土力学与基础工程计算.PDF-摩尔-库伦强度理论

8.3 Python求解 Python求解代码如下&#xff1a; 1.import math 2. 3.sigma1 300 # 最大主应力&#xff0c;单位 kPa 4.sigma3 100 # 最小主应力&#xff0c;单位 kPa 5.alpha 30 # m-n面与最小主应力方向夹角&#xff0c;单位度 6. 7.rad_alph…

uniapp的 picker 日期时间选择器

效果图&#xff1a; dateTimePicker.js function withData(param){return param < 10 ? 0 param : param; } function getLoopArray(start,end){var start start || 0;var end end || 1;var array [];for (var i start; i < end; i) {array.push(withData(i))…

C++网狐服务器引入开源日志库

很多人对日志库不以为然&#xff0c;包括网狐这种十几年的公司都不重视&#xff0c;其实日志库记录的东西能在线上出问题时高效解决&#xff0c;特别是别人写的东西&#xff0c;人又走了&#xff0c;出了问题&#xff0c;还可以用日志分析快速解决。要是没有日志记录&#xff0…

【kubernetes系列】Calico原理及配置

概述 Calico是针对容器&#xff0c;虚拟机和基于主机的本机工作负载的开源网络和网络安全解决方案。 Calico支持广泛的平台&#xff0c;包括Kubernetes&#xff0c;OpenShift&#xff0c;Docker EE&#xff0c;OpenStack和裸机服务。 Calico在每个计算节点都利用Linux Kernel实…

TiDB Serverless Branching:通过数据库分支简化应用开发流程

2023 年 7 月 10 日&#xff0c;TiDB Serverless 正式商用。这是一个完全托管的数据库服务平台&#xff08;DBaaS&#xff09;&#xff0c;提供灵活的集群配置和基于用量的付费模式。紧随其后&#xff0c;TiDB Serverless Branching 的测试版也发布了。 TiDB Serverless Branc…

【二等奖方案】大规模金融图数据中异常风险行为模式挖掘赛题「冀科数字」解题思路

第十届CCF大数据与计算智能大赛&#xff08;2022 CCF BDCI&#xff09;已圆满结束&#xff0c;大赛官方竞赛平台DataFountain&#xff08;简称DF平台&#xff09;正在陆续释出各赛题获奖队伍的方案思路&#xff0c;欢迎广大数据科学家交流讨论。 本方案为【大规模金融图数据中…

Java代码审计15之Apache log4j2漏洞

文章目录 1、log4j简介2、复现2.1、高版本测试2.2、测试代码2.3、补充之dns探测2.3.1、rmi、ldap也可以dnslog探测 2.3.2、dnslog外带信息 3、漏洞原理3.1、漏洞的危害大的背景3.2、具体的代码调试 4、靶场测试4.1、dns探测4.2、工具下载与使用4.3、测试 5、bypass 1、log4j简介…

FBX SDK 开发环境配置 visual studio 2022

FBX | Adaptable File Formats for 3D Animation Software | Autodesk. 下载windows的sdk并安装. 创建一个c console 工程 设置include目录 添加预处理宏 FBX_SHARED1 添加fbx sdk lib 目录 添加依赖lib : libfbxsdk-md.lib libxml2-md.lib zlib-md.lib 配置完毕.

C# | DBSCAN聚类算法实现 —— 对直角坐标系中临近点的点进行聚类

C# | DBSCAN聚类算法实现 聚类算法是一种常见的数据分析技术&#xff0c;用于将相似的数据对象归类到同一组或簇中。其中&#xff0c;DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;能够有效…

【算法训练-数组 三】数组中的第K个最大元素(TOPK问题|寻找第K大)

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【寻找第K大】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

第 3 章 栈和队列(顺序栈,算法 3.3)

1. 背景说明&#xff1a; 若迷宫 maze 中存在从入口 start 到出口 end 的通道&#xff0c;则求得一条存放在栈中(从栈底到栈顶)&#xff0c;并返回 TRUE&#xff1b;否则返回 FALSE&#xff0c;注意&#xff0c;该解并非最优解&#xff0c; 最优解需要求得最短路径且可能并非…

基于Googlenet深度学习网络的人脸身份识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..................................................................... % 定义修改的范围 …

IP子网的划分

文章目录 一、子网掩码1. 产生背景2. 定义3. 分类 二、VLSM算法1. 得出下列参数2. 计算划分结果3. 举例子计算 三、常见子网划分对应关系四、练习IP编址题目需求解题1. 192.168.1.100/282. 172.16.0.58/263. 25.83.149.222/254. 100.100.243.18/205. 10.100.100.100/10 首先可以…

Python Qt学习(一)一个简单的JSON数据预览界面

先贴上代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file json_converter.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. …

Python飞机大战小游戏

游戏规则&#xff1a;键盘上下左右键控制飞机移动 游戏展示图片&#xff1a; 源码&#xff1a; 第一个py命名为&#xff1a;plane_main.py import pygamefrom plane_sprites import *class PlaneGame(object):# """飞机大战主游戏"""def __in…

ExpressLRS开源之基本调试数据含义

ExpressLRS开源之基本调试数据含义 1. 源由2. 代码2.1 debugRcvrLinkstats2.2 debugRcvrSignalStats 3. 含义解释3.1 ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset3.2 IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT 4. 总结5. 参考资料 1. 源由 …

详解 ElasticSearch Kibana 配置部署

默认安装部署所在机器允许外网 SSH工具 Putty 链接&#xff1a;https://pan.baidu.com/s/1b6gumtsjL_L64rEsOdhd4A 提取码&#xff1a;lxs9 Winscp 链接&#xff1a;https://pan.baidu.com/s/1tD8_2knvv0EJ5OYvXP6VTg 提取码&#xff1a;lxs9 WinSCP安装直接下一步到完成…

UE 5 GAS 在项目中通过数据初始化

近期&#xff0c;在制作多角色&#xff0c;考虑到角色和角色之间有很多共用的内容&#xff0c;正常项目中的实现的话&#xff0c;会通过数据的方式去实现角色初始化&#xff0c;接下来介绍一下&#xff0c;我的实现方式。 以上是我设置的相应的数据&#xff0c;上面最简单的名…