【JS逆向实战-入门篇】某gov网站加密参数分析与Python算法还原

news2024/11/16 5:44:50

文章目录

  • 1. 写在前面
  • 2. 请求分析
  • 3. 断点分析
  • 4. 算法还原

【作者主页】:吴秋霖
【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作!
【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建与开发实战》
还有未来会持续更新的验证码突防、APP逆向、Python领域等一系列文章

1. 写在前面

  这是一个GOV的站,但是可能算是最最最最简单那一梯队级别的!当然我说的只是参数这一块,其他未知的风控套餐也许并未浮现出来,开始本期的参数加密分析~

分析目标

aHR0cDovL3R6eG0uanh6d2Z3dy5nb3YuY24vaWNpdHkvaXByby9vcGVuL3B1YmxpY2l0eQ==


在这里插入图片描述

2. 请求分析

打开网站,F12监听一下请求,正常请求接口返回如下:

在这里插入图片描述

这里使用Replay XHR或者把请求信息Curl到本地都可以,重新构建请求提交一次,可以看到得到响应内容如下,是失败的:

在这里插入图片描述

为什么会失败?问题出现在请求提交的参数中,这些参数每次请求都是动态变化的,我们需要实现数据采集就必须在请求之前把参数值计算出来,再携带参数提交请求,如下所示:

在这里插入图片描述

3. 断点分析

知道上面的参数是请求动态变化的,现在我们需要从JS代码层面去定位到生成参数的核心代码,这里单搜几个参数,会比较麻烦,因为没有什么特征去定位的话,一搜一大堆!

我这里用的XHR断点,断点停住后在当前JS代码中搜索参数,这里搜索参数不能单搜一个s或者t,加一个=,因为在URL中参数必然有赋值操作,代码2000多行,带=参数搜索有20多个,幸运的是翻一下就找到了可疑之处,在此位置打上断点刷新如下所示:

在这里插入图片描述

sig是s参数的值,tkey是o参数的值,t即t参数的值,如下所示:
在这里插入图片描述

4. 算法还原

接下来将主要参数生成的网站内原生JS代码扣了下来,如下:

var curUrl = this.url + "/" + this.action + "/" + type;
if (this.isApiV2) {
    var sig = "";
    var chars = "0123456789abcdef";
    if (!LEx.isNotNull(__signature)) {
        var curTime = parseInt(Math.random() * (9999 - 1000 + 1) + 1000) + "" + Date.parse(new Date());
        sig = chars.charAt(parseInt(Math.random() * (15 - 15 + 1) + 10)) + chars.charAt(curTime.length) + "" + curTime;
    } else {
        sig = __signature;
    }

    var key = "";
    var keyIndex = -1;
    for (var i = 0; i < 6; i++) {
        var c = sig.charAt(keyIndex + 1);
        key += c;
        keyIndex = chars.indexOf(c);
        if (keyIndex < 0 || keyIndex >= sig.length) {
            keyIndex = i;
        }
    }

    var timestamp = parseInt(Math.random() * (9999 - 1000 + 1) + 1000) + "_" + key + "_" + Date.parse(new Date());

    var tkey = "";
    var tkeyIndex = -1;
    for (var i = 0; i < 6; i++) {
        var c = timestamp.charAt(tkeyIndex + 1);
        tkey += c;
        tkeyIndex = chars.indexOf(c);
        if (tkeyIndex < 0 || tkeyIndex >= timestamp.length) {
            tkeyIndex = i;
        }
    }

    var t = timestamp;
    //LEx.azdg.encrypt(timestamp,key);
    t = t.replace(/\+/g, "_");
    curUrl += "?s=" + sig;
    curUrl += "&t=" + t;
    curUrl += "&o=" + tkey;
}

根据上面的JS代码,我们现在需要稍微的做一下修改进行还原!this.isApiV2为true即可!为什么是true,在代码还原跟手补环境中,都是需要分析代码的,可以在控制台或者断点日志处查看某些参数、变量的结果,然后还原替换到代码中,不然大部分JS代码你扣下来都是无法运行的!

if (!LEx.isNotNull(__signature))这里的条件分支可以直接去除,保留下面sig的重新计算代码就可以,修改后代码如下所示:

import random
import time

def generate_key(sig):
    chars = "0123456789abcdef"
    key = ""
    keyIndex = -1

    for _ in range(6):
        c = sig[keyIndex + 1]
        key += c
        keyIndex = chars.index(c) if c in chars else keyIndex
        if keyIndex < 0 or keyIndex >= len(sig):
            keyIndex = _

    return key

def generate_timestamp():
    chars = "0123456789abcdef"
    cur_time = str(int(random.uniform(1000, 9999))) + str(int(time.time()))

    sig = chars[int(random.uniform(10, 15))] + chars[len(cur_time)] + cur_time
    key = generate_key(sig)

    timestamp = str(int(random.uniform(1000, 9999))) + "_" + key + "_" + str(int(time.time()))
    tkey = generate_key(timestamp)

    t = timestamp.replace("+", "_")

    payload = {'s': sig, 't': t, 'o': tkey}
    return payload

if __name__ == "__main__":
    result = generate_timestamp()
    print(result)

我这里的话是使用Python进行还原的,generate_key函数接收一个字符串sig作为参数,表示一个生成的签名。在函数中,使用了一个字符集chars,其中包含了十六进制数字0-9和小写字母a-f

函数迭代了六次,每次都从sig中取一个字符,然后使用该字符的索引生成一个密钥

generate_timestamp函数生成了一个包含签名、时间戳和密钥的字典作为结果!使用random.uniform生成一些随机数和当前时间来构建签名和时间戳

JS与Python代码测试如下所示:

在这里插入图片描述

在这里插入图片描述

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

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

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

相关文章

Unity 观察者模式(实例详解)

文章目录 简介示例1 - 简单的文本更新通知示例2 - 多观察者监听游戏分数变化示例3 - 事件系统实现观察者模式示例4 - 泛型观察者和可序列化的事件系统示例5 - 使用C#委托简化版 简介 在Unity中实现观察者模式&#xff0c;我们可以创建一个Subject&#xff08;目标/主题&#x…

【Vue.js设计与实现】第一篇:框架设计概览-阅读笔记(持续更新)

从高层设计的角度去探讨框架需要关注的问题。 参考&#xff1a;速读《Vue.js 设计与实现》 - 掘金 (juejin.cn) 系列目录&#xff1a; 标题博客第一篇&#xff1a;框架设计概览【Vue.js设计与实现】第一篇&#xff1a;框架设计概览-阅读笔记第二篇&#xff1a;响应系统【Vue.…

代码随想录算法训练营29期|day34 任务以及具体任务

第八章 贪心算法 part03 1005.K次取反后最大化的数组和 class Solution {public int largestSumAfterKNegations(int[] nums, int K) {// 将数组按照绝对值大小从大到小排序&#xff0c;注意要按照绝对值的大小nums IntStream.of(nums).boxed().sorted((o1, o2) -> Math.ab…

c++学习记录 文件操作—文本文件—读文件

#include<iostream> using namespace std; #include<fstream> #include<string>void test01() {//创建流对象ifstream ifs;//打开文件&#xff0c;并且判断是否打开成功ifs.open("test.txt", ios::in);if (!ifs.is_open()){cout << "文…

39种值得关注的利基AI应用【2024】

人工智能非常令人兴奋。 潜在的应用数量如此巨大&#xff0c;而且这个空间正在以光速发展。 由于步伐轻快&#xff0c;听到该技术正在堵塞所有不同的漏洞就像开车穿过乡村小镇向窗外看一样。 你捕捉到了大部分重要的东西&#xff0c;但许多独特的魅力和隐藏的宝石却被忽视了。…

GM/T 0018-2012 设备接口描述笔记

GM/T 0018-2012 设备接口描述笔记 文章目录 GM/T 0018-2012 设备接口描述笔记6. 设备接口描述6.1 密码设备应用接口在公钥密码基础设施应用技术体系框架中的位置6.2 设备管理类函数6.3 密钥管理类函数6.4 非对称算法运算类函数6.5 对称算法运算类函数6.6 杂凑运算类函数6.7 用户…

揭秘 Docker 网络:手动实现 Docker 桥接网络

本文将带领读者探索 Docker 桥接网络模型的内部机制&#xff0c;通过 veth pair、bridge、iptables 等关键技术手动实现 Docker 桥接网络模型&#xff0c;揭示网络背后的运作原理。 如果你对云原生技术充满好奇&#xff0c;想要深入了解更多相关的文章和资讯&#xff0c;欢迎关…

idea用version标签配置版本号报错版本号missing

问题描述&#xff1a; 用<mybatis-plus.version>3.3.2</mybatis-plus.version>配置pom的版本号&#xff0c;报错 dependencies.dependency.version for com.baomidou:mybatis-plus-boot-starter:jar is missing. line 33, column 21详细报错如下&#xff1a; 详…

负载均衡下Webshell连接思路及难点

君衍. 一、应用场景二、环境搭建三、思路以及难点1、查看内部结构2、查看webshell3、使用蚁剑进行连接4、难点1 shell文件上传问题5、难点2 命令执行时飘逸6、难点3 大工具上传失败7、难点4 脚本失效 四、解决方式1、关闭对方节点服务器2、基于IP地址判断是否执行3、脚本实现流…

文献速递:人工智能医学影像分割--- 深度学习分割骨盆骨骼:大规模CT数据集和基线模型

文献速递&#xff1a;人工智能医学影像分割— 深度学习分割骨盆骨骼&#xff1a;大规模CT数据集和基线模型 我们为大家带来人工智能技术在医学影像分割上的应用文献。 人工智能在医学影像分析中发挥着至关重要的作用&#xff0c;尤其体现在图像分割技术上。这项技术的目的是准…

1 月 29日算法练习-二分法

二分法是一种高效的查找方法&#xff0c;它通过将问题的搜索范围一分为二&#xff08;两边具有明显的区别&#xff09;&#xff0c;迭代地缩小搜索范围&#xff0c;直到找到目标或确定目标不存在。 二分法适用于有序数据集合&#xff0c;并且每次迭代可以将搜索范围缩小一半。 …

STL_list

一、有关list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。Ii…

备战蓝桥杯--数据结构及STL应用(基础)

今天轻松一点&#xff0c;讲一讲stl的基本操作吧&#xff01; 首先&#xff0c;让我们一起创建一个vector容器吧&#xff01; #include<bits/stdc.h> using namespace std; struct cocoack{ int coco,ck; } void solve(){vector<cocoack> x;for(int i0;i<5;i){…

负载均衡技术助力企业数字化转型和高可用架构实现

文章目录 什么是高可用架构什么是负载均衡负载均衡设备硬件负载均衡的代表产品软件负载均衡的代表产品 负载均衡基于OSI模型分层负载均衡在网络层负载均衡在传输层负载均衡在应用层 优先考虑负载均衡的场景硬件负载均衡的缺点云负载均衡正在成为最佳选择企业数字化转型对负载均…

Ubuntu 22.04 中文乱码解决方案

sudo apkg-reconfigure locales 按空格键选中

数字图像处理(实践篇)三十六 OpenCV-Python 使用ORB和BFmatcher对两个输入图像的关键点进行匹配实践

目录 一 涉及的函数 二 实践 ORB(Oriented FAST and Rotated BRIEF)是一种特征点检测和描述算法,它结合了FAST关键点检测和BRIEF描述子。ORB算法具有以下优势: ①实时性:能够在实时应用中进行快速的特征点检测和描述。 ②

跟着cherno手搓游戏引擎【14】封装opengl

本节先把代码粘上&#xff0c;后续会慢慢把注释都给加上&#xff0c;先看代码了解个大概&#xff08;待更新&#xff09; 前置&#xff1a; RendererAPI.h: #pragma once namespace YOTO {enum class RendererAPI {None 0,OpenGL1};class Renderer {public:inline static R…

交换排序(快排)

当当当当&#xff01;终于来到了令人激动人心的环节&#xff1a;交换排序&#xff01;在这里&#xff0c;我们将会学习到一个大家经常听到过的名词&#xff1a;快速排序&#xff0c;而我希望通过这篇文章的学习&#xff0c;大家也能够真正的学会快排&#xff01; 交换排序 基本…

SkyWalking+es部署与使用

第一步下载skywalking :http://skywalking.apache.org/downloads/ 第二步下载es:https://www.elastic.co/cn/downloads/elasticsearch 注&#xff1a;skywalking 和es要版本对应&#xff0c;可从下面连接查看版本对应关系&#xff0c;8.5.0为skywalking 版本号 Index of /di…

Scala入门01

Spark入门 1.入门 spark采用Scala语言开发 Spark是用来计算的 Scala掌握&#xff1a;特性&#xff0c;基本操作&#xff0c;集合操作&#xff0c;函数&#xff0c;模式匹配&#xff0c;trait&#xff0c;样例类&#xff0c;actor等内容。 2.内容讲解 2.1 Scala简介 在http…