人均瑞数系列,瑞数 6 代 JS 逆向分析

news2024/10/6 12:32:07

00

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!

前言

K哥往期瑞数相关文章:

  • 人均瑞数系列,瑞数 4 代 JS 逆向分析

  • 人均瑞数系列,瑞数 5 代 JS 逆向分析

  • 转载十一姐优质好文:js逆向思路-区分瑞数vmp/6/5/4/3反爬

上述文章中,详细介绍了瑞数的特征、如何区分不同版本、瑞数的代码结构以及各自的作用,本文就不再赘述了,不了解的同志可以先去看看之前的文章。

Cookie 入口定位

与以往的四代、五代一样,定位 Cookie,首选 Hook,通过 Fiddler 插件、油猴脚本、浏览器插件等方式注入以下 Hook 代码:

(function() {
    var cookieTemp = "";
    Object.defineProperty(document, 'cookie', {
        set: function(val) {
            console.log('Hook捕获到cookie设置->', val);
            debugger;
            cookieTemp = val;
            return val;
        },
        get: function() {
            return cookieTemp;
        }
    });
})();

VM 代码以及 $_ts 变量获取

参考五代文章:人均瑞数系列,瑞数 5 代 JS 逆向分析

流程分析

与五代一致,用本地替换固定一套代码。通过 (947, 1) 定位到加密流程入口,开始进行流程分析,从现在开始只需要 F9 操作,并且做好记录,其中大部分流程与 5 代一致,可以参考之前的文章。下文中不会对流程中的每一步进行讲解,只会记录对结果有影响的关键步骤。

步骤1

这一步调用了一个方法,得到了一个类似时间戳的值,进入方法内部:

01

02

对两个时间戳以及当前时间戳做了计算,记录 _$MM_$En 的值,后续还会用到。

步骤2

这里对两个数组进行了拼接操作,_$4y 为 16 位数组,_$bx 为 4 位数组:

03

先来看 16 位数组 _$4y 的生成,搜索 _$4y =,可以定位到一处:

04

先看参数 _$yx._$N$ 的值,AMEExbhbQVYKGNjj8cTp.A,通过全局搜索可以发现这个值是在 JS 文件中:

05

再看 _$yx,观察它的值,可以发现与 $_ts 一致 ,后续还会有多处会用到 _$yx

06

参数值找到了,还剩方法 _$Vg 。进入方法内部,可以看到它进行了很多运算,这里直接扣下来就行:

07

16 位数组搞定了,还有 4 位数组 _$bx ,同样进行搜索,一共有 6 处,其中 5 处能够比较明显的看出是 _$bx 的生成流程,全部打下断点,首选创建了一个 4 位数组:

08

下面就是对数组的每一位进行了赋值,这段逻辑很简单,但是实现却比较复杂:

var _$3B = _$5W[_$yx._$Go](_$Ke, _$tm);
_$bx[1] = _$3B;  // 102
============================================
var _$I$ = _$5W[_$yx._$OA](_$dk);
_$bx[3] = _$I$;  // 102
============================================
var _$dk = _$5W[_$yx._$Lr]();
_$bx[2] = _$dk;  // 127
============================================
var _$j9 = _$5W[_$yx._$0f](_$jU, _$I$);
_$bx[0] = _$j9;  // 108

首先 _$yx._$xx 返回一个变量名,上文中讲到了 _$yx 就是 $_ts 。然后 _$5W 是一个对象,里面存放着多个方法,根据_$yx._$xx 返回的变量名来调用对应的方法。_$5W 中的方法都有一个特点,就是结构相同,如下:

function _$Vk() {
    var _$pn = [249];
    Array.prototype.push.apply(_$pn, arguments);
    return _$2W.apply(this, _$pn);
}

这里其实不用在意方法内部做了什么,经测试可以发现,方法中的数组如 [249] 与方法最终结果值存在对应关系,我们只需要找到调用的方法中数组值就可以知道方法的返回值,这里直接将关系给出:

valueMap = {
    194: 103,
    274: 103,
    306: 100,
    251: 203,
    247: 0,
    272: 126,
    240: 103,
    290: 225,
    285: 203,
    249: 102,
    283: 102,
    298: 181,
    281: 11,
    256: 224,
    264: 181,
    266: 108,
    268: 240,
    302: 208,
    304: 180,
    308: 127,
    270: 101,
}

_$5W[_$yx._$Go](_$Ke, _$tm) ,这个方法中数组为 [249] ,而 249 对应的值为 102,那么 _$5W[_$yx._$Go](_$Ke, _$tm) 的返回值就是 102

到这里就是 16 位数组和 4 位数组的生成,将它们拼接后得到一个 20 位数组。

步骤3

09

这里对时间戳进行了运算,_$tm 的值为步骤1中时间戳计算的结果 _$I$

步骤4

10

步骤5

11

这里将步骤3、4中的结果存入数组赋值给了 _$xg

步骤6

12

这里将两位数组转为了八位数组,进入 _$CY 方法内部看看,也是一些朴实无华的操作,扣下来即可:

13

步骤7

下面有一段较长的流程,都是在对一些自动化特征进行检测,可以直接跳过:

14

15

步骤8

生成了一个 128 位数组,最终 cookie 也是由这个数组转化得来:

16

步骤9

首先将步骤2中生成的 20 位数组存入 128 位数组:

17

步骤10

这四处值可以固定:

18

19

20

21

步骤11

这里 _$Ke 值为 4 位数组:

22

搜索 _$Ke 可以定位到生成点,由方法 _$Js 生成:

23

进入 _$Js 内部,发现值的生成由 _$Zb 实现:

24

进入 _$Zb,可以发现这行是用于生成 0 - 255 的随机数:

25

那么 4 位数组的生成就解决了,由四个 0 - 255 间的随机数组成。

步骤12

_$g5 为 8 位数组,这个数组的由来比较棘手,先搜索_$g5,一共有四处结果,全部断下:

26

这里可以看到要找的值是 _$zi,但是 _$zi 出现的地方很多,通过搜索定位不到 8 位数组的生成位置,这里只能追栈,回到上一个栈:

27

可以看到 _$pn 中包含了一个字符串 zbOdssUZRkdTixew3tpf4WGN.rNLK_jWMTTqMIafmZV,这个字符串就是八位数组生成的关键值,经测试,这个字符串可以固定。那么 F9 继续往下走:

28

这里会进入一个新分支,而生成的值就是我们要找的八位数组,跟进去:

29

到这里就找到了八位数组的生成点,_$mq 为上文中的字符串,_$gr 会生成随机的 21 位数组,

_$zW 生成最终八位数组:

30

先看 _$gr ,进入该方法,代码如下。

var _$dk = _$Vg(_$2s(_$SK[46]) + _$yx._$1E);
return _$Gi(_$dk);

_$Vg 方法前文中已经讲到了,扣下来即可。前文讲到了,_$yx 就是 $_ts ,因此 _$yx._$1E 的值在网页返回的代码中,需要动态匹配。再看 _$2s,进入该方法:

var _$zi = _$mq % _$SK[83];
var _$uC = _$mq - _$zi;
_$zi = _$cl(_$zi);
_$zi ^= _$yx._$y3;
_$uC += _$zi;
return _$Yv[_$uC];

首先看方法 _$cl,需要关注的值是 _$yx._$O2,动态匹配即可。

var _$dk = [0, 1, _$SK[113], _$SK[11], _$SK[124], _$SK[41]];
return (_$k4 >> _$yx._$O2) | ((_$k4 & _$dk[_$yx._$O2]) << (_$SK[91] - _$yx._$O2));

然后是 _$yx._$y3,同样需要动态匹配。最后是 _$Yv ,这是一个 64 位数组,通过搜索 _$Yv[ 可以定位到它的生成点。

31

_$k4 的值也是网页返回的 JS 代码中的,需动态匹配,_$j9 方法直接扣下来即可。

到这里 _$dk 的值就能拿到了,得到的是一个 16 位数组。还剩 _$Gi,这个方法主要是对数组值进行了一些逻辑操作,缺啥补啥即可。

到这里 21 位数组也得到了,离最终的八位数组还剩 _$zW 方法,代码如下:

var _$dk = _$Vg(_$k4);
var _$jU = new _$35(_$fO);
return _$jU._$ZL(_$dk, true);

_$Vg 讲过了,_$35 中内容比较多,这里不做讲解,缺啥补啥即可。

那么八位数组的生成就结束了。

步骤13

以下四处值可以固定:

32

33

34

35

步骤14

这里将一个八位数组 _$tj 的值添加到了数组中,而这个八位数组就是 步骤6 中生成的八位数组:

36

步骤15

这里将下标 12 的位置空了出来,其余各处值均可固定:

37

38

39

40

在该步骤中,也是对一些环境进行了检测,流程较长,慢慢跟即可。

步骤16

其中 _$rt 固定为 https:443_$wk 方法将字符串转数组,该方法可以直接扣下来:

41

步骤17

这里会进入一个新分支,得到一个固定值,感兴趣的可以跟进去看一下,流程比较长,主要是对 UA 等环境值进行了处理:

42

步骤18

这里对 128 位数组下标 12 的位置做了重新赋值,_$jU 的值为固定值,细心的朋友在前面几个步骤的调试过程中会发现一些 | 运算,如 _$jU |= _$SK[189]; 这些就是在计算 _$jU 的值:

43

进入 _$8c 方法中,代码如下:

[(_$k4 >>> _$SK[162]) & _$SK[4], (_$k4 >>> _$SK[189]) & _$SK[4], (_$k4 >>> _$SK[43]) & _$SK[4], _$k4 & _$SK[4]];

也是在进行一些逻辑运行,这里直接扣下来即可。

步骤19

这里对 128 位数组进行了切割,保留了有值的部分,得到一个 18 位数组:

44

步骤20

这行代码利用了 concatapply 方法将 18 位数组转为了一个一维的大数组:

45

步骤21

这一步会进入一个新分支,得到一个 32 位的数组,跟进去:

46

两个方法 _$BW_$o9_$o9 生成一个随机的 37 位数组,_$BW 生成 32 位数组,先看 _$o9

47

_$o9步骤12中的 _$gr 方法相似,区别在于 _$2s 的参数值以及 _$yx._$BL

var _$dk = _$Vg(_$2s(_$SK[66]) + _$yx._$BL);
_$sP(_$SK[152], _$dk.length !== _$SK[173]);
return _$Gi(_$dk);

然后看 _$BW ,在步骤12中提到了一个方法_$35,在扣 _$35 时也会遇到 _$BW,这里就单独的讲一下_$BW

48

将代码整理一下,如下:

function _$BW(_$k4) {
    var _$dk = _$k4.slice(0);
    if (_$dk.length < 5) {
        return;
    }
    var _$jU = _$dk.pop();
    var _$I$ = 0
    , _$IM = _$dk.length;
    while (_$I$ < _$IM) {
        _$dk[_$I$++] ^= _$jU;
    }
    var _$j9 = _$dk.length - 4;
    var _$Ff = _$PO() - _$0f(_$dk.slice(_$j9))[0];
    if (_$Ff > _$rT) {
        if (_$Ff > 255) {
            _$rT = 255;
        } else {
            _$rT = _$Ff;
        }
    }
    _$dk = _$dk.slice(0, _$j9);
    var _$df = parseFloat("11.678");
    var _$52 = Math.floor(Math.log(_$Ff / _$df + Math.floor("1.234")));
    var _$zi = _$dk.length;
    var _$Pa = _$yx._$AX[_$ic];
    _$I$ = 0;
    while (_$I$ < _$zi) {
        _$dk[_$I$] = _$52 | (_$dk[_$I$++] ^ _$Pa);
    }
    _$Db(_$SK[43], _$52);
    return _$dk;
}

可以发现关键点有三处,_$PO_$0f_$yx._$AX

_$PO 返回当前时间戳(秒)的四舍五入整数值。_$0f 方法则是数组进行转换,其中涉及到一些逻辑运算,可以直接扣下来。_$yx._$AX 不用多说,需动态匹配。

这里就得到了一个 32 位数组,但是该分支还没有结束,继续往下走。

下面又对生成的 32 位数组进行了处理,得到一个 16 位数组,两个方法 _$aT_$9J

49

_$aT 代码整理后如下,直接用即可:

function _$aT(_$k4) {
    var _$dk = _$k4.slice(0, 16);
    var _$jU, _$I$ = 0, _$IM;
    _$IM = _$dk.length;
    while (_$I$ < _$IM) {
        _$jU = Math.abs(_$dk[_$I$]);
        _$dk[_$I$++] = _$jU > 256 ? 256 : _$jU;
    }
    return _$dk;
}

_$9J 代码整理后如下,有一个_$4c 方法需注意,也是缺少补啥:

function _$9J() {
    var _$dk = new _$4c();
    for (var _$jU = 0; _$jU < arguments.length; _$jU++) {
        _$dk._$1l(arguments[_$jU]);
    }
    return _$dk._$Dt().slice(0, 16);
}

16 位数组跟完后继续往下走,会生成另一个 16位数组,不过这个就比较简单了,_$9J_$BW_$gr 在前文都已经提到了:

50

继续往下走,会到一个for循环里面,这里对上面生成的 32 位数组以及 16 位数组进行处理,生成一个32 位数组:

51

52

到这里该分支就结束了,最终得到了32 位数组。

步骤22

下面主要是对时间戳进行了一些处理,涉及到的时间戳都来自于步骤1中:

53

54

55

56

这里通过时间戳计算得到了四个值, [1695610803, 1695611070, 394, -901278768],下面又将这四个值转成了一个 16 位的数组,_$CY 方法在上文中也提到了:

57

步骤23

这里对上一步中生成的数组进行了位异或操作:

58

在这里就生成了最终cookie的一部分,_$52 是上面处理后的 16 位数组,方法 _$Cj前面没有遇到,这里直接扣下来即可:

59

这里也是将瑞数的标识加上了,那么到这里 173cookie 的第一部分就出来了:

60

步骤24

这里又进到了一个新分支:

61

首先取了一个值,也是需要动态匹配的:

62

然后将该值拼接到了一个数组 _$r3 后面,_$r3 的值就是 步骤2018 位数组合并成的新数组:

63

这里将数组转成了一串数字:

64

进入方法_$hM 内部,主要涉及到了一个256 位数组 _$yx._$4y,这个值可以直接固定,整理代码如下:

function _$hM(_$k4) {
    if (typeof _$k4 === _$A9(_$PM[7]))
        _$k4 = _$wk(_$k4);
    var _$dk = _$yx._$4y || (_$yx._$4y = _$iV());
    var _$jU = -1
    , _$I$ = _$k4.length;
    for (var _$IM = 0; _$IM < _$I$; ) {
        _$jU = (_$jU >>> -1) ^ _$dk[(_$jU ^ _$k4[_$IM++]) & 255];
    }
    return (_$jU ^ -1) >>> 0;
}

这里对那串数字进行了转换,得到了一个四位数组,_$8c 上文已经提到了:

65

到这里该分支就结束了,得到了四位数组。

步骤25

这里将四位数组与 _$r3 进行了拼接:

66

_$dk步骤21 中的 32 位数组,_$Cj 上文提到了,那么还剩 _$o$,也是缺啥补啥即可:

67

到这里 173cookie 的第二部分就出来了,最后将两部分拼接就得到了最终的 173cookie

68

至此,逆向流程结束。

动态匹配

六代与五代最大的区别应该就是动态值的匹配方式发生了变化。数据匹配一般有两种方案,正则和AST,这里推荐正则。

步骤2 中的四位数组为例:

var _$3B = _$5W[_$yx._$Go](_$Ke, _$tm);
var _$I$ = _$5W[_$yx._$OA](_$dk);
var _$dk = _$5W[_$yx._$Lr]();
var _$j9 = _$5W[_$yx._$0f](_$jU, _$I$);

前面已经讲到了 _$3B 值与所引用的方法内部的一位数组存在映射关系,想要拿到值就需要找到对应的方法。已知 _$5W 是一个对象,里面包含所有方法,_$yx._$Go 返回一个字符串,根据返回的字符串来引用方法,得到结果。那么首先要定位 _$5W ,因为代码是动态的,每一次这个包含方法的对象名都不一样,所以这里就需要找到一个固定的关键字来进行定位。这里可以用 842, 来找到 _$5W。定位到 _$5W 后就可以通过 _$5W[ 来匹配四个索引:

69

这里_$yx._$Go 的值为 _$ym,对应的方法为_$3$。那么就需要找到 _$ym_$3$ 是怎么映射起来的:

70

通过搜索 ._$ym 可以定位到,同理 _$yx._$OA 的值为 _$xy ,也可以通过这个方法来定位到方法名:

71

72

方法名找到后可以通过 function 方法名 来进行定位:

73

梳理一下流程:

  1. 通过842来匹配对象名
  2. 通过对象名来匹配四个索引名(_$yx._$Go
  3. 根据 KaTeX parse error: Expected group after '_' at position 12: _ts 拿到索引值(`_̲ym`)
  4. 通过.索引值 (._$ym) 来匹配到真实方法名
  5. 通过 function 方法名 匹配一位数组
  6. 根据数组值拿到方法返回值

通过以上流程就能得到四位数组。

结果验证

74

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

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

相关文章

“时尚设计 时尚原创”首届广州(三元里)时尚设计大赛正式起航

10月18日上午&#xff0c;由广州市商务局、广州市工业和信息化局、白云区人民政府指导&#xff0c;白云区科技工业商务和信息化局、白云区三元里街道办事处主办&#xff0c;广东省皮具商会、三元里街工商业联合会承办&#xff0c;白云世界皮具贸易中心作为执行单位的首届广州(三…

免费高清壁纸下载(静态和动态壁纸)

一、网址下载&#xff08;静态壁纸&#xff09; 高清图片直接另存为就可以了。然后在电脑空白处右键——个性化设置即可替换壁纸。 ①网址&#xff1a;https://www.hippopx.com ②极简壁纸&#xff1a;https://bz.zzzmh.cn/index ③彼岸图网&#xff1a;http://pic.netbian…

大模型基础——大模型范式

大模型背后的范式 整个预训练语言模型的使用范式&#xff1a; 对于预训练模型&#xff0c;最核心的要素是从无标注的数据中去学习&#xff0c;通过自监督的一些任务去做预训练&#xff0c;得到丰富的知识。在具体的应用中&#xff0c;会引入一些任务相关的数据&#xff0c;去调…

Leetcode—2525.根据规则将箱子分类【简单】

2023每日刷题&#xff08;五&#xff09; Leetcode—2525.根据规则将箱子分类 实现代码 char * categorizeBox(int length, int width, int height, int mass){long long volume;long long len (long long)length;long long wid (long long)width;long long heig (long lo…

十八、字符串(2)

本章概要 格式化输出 printf()Systen.out.format()Formatter 类格式化修饰符Formatter 转换String.format() 一个十六进制转储&#xff08;dump&#xff09;工具 格式化输出 在长久的等待之后&#xff0c;Java SE5 终于推出了 C 语言中 printf() 风格的格式化输出这一功能…

VFP GRID每行BLOB显示图片,简单几行代码就完成啦

不止一位狐友问我&#xff0c;想在表格里面显示图片&#xff0c;于是我想了想&#xff0c;满足狐友们的期望&#xff0c;升级了一个框架控件&#xff0c;再来个超容易的教程。 一、拖入一个表单 二、删除自动生成的TEXTBOX1 选中表格&#xff0c;右键->编辑 &#xff0c;点击…

Kibana Discover数据查询

步骤1&#xff1a;打开管理页面(Management) 步骤2&#xff1a; 因为前面的章节导入航班数据的时候&#xff0c;自动创建了一个名字叫kibana_sample_data_flights的航班数据索引&#xff0c;如果我们只想搜索kibana_sample_data_flights索引的数据&#xff0c;则不需要通配符&…

Mysql数据库表操作--存储

建表&#xff1a; 插入上面的数据&#xff1a; 1、创建一个可以统计表格内记录条数的存储函数 &#xff0c;函数名为count_sch() 2、创建一个存储过程avg_sal&#xff0c;有3个参数&#xff0c;分别是deptno&#xff0c;job&#xff0c;接收平均工资(out);功能查询employees表的…

哈希表超详解

目录 哈希表 概念 冲突-概念 冲突-避免 冲突-避免-哈希函数设计 冲突-避免-负载因子的调节 冲突-解决-闭散列 冲突-解决-开散列 哈希桶的实现 性能分析 java和类集的关系 哈希表 概念 顺序结构及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应关系&#xf…

不做技术不会管理,测试人还有这个职位可以进阶

之前我们讲过&#xff0c;测试工程师的4层技术发展路线都需要掌握哪些技能。学而优则仕&#xff0c;今天我们来说说如果想做某个行业的专家应该掌握哪些技能。 如果你对测试技术不感兴趣&#xff0c;但对某领域的业务兴趣浓厚&#xff0c;可以考虑行业专家路线。 由于测试工程…

python单元测试框架(继承、unittest参数化、断言、测试报告)

一、继承 继承能解决什么问题&#xff1f; unittest每个模块都要用到前提条件以及清理&#xff0c;如果有上百个模块&#xff0c;我们要改域名和浏览器&#xff0c;就会工作量很大特别麻烦&#xff0c;这时我们可以用继承的思想只用改一次 我们可以将前提和清理提出来单独放…

日志分析系统——ELK

目录 一、ELK概述 ELK的组成 1、ElasticSearch 2、Logstash 3、Kiabana 完整日志采集系统基本特征 ELK的工作原理 二、ELK的部署 1、环境准备 2、部署ElasticSearch软件 3、安装Elasticsearch-head插件 4、Logstash部署 5、Kibana部署 三、FilebeatELK部署 1、安…

python基础教程:递归函数教程

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 1.递归的定义&#xff1a; 在函数内部直接或者间接调用函数本身 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资…

数据科学中常用的应用统计知识

随着大数据算法技术发展&#xff0c;数据算法越来越倾向机器学习和深度学习相关的算法技术&#xff0c;概率论和应用统计 等传统的技术貌似用的并不是很多了&#xff0c;但实则不然&#xff0c;在数据科学工作&#xff0c;还是会经常需要应用统计概率相关知识解决一些数据问题&…

Autosar诊断实战系列25-UDS 0x27服务相关问题思考

本文框架 前言0x27服务几个相关问题1. 安全访问种子的随机数能不能是全0?2. 安全级别之间是否有联系?是怎么确定的?3. 安全访问错误计数器具体变化策略?前言 在本系列笔者将结合工作中对诊断实战部分的应用经验进一步介绍常用UDS服务的进一步探讨及开发中注意事项, Dem/D…

如何使用 AI 快速学习新技术?

大家好&#xff0c;我是木川 当今&#xff0c;技术的快速发展势不可挡。无论您是初学者还是专业人士&#xff0c;学习新技术都是不可或缺的。 在没有 AI 的时代&#xff0c;我们如何学习新技术&#xff1f;而当 AI 出现后&#xff0c;我们如何更高效地掌握新技术呢&#xff1f;…

线性代数中涉及到的matlab命令-第三章:矩阵的初等变换及线性方程组

目录 1&#xff0c;矩阵的初等变换 1.1&#xff0c;初等变换 1.2&#xff0c;增广矩阵 ​1.3&#xff0c;定义和性质 1.4&#xff0c;行阶梯型矩阵、行最简型矩阵 1.5&#xff0c;标准形矩阵 1.6&#xff0c;矩阵初等变换的性质 2&#xff0c;矩阵的秩 3&#xff…

微信小程序6

一、什么是后台交互&#xff1f; 在小程序中&#xff0c;与后台交互指的是小程序前端与后台服务器之间的数据通信和请求处理过程。通过与后台交互&#xff0c;小程序能够获取服务器端的数据、上传用户数据、发送请求等。 与后台交互可以通过以下方式实现&#xff1a; 发起网络请…

黑客技术(自学方法)——网络安全技术

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…

腾讯地图基本使用(撒点位,点位点击,弹框等...功能) 搭配Vue3

腾讯地图的基础注册账号 展示地图等基础功能在专栏的上一篇内容 大家有兴趣可以去看一看 今天说的是腾讯地图的在稍微一点的基础操作 话不多说 直接上代码 var marker ref(null) var map var center ref(null) // 地图初始化 const initMap () > {//定义地图中心点坐标…