workminer之dht通信部分

news2024/10/7 6:47:05

workminer是通过SSH爆破传播的挖矿木马,感染后会释放xmrig挖矿程序利用主机的CPU挖取北方门罗币。该样本能够执行特定的指令,指令保存在一个配置文件config中,config文件类似于xml文件,里面有要执行的指令和参数,样本中内嵌了一个config,无攻击指令。该样本通过使用自己扩展的DHT协议来更新config,有两种方式,一是访问8个引导节点(样本内嵌,公开的)加入p2p网络,通过来寻找具有特定前缀id的同伙,来更新config,二是会随机扫描其它IP的UDP端口(IP是随机生成的,端口是一个范围内的随机端口),若扫中其它受害主机,受害主机会返回config,用这种方式来更新config。
workminer属于Mozi僵尸网络组织,主要攻击Iot设备,作者已于2021年被中国警方逮捕,该僵尸网络目前在互联网上还持续活跃。本文主要介绍workminer的dht通信部分,workminer使用go和C语言混合编译,C语言主要用于与同伙节点通信,拉取和更新config。

基础知识一:Linux系统调用

为了识别样本中的socket相关函数,我们需要了解Linux系统调用,尤其是socket相关函数调用的基础知识。
linux系统中使用int 80来调用linux系统api,linux中调用socket相关函数,是通用系统调用sys_socketcall的实现的,该接口的系统调用号为102,函数定义为

#include <sys/socket.h>
int socketcall(int subcall, unsigned long *args);
调用的时候,寄存器eax保存调用号,ebx为第1个参数,ecx为第2个参数,通过eax和ebx就能知道是哪个api
ebx int  subcall
ecx unsigned long *
eax 102
int 0x80

第一个参数subcall要调用的api号,在 /usr/include/linux/net.h中定义,使用find命令找到这个文件

# cat /usr/include/linux/net.h | grep SYS                     
#define SYS_SOCKET      1               /* sys_socket(2)                */
#define SYS_BIND        2               /* sys_bind(2)                  */
#define SYS_CONNECT     3               /* sys_connect(2)               */
#define SYS_LISTEN      4               /* sys_listen(2)                */
#define SYS_ACCEPT      5               /* sys_accept(2)                */
#define SYS_GETSOCKNAME 6               /* sys_getsockname(2)           */
#define SYS_GETPEERNAME 7               /* sys_getpeername(2)           */
#define SYS_SOCKETPAIR  8               /* sys_socketpair(2)            */
#define SYS_SEND        9               /* sys_send(2)                  */
#define SYS_RECV        10              /* sys_recv(2)                  */
#define SYS_SENDTO      11              /* sys_sendto(2)                */
#define SYS_RECVFROM    12              /* sys_recvfrom(2)              */
#define SYS_SHUTDOWN    13              /* sys_shutdown(2)              */
#define SYS_SETSOCKOPT  14              /* sys_setsockopt(2)            */
#define SYS_GETSOCKOPT  15              /* sys_getsockopt(2)            */
#define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
#define SYS_RECVMSG     17              /* sys_recvmsg(2)               */
#define SYS_ACCEPT4     18              /* sys_accept4(2)               */
#define SYS_RECVMMSG    19              /* sys_recvmmsg(2)              */
#define SYS_SENDMMSG    20              /* sys_sendmmsg(2)              */

DHT协议基础

DHT协议是一种BT协议,使用udp来通信,通信内容使用bencode编码。可参考bt协议详解 DHT篇(下) - 蓝猫163 - 博客园 (cnblogs.com)。

DHT协议有以下几种报文

ping

最基础的请求就是ping。这时KPRC协议中的“q”=“ping”。Ping请求包含一个参数id,它是一个20字节的字符串包含了发送者网络字节序的nodeID。对应的ping回复也包含一个参数id,包含了回复者的nodeID。
示例

ping请求={"t":"aa", "y":"q","q":"ping", "a":{"id":"abcdefghij0123456789"}}  

B编码=d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe 
回复={"t":"aa", "y":"r", "r":{"id":"mnopqrstuvwxyz123456"}} 
B编码=d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

find_node

Findnode被用来查找给定ID的node的联系信息。这时KPRC协议中的q=“find_node”。find_node请求包含2个参数,第一个参数是id,包含了请求node的nodeID。第二个参数是target,包含了请求者正在查找的node的nodeID。当一个node接收到了find_node的请求,他应该给出对应的回复,回复中包含2个关键字id和nodes,nodes是一个字符串类型,包含了被请求节点的路由表中最接近目标node的K(8)个最接近的nodes的联系信息
示例

find_node请求={"t":"aa", "y":"q","q":"find_node", "a":{"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}}
B编码=d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe
回复={"t":"aa", "y":"r", "r":{"id":"0123456789abcdefghij", "nodes":"def456..."}}
B编码=d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re

get_peers

这个请求用来表明发出announce_peer请求的node,正在某个端口下载torrent文件。announce_peer包含4个参数。第一个参数是id,包含了请求node的nodeID;第二个参数是info_hash,包含了torrent文件的infohash;第三个参数是port包含了整型的端口号,表明peer在哪个端口下载;第四个参数数是token,这是在之前的get_peers请求中收到的回复中包含的。收到announce_peer请求的node必须检查这个token与之前我们回复给这个节点get_peers的token是否相同。如果相同,那么被请求的节点将记录发送announce_peer节点的IP和请求中包含的port端口号在peer联系信息中对应的infohash下。
这个请求报文本样本没有
其响应报文的处理同find_node报文

announce_peer

这个请求用来表明发出announce_peer请求的node,正在某个端口下载torrent文件。announce_peer包含4个参数。第一个参数是id,包含了请求node的nodeID;第二个参数是info_hash,包含了torrent文件的infohash;第三个参数是port包含了整型的端口号,表明peer在哪个端口下载;第四个参数数是token,这是在之前的get_peers请求中收到的回复中包含的。收到announce_peer请求的node必须检查这个token与之前我们回复给这个节点get_peers的token是否相同。如果相同,那么被请求的节点将记录发送announce_peer节点的IP和请求中包含的port端口号在peer联系信息中对应的infohash下。
这个请求报文本样本没有
不支持这个报文

workminer的DHT通信部分

workminer通过自己改良过的DHT协议来请求和config,下面来介绍workminer的dht通信过程。
首先会生成一个特殊的version,则workminer节点发出的dht报文中都会有这个version字段。version字段共9个字节,前5个字节为1:v43:(31 3A 76 34 3A),后面4个字节中根据下面的规则生成的。
第1个字节是随机产生的,第2个字节是硬编码的0x42或由config文件中[ver]字段指定,第3个字节和第4个字节是通过自定义的校验算法生成的。

下面是抓取的ping包,通过这个特殊的标记,wokerminer在处理接收到的包时就能够识别出哪些包是正常的dht包,哪些包中由同伙发出来的,对于正常的dht协议的请求和响应包,走正常的处理流程,对于同伙的包(ping和find_node),就会交换config。

上面这个计算校验和的算法是识别同伙的关键,如下代码,若结果为0表示是同伙的包,若不是0则是正常的dht数据包。

// 根据version字段来判断是同伙发来的包
int  GenCheckSum_82AAB68(unsigned __int16 a1, char *buf_a2, unsigned int buflen_a3)
{
    char j; // [esp+5h] [ebp-Bh]
    unsigned int i; // [esp+Ch] [ebp-4h]

    for ( i = 0; i < buflen_a3; ++i )
    {
        a1 ^= (unsigned __int8)buf_a2[i] << 8;
        for ( j = 8; j; --j )
        {
            if ( (a1 & 0x8000) != 0 )
                a1 = (2 * a1) ^ 0x8005;
            else
                a1 *= 2;
        }
    }
    return a1;

}
int main(){

    char version[] = { 0x31,0x3a ,0x76 ,0x34 ,0x3a ,0x26 ,0x42 ,0x53 ,0x77};
    int checksum = GenCheckSum_82AAB68(0,version,9);
    if(checksum == 0){
        puts("Mozi pkt");
    }
    else{
        puts("Normal dht pkt");
    }
    return 0;
}

从下列中随机选择一个端口,若端口为0,则取random()%64510+1024,监听这个udp端口。

port_list[28] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,8080,8000,1900,1434,1027,6881,4000
30301,5353,11211,8082,8081,8083,5060]

为这UDP端口添加iptables规则。

使用异或的方式解密了两个公钥,异或使用密钥为
4E 66 5A 8F 80 C8 AC 23 8D AC 47 06 D5 4F 6F 7E
将内嵌在样本的config提取出来,共624字节,前524字节为加密的config内容,后96字节为文件的签名。使用第1个公钥来对加密的config验证签名。若验证签名通过,则使用go语言来解析解密后的config,执行config中的指令。若config中含有[ver]标签,使用ver标签的值来重新计算数据包version字段。
公钥为

第一个公钥 用于验证config前528字节的完整性
02 d5 d5 e7 41 ee dc c8 10 6d 2f 48 0d 04 12 21 
27 39 c7 45 0d 2a d1 40 72 01 d1 8b cd c4 16 65 
76 57 c1 9d e9 bb 05 0d 3b cf 6e 70 79 60 f1 ea 
ef

第二个公钥 用于验证config前428字节的完整性
02 c0 a1 43 78 53 be 3c c4 c8 0a 29 e9 58 bf c6
a7 1b 7e ab 72 15 1d 64 64 98 95 c4 6a 48 c3 2d
6c 39 82 1d 7e 25 f3 80 44 f7 2d 10 6b cb 2f 09 
c6

解密后的config
[ss]ssh[/ss][cpu].x[/cpu][hp]88888888[/hp]

构造自身nodeid,nodeid有20个字节,有以下几种可能
一 1/1000的可能 使用字符串888888d1:ad2:id20:作为前缀,即38 38 38 38 38 38 64 31 3A 61 64 32 3A 69 64 32 30 3A xx xx,后两个字节为随机值。
二 49/1000的可能,使用888888作为前缀,即38 38 38 38 38 38 xx xx xx xx xx xx xx xx xx xx xx xx xx xx,后面12个字节为随机值
三 950/1000的可能,使用随机生成的nodeid.

接着使用上面的构造的selfNodeId,向内置的8个引导节点发送ping请求。TransactionId使用6E 70 00 00

router.bittorrent.com:6881 
bttracker.debian.org:6881
router.utorrent.com:6881
dht.transmissionbt.com:6881
212.129.33.59:6881
82.221.103.244:6881
130.239.18.159:6881
87.98.162.88:6881


使用wireshark抓包可以看到包的内容

这个包的含义如下,

请求参数(request arguments)
a:{id:38383838383864313a6164323a696432303a9550}
请求类型(request type)
q:ping
会话Id(Transaction Id)
t:706e0000
版本(Version)
v:1942d177
消息类型(Message Type)q表示请求
y:q

设置一个全局的队列,用来存储的节点信息,这个队列结构如下所示。

struct NODE
{
  char node_id[20];//节点的node_id
  char addr[128];//地址信息 可存储Ipv4和ipv6的sockaddr结构
  int addrlen;//sockaddr结构的长度
};
struct NODE_LIST
{
  int head;//队列头
  int end;//队列尾
  NODE nodelist[64];//队列,队列大小为64
};

下面进入一个死循环,不断的向外发包和处理响应包。
每隔899秒,向内嵌的8个公共节点发送ping请求。
从config中取出[nd]标签的值,这是一个以,分割的列表,如url1,ip,url2,...,向其中的每个地址发送ping请求,使用端口6881,会话id使用6E 70 00 00。(内嵌的config中没有nd标签,不会执行)

每隔299秒,若node_list不为空的话,从其中随机取一个node,发送find_node请求。
find_node消息中的target_node_id使用以下的规则构造,有4种可能。
一是 targetid完全使用随机值,即20个随机的字节
二是 将 123888d1:ad2:id20: 作为target_nodeid的前18个字节,后2个字节随机
三是 以888888作为target_nodeid的前6个字节,后14个字节随机
四是 以888888d1:ad2:id20:作为target_nodeid的前18个字节,后2个字节随机
会话id为6E 66 00 00

构造一段随机长度的buf,长度为从[3,97]中取一个随机数,将第二个字节为0x2e,使用前面的算法计算校验值,将2个字节的校验值添加到buf末尾。

['8080','8000', '1900', '1434', '1027', '6881', '4000', '30301', '5353', '11211', '8082', '8081', '8083', '5060']中随机取一个端口,构造一个随机的IP地址,将上面构造好的数据发出去。执行100次。
当同伙收到这个报文后,会将加密的config发回来,这里将这个报文定义为GET_CONF报文。

每隔599秒,向node_list中所有节点发送一次find_node请求,target_nodeid有两种情况,会话id为6E660000.
一是 以888888d1:ad2:id20:为前缀,后面为随机值
二是 以888888前缀后面为随机值

下面是处理接收到的数据包的逻辑
首先使用select和recvfrom接收udp的包,将dht相关的包中关键字段解析出来,如下图所示。对dht数据包进行解析,对其中的关键的字段提取,并返回数据包的类型,根据这个类型值进入不同的处理逻辑,提取出来的字段dht字段有

version: 可判断是否为同伙的包
transctionid :可判断ping和find_node的响应
nodeid :对方的nodeid
targetid: find_node请求的目标id
nodes :find_node响应的nodes列表


数据的类型有以下几种

enum DHTPktType : int
{
  DHTPktType_OTHER = -1,//其它
  DHTPktType_ERROR = 0,//报错信息
  DHTPktType_RESPONSE,//响应包 包括ping、find_node的响应
  DHTPktType_PING,// ping请求
  DHTPktType_FIND_NODE,// find请求
  DHTPktType_GET_PEERS,//get_peers请求
  DHTPktType_ANNOUNCE_PEER,//annouce_peer 请求
  DHTPktType_MOZI_CNF_REQ,//get_conf请求 即上面的GET_CONF报文
  DHTPktType_MOZI_ENCODING_CNF //接收到对方发来加密的config
};

下面介绍这几种报文的处理逻辑

ping、find_node的响应

若会话id为6E 70 00 00,说明是本机发出去的ping请求的响应包,将对方的nodeid、ip、port添加进入全局队列。
若会话id为6E 66 00 00,说明是本机发出来的find_node请求的响应,将对方的信息加入队列,检查version字段。若不是Mozi节点发来的包,将其中的nodes字段中8个节点加入队列。若是Mozi节点的包,且nodes大小为624,这其实是加密的config,处理这个config。

ping请求

若收到别的节点发来的ping请求,将对方信息加入队列,进行正常的回复。

find_node、get_peers的请求

这两类请求的处理逻辑相同。若是非同伙的包,按照正常的dht协议来处理,从队列中取8个节点信息发给对方。
若是同伙发来的请求,有4/5的概率,会将自身加密的config填充进nodes字段发送给对方。

announce_peer请求

这类请求不支撑,发送一个error信息。

GET_CONF请求

这不是DHT请求,就是前面随机构造的数据包,数据包长度<=99字节,最后两个字段是校验值,当节点收到此请求,会将自身的config发送给对方,大小为624字节。

收到对方的config

若不是DHT报文,且大于99字节,这是别的节点发来的加密的config,处理这个config.

config的处理

对同伙获取的config大小为624字段,其中前528字段是config1,后面96字段是签名信息,使用第1个公钥验证其完整性,
对于config1,取其前428为config2,428到524的96字段为签名信息,使用第2个公钥签证其完整性。
然后对config2进行解密,向对方节点发送一个ping请求,将config文件中的[cpu]、[ss]、[sv]三个标签的值,提取hp字段,这是的nodeid的前缀,提取ver字段,重新计算verison。

cpu 不知道含义
ss 不知道含义
sv 不知道含义
hp nodeid的前缀
ver 这是一个byte值,作为version字段的第二个字节

最后调用go函数main_deal_conf来处理config,提取出下列标签,进而执行不同的操作。

slan 这是个开关变量,作用未知
swan 这是个开关变量,未知
spl 这是一个url,用于下载更新的bash脚本
sdf 格式为"url|filename",会从url中下载文件保存为/tmp/+filename
sud 其中含有一个url,用于更新本地的病毒母体
ssh 其中含有一个url,用于下载bash脚本来执行
sdr 用于下载文件执行
srn 用于执行命令
scount 指向用于回连的url,默认为`http://ia.51.la/go1`,受害者会周期性的访问这个地址,用于便于攻击者知道受害者的信息

IOC

如何快速识别workminer的流量,可以根据下面的特征

正常的dht报文的version字段符合文中的校验算法
nodeid以88888、88888888、888888d1:ad2:id20:开头
会话id中为6E 70 00 00或6E 66 00 00
udp的载荷小于99,符合文中的校验算法
upd的载荷大小为624
有对外随机的udp扫描行为,目标端口为['8080','8000', '1900', '1434', '1027', '6881', '4000', '30301', '5353', '11211', '8082', '8081', '8083', '5060']

访问url
http://ia.51.la/go1

连接下列地址udp
router.bittorrent.com:6881 
bttracker.debian.org:6881
router.utorrent.com:6881
dht.transmissionbt.com:6881
212.129.33.59:6881
82.221.103.244:6881
130.239.18.159:6881
87.98.162.88:6881

访问门罗币矿池
xmr.crypto-pool.fr:6666

扫描TCP以下端口
2222
3389
22222
443
55554
9000
2223
9090
8888
8022
6000
9999
2323
2002
7777
2022
666
444
5555
222
26
2382
830
4118
23
50000

流量中含有
SSH-2.0-Go

总结

workminer的作者使用了一种变形的dht协议来更新config,确认非常聪明,具有很好的隐蔽性。config 文件中有些标签的含义还是没有分析清楚。

参考资料

  • Linux系统调用 int 80h int 0x80_怎么寻找int80指令-CSDN博客
  • Linux system call table 정리(32bit, 64bit) (tistory.com)
  • 深度追踪Mozi僵尸网络:360安全大脑精准溯源,揪出幕后黑手_360社区
  • BitTorrent 分布式散列表(DHT)协议详解 | 寂静花园 (addesp.com)
  • bt协议详解 DHT篇(下) - 蓝猫163 - 博客园 (cnblogs.com)
  • P2P Botnet: Mozi分析报告 (360.com)
  • P2P僵尸网络深度追踪——Mozi(二)二叉树吃瓜记-安全客 - 安全资讯平台 (anquanke.com)
  • 『P2P僵尸网络漏洞研究——mozi』 netgear路由器漏洞复现-安全客 - 安全资讯平台 (anquanke.com)
  • 【转】ECDSA 签名验证原理及C语言实现_ecdsa 嵌入式c语言-CSDN博客

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

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

相关文章

服务注册与发现Eureka、Zookeeper、Consul 三个注册中心的异同点(CAP理论)

Eureka Eureka是由Netflix开源的一个服务注册和发现组件&#xff0c;它主要用于构建高可用、分布式系统的基础设施中。Eureka的服务器端被称为Eureka Server&#xff0c;客户端则是那些需要注册的服务。Eureka具有以下特点&#xff1a; 高可用性&#xff1a;Eureka支持多节点…

小米汽车充电枪继电器信号

继电器型号&#xff1a; 参考链接 小米SU7&#xff0c;便捷充放电枪拆解 (qq.com)https://mp.weixin.qq.com/s?__bizMzU5ODA2NDg4OQ&mid2247486086&idx1&sn0dd4e7c9f7c72d10ea1c9f506faabfcc&chksmfe48a110c93f2806f6e000f6dc6b67569f6e504220bec14654ccce7d…

Linux网络开发基础知识

一个网络服务器的简单实现 项目需求 实现回声服务器的客户端/服务器程序&#xff0c;客户端通过网络连接到服务器&#xff0c;并发送任意一串英文信息&#xff0c;服务器端接收信息后&#xff0c; 将每个字符转换为大写并回送给客户端显示。 eoch_client.c #include <arpa/i…

Android双向认证配置过程

1&#xff08;可以绕过&#xff09;准备过程 为了让这个教程可以一直复用&#xff0c;打算直接写一个双向认证的APP作为素材。 工具&#xff1a; ●protecle&#xff08;签名文件转换&#xff09; ●keytool&#xff08;java自己就有&#xff09; ●openssl&#xff08;apache里…

前端canvas项目实战——在线图文编辑器(九):逻辑画布

目录 前言一、 效果展示二、 实现步骤1. 调整布局&#xff0c;最大化利用屏幕空间2. 添加逻辑画布3. 添加遮罩4. 居中显示逻辑画布5. 一个容易被忽视的bug点 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们实现了一组通用的功能按钮&#xff1a;复制、删除、锁定…

LeetCode-hot100题解—Day5

原题链接&#xff1a;力扣热题-HOT100 我把刷题的顺序调整了一下&#xff0c;所以可以根据题号进行参考&#xff0c;题号和力扣上时对应的&#xff0c;那么接下来就开始刷题之旅吧~ 1-8题见LeetCode-hot100题解—Day1 9-16题见LeetCode-hot100题解—Day2 17-24题见LeetCode-hot…

httpClient提交报文中文乱码

httpClient提交中文乱码&#xff0c;ContentType类型application/json 指定提交参数的编码即可 StringEntity se new StringEntity(paramBody.toJSONString(),"UTF-8");se.setContentType("application/json");context.httpPost.setHeader("Cookie&…

Go-Zero从0到1实现微服务项目开发(二)

前言 书接上回&#xff0c;继续更新GoZero微服务实战系列文章。 上一篇被GoZero作者万总点赞了&#xff0c;更文动力倍增&#xff0c;也建议大家先看巧一篇&#xff0c;欢迎粉丝股东们三连支持一波&#xff1a;Go-zero微服务快速入门和最佳实践&#xff08;一&#xff09; 本…

Windows Server 2022 OVF, updated Apr 2024 (sysin) - VMware 虚拟机模板

Windows Server 2022 OVF, updated Apr 2024 (sysin) - VMware 虚拟机模板 2024 年 4 月版本更新&#xff0c;现在自动运行 sysprep&#xff0c;支持 ESXi Host Client 部署 请访问原文链接&#xff1a;Windows Server 2022 OVF, updated Apr 2024 (sysin) - VMware 虚拟机模…

从Kernel启动到Android系统整个过程源码分析

1、 第一阶段&#xff1a; 对于ARM的处理器&#xff0c;内核第一个启动的文件是arc/arm/kernel下面的head.S文件。当然arc/arm/boot/compress下面也有这个文件&#xff0c;这个文件和上面的文件略有不同&#xff0c;当要生成压缩的内核时zImage时&#xff0c;启动的是后者&…

企业如何保证内部传输文件使用的工具是安全的?

企业内部文件的频繁交换成为了日常运营不可或缺的一环。然而&#xff0c;随着数据量的爆炸式增长和网络攻击手段的日益复杂&#xff0c;内网文件传输的安全隐患也日益凸显&#xff0c;成为企业信息安全的薄弱环节。本文将探讨内网文件传输的安全风险、企业常用的防护措施。 内网…

《Fundamentals of Power Electronics》——Buck、Boost、Buck-Boost三个电路的CCM-DCM工作特性总结

Buck、Boost、Buck-Boost这三个电路的CCM-DCM工作特性总结如下表所示&#xff1a; Buck、Boost、Buck-Boost这三个电路工作在DCM模式下电压传输比的对比图如下所示&#xff1a; 由上图可知&#xff0c;Buck-Boost电路的工作特性是一条斜率为的直线&#xff0c;Buck电路和Boost电…

小长假来临,企业借助巡检系统做好安全巡查工作

节前节后是安全隐患事故多发期&#xff0c;小长假来了&#xff0c;企业面临着员工离岗、生产活动减少等特殊情况&#xff0c;这可能导致一些安全隐患被忽视。因此&#xff0c;借助巡检系统做好全面安全巡查工作显得尤为重要。巡检系统可以帮助企业实现巡检工作的规范化、标准化…

八_实验1:创建 VLAN 和划分端口

1、实验目的 通过本实验可以掌握&#xff1a; VLAN的概念。创建VLAN的方法。把交换机端口划分到VLAN中的方法。 2、实验​​​​​​拓扑 创建 VLAN 和划分端口的实验拓扑如下图所示。 图8-5 创建 VLAN 和划分端口的实验拓扑 3、实验步骤 &#xff08;1&#xff09;实验准…

C++:map和set的封装

关于红黑树的模拟实现&#xff0c;大家不清楚的先去看看博主的博客再来看这篇文章&#xff0c;因为set和map的封装底层都是利用用的红黑树。所以这里不会过多介绍红黑树的相关内容&#xff0c;而更多的是去为了契合STL中的红黑树去进行改造&#xff0c;让封装的set和map能够去复…

第二篇:Python环境搭建:从初学者到专家

Python环境搭建&#xff1a;从初学者到专家 在编程的世界里&#xff0c;准备好一个高效而舒适的开发环境是走向成功的第一步。在这篇博客文章中&#xff0c;我们将一起探索如何为Python编程搭建一个理想的环境。无论你是完全的新手还是希望提升现有的技能&#xff0c;本文都会…

常用图像加密技术-流密码异或加密

异或加密是最常用的一种加密方式&#xff0c;广泛的适用于图像处理领域。这种加密方式依据加密密钥生成伪随机序列与图像的像素值进行异或操作&#xff0c;使得原像素值发生变化&#xff0c;进而使得图像内容发生变化&#xff0c;达到保护图像内容的目的。 该加密方法是以图像…

C语言程序设计(一)

1、指令、程序、软件 2、计算机语言&#xff1a;机器语言、汇编语言、高级语言 高级语言的发展&#xff1a;非结构化语言&#xff08;FORTRAN&#xff09;、结构化语言&#xff08;C语言&#xff09;、面向对象的语言&#xff08;C、面向对象&#xff09; 3、源程序、二进制…

在ubuntu 24.04 上安装vmware workstation 17.5.1

ubuntu安装在新组装的i9 14900机器上&#xff0c;用来学习笨叔的ARM64体系结构编程&#xff0c;也熟悉Linux的用法。但有时候写文档总是不方便&#xff0c;还是需要window来用。因此想在ubuntu 24.04上安装Linux版本的vmware worksation 17.5.1以虚拟机的方式安装windows 11。其…

Kubernetes学习笔记03

第八章、Kubernetes控制器Controller详解 Statefulset Statefulset主要是用来部署有状态应用 对于StatefulSet中的Pod&#xff0c;每个Pod挂载自己独立的存储&#xff0c;如果一个Pod出现故障&#xff0c;从其他节点启动一个同样名字的Pod&#xff0c;要挂载上原来Pod的存储…