【工具】AFL+Unicorn|二进制程序模糊测试工具 AFL 和 Unicorn 的前世今生、安装以及 Python 使用实例

文章目录

  • 【工具】AFL+Unicorn|二进制程序模糊测试基础工具(AFL+Unicorn)
    • 写在最前
    • 1. 系统环境
    • 2. 软件版本
    • 3. 背景知识
      • 3.1 AFL vs AFLplusplus
      • 3.2 QEMU vs Unicorn
      • 3.3 Unicorn vs UnicornAFL
    • 4. 工具安装
      • 4.1 Ubuntu18
      • 4.2 Ubuntu 20~22
      • 4.3 收尾
    • 5. Python 测试用例简单讲解
      • 5.1 复杂使用示例
      • 5.2 官方使用示例

【工具】AFL+Unicorn|二进制程序模糊测试基础工具(AFL+Unicorn)

写在最前

这篇文章参与华中大开源俱乐部开源工坊的“模糊测试理论与工具实践”分享,关于挖掘二进制程序漏洞。本篇没讲太技术细节的东西,就是简单介绍下工具的使用方式,便于分享后给同学们进行查漏补缺。【但我相信这种详细程度估计也是博客里罕见的了orz】
改天简单做个视频更清晰些,到时贴这里,关注更新。

1. 系统环境

  • 系统:Linux,Ubuntu 18~22。

官方开发的 AFL 都是在 Linux 平台上使用的,
官方给的编译脚本都是 sh 格式的。

至于 Unicorn,它有 Python 版本的 API,其实应该是可以在 Windows 下使用的,但我不推荐这种使用方法,因为它也更新的很快。如果要从源码安装的话,要装 cmake 去编译它,Windows 下挑一个 cmake 版本麻烦太多了。

2. 软件版本

  • AFLPlusplus:Release v4.20c.tar.gz 【2024年4月13日发布】
  • UnicornAFL:AFLPlusplus 的对应版本,写在 AFLplusplus/unicorn_mode/UNICORNAFL_VERSION 里,这个版本对应的是 commit id 63aab0f。

3. 背景知识

如果对模糊测试的工作流程都不太熟的话,建议去搜一搜更基础的文章先,比如 AFL-FUZZ使用笔记(1),这篇文章开头的简介就还不错,我直接搬过来了【官方教程也都很详细只不过是英文的,接下来会继续介绍官方仓库之间的关系,所以看完简介就可以往后面继续看了、不用再重新找官方仓库了、我担心你们找偏了、因为我就找偏过】:

简单来说,模糊测试就是字面的意思,在测试一个程序的时候,把模糊化的数据批量喂给程序,然后等程序运行结束得到结果。被模糊化的数据就叫做输入文件,是初始测试集;已经模糊化了的数据,就叫做输入队列,这个模糊过程常常被叫做“按一定的策略进行突变“。

在这里插入图片描述

3.1 AFL vs AFLplusplus

AFL 是谷歌开发的一个2024年3月22号被归档了的一个开源的覆盖率引导的模糊测试器,

在这里插入图片描述

在 AFL 的基础上,衍生出来了一大堆的优秀的其他模糊测试器。
其中发展的最好的是 AFL++ 这个仓库:

在这里插入图片描述

AFL 这个工具,它的原理是对原来的二进制程序进行插桩,然后动态执行原有的二进制程序,所以它必须得有能够运行原来的二进制程序的结构的模式。里面常用的两个模式是 qemu 模式和 unicorn 模式。

3.2 QEMU vs Unicorn

众所周知,QEMU 是一个仿真器,在我们平时的网络攻防实践课程中,总是会用到这个仿真器,用过的都会觉得它是通过命令行使用的,一点都不好用(小声)

🦄 Unicorn 基于 qemu,但它是一个仿真器框架,而不是仿真器。它摘除了外设、中断等仿真时容易出错的部分,只保留了指令仿真的部分,并增加了许多便利的 Hook 函数,还把这些函数都写成了 Python 或者 c 语言的形式,方便调用。也就是说,qemu 是下图结构,而 unicorn 则是只保留了红色框那一部分【下图来源于 unicorn 的 blackct 的 PPT】。

在这里插入图片描述

那么问题来了,它把中断和外设这些都摘除了,那遇到有这些内容的二进制程序,它怎么保证它能正常的仿真呢?没错,它不能保证,要求用户自己实现。

❓ 到这,我有一个朋友就想问了,为什么这种要求用户重新实现一遍部分内容的框架,还有生存的空间呢?

主要原因是原来的实现实在是太不统一了,非常的麻烦,每新增一种外设,都要在 qemu 里定制化添加代码;许多研究人员试图通过一些模型,让外设的仿真变成一劳永逸的事情,所以这个框架的出现,也让这个事情能够有更加灵活的解决办法;但是它把中断给机制摘除了,这个我也不太理解为什么,巨!不!方!便!【我怀疑是他们还没有找到通用的加中断的方式,实现不了就删了】

3.3 Unicorn vs UnicornAFL

Unicorn 想和 AFL 结合,是需要通过 UnicornAFL 的。就像用 afl 直接测试 Python 的代码,也有个 Python-afl 库一样。

这个 UnicornAFL,就说来话长了。众所周知,AFL 在飞快更新,Unicorn 作为新兴的库也在飞快更新,甚至持续有版本的迭代,这就导致 UnicornAFL 作为它俩的桥梁也要飞快更新🚀。

AFL 在更新,AFLplusplus 更新更快;AFL 不更新了,AFLplusplus 还在更新。好几年前,谁会想到 AFL++ 才是现在的主流呢?所以最开始将 AFL 与 Unicorn 相结合的人他是基于 AFL 原版开发的,为了保证他的代码的不用维护性😂(这事儿得怪 AFL 官方始终不支持 unicorn_mode),它甚至是针对 AFL 和 Unicorn 的特定旧版本开发的,他的仓库是 afl-unicorn:https://github.com/Battelle/afl-unicorn。它基于的版本在现在的 afl 的官方仓库里面,甚至已经消失了,但令人啧啧称奇的是,只要找到那个版本的 AFL,这个仓库已经 7 年了但真的能用,甚至只需要改个版本号和行数就能继续兼容 Unicorn 1 的最高版本 Unicorn 1.0.3。

⭐afl-unicorn 仓库的原理是,给 unicorn 打 patch,给它加个接口能与 AFL 进行交互。所以 unicorn 一更新,它这个 patch 的行数也得更新,不然用不了。这个仓库的好处是只要重新编译 unicorn 就可以,单纯多个接口,不需要引入其他的编译流程。

在这里插入图片描述

AFLplusplus 官方支持 Unicorn_mode。定睛一看,对于 unicorn 1.x 版本来说,它的 unicornafl 1.x 仓库就是 afl-unicorn 演变而来的,没太大区别,就是会在 AFLplusplus/unicorn_mode 文件夹下多加个版本号而已。

⭐unicornafl 2.x 就不一样了,unicorn 2.x 的编译方式从原来的 make 改成了 cmake,原来的被 patch 的文件都不知道挪到哪里去了,可能是因为每次两边任一有更新 unicornafl 就要更新 patch,开发者也乏了,就额外写了更通用的 unicornafl,也开放 python 和 c 语言版本的接口。unicornafl 不对原有的 unicorn 打 patch 并重新编译,而是把与 afl 交互的部分挪到了 unicornafl 库中,分开编译。

在这里插入图片描述

❓ 看到这里,我有一个朋友就要问了:交互部分分开,那不是会增加调用的开销吗?直接编译进去,肯定开销更小啊,模糊测试这么需要性能,怎么能用 unicornafl 呢?

没错,我也有这个疑问,但是开发者告诉我,这点东西差别不大,赶紧换到 unicorn2,unicorn2 更快更强。
经过友好的交流之后,我相信他肯定不至于骗我。

与开发者友好的交流的 issue:https://github.com/AFLplusplus/unicornafl/issues/20

在这里插入图片描述

在这里插入图片描述
其实不是我想评估 是老师问我有没有性能差距

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4. 工具安装

参考:

  1. https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/INSTALL.md,如果安装遇到问题,请直接阅读官方文档。以下安装是省流版。
  2. https://github.com/unicorn-engine/unicorn/blob/master/docs/COMPILE.md,这是 unicorn 的编译官方教程,如果 unicorn 编译不通过,请进一步结合阅读官方文档。以下编译都是省流版。

这个工具在安装的时候,c 语言的 so 文件依赖可能会安装的有点问题,所以可以重新 make install 一下,和官方的教程不大一样。
afl++ 更新的太快,我怕这个教程在以后会失效。所以以下安装脚本均是针对特定版本安装。如果需要安装最新版本,请把下面的安装脚本的 wget 改回 git clone。

4.1 Ubuntu18

完整安装脚本可以参考我们已经开发好的工具的 AFL 安装部分:https://github.com/IoTS-P/SEmu-Fuzz/blob/main/install_local_ubuntu18.sh

Ubuntu 18的 llvm 版本比较低,所以它需要重新安装一下相关的东西。官方教程并没有提太多,里面也很有可能会出现许多问题,我直接把能装好的安装流程贴上来,如果有需要优先参考下文吧:

# fix cmake
# CMake 3.13.4 or higher is required to build LLVM-13 from source.
# Ubuntu 18.04 comes with cmake 3.10.2
# Install the latest cmake (as of this writing)
wget -O cmake.sh https://github.com/Kitware/CMake/releases/download/v3.23.1/cmake-3.23.1-Linux-x86_64.sh && \
    sudo sh ./cmake.sh --prefix=/usr/local --skip-license

# fix llvm for AFLplusplus
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo -S apt-key add -
echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main" | sudo tee -a /etc/apt/sources.list
sudo -S apt-get update
sudo -S apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools cargo libgtk-3-dev
# try to install llvm 12 and install the distro default if that fails
sudo -S apt-get install -y lld-12 llvm-12 llvm-12-dev clang-12 || sudo -S apt-get install -y lld llvm llvm-dev clang
sudo -S apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
sudo -S apt-get install -y ninja-build # for QEMU mode

# get afl
git config --global core.longpaths true
# Newest: git clone https://github.com/AFLplusplus/AFLplusplus
# Old:
wget https://github.com/AFLplusplus/AFLplusplus/archive/refs/tags/v4.20c.tar.gz
tar xvf v4.20c.tar.gz
mv AFLplusplus-4.20c AFLplusplus
cd AFLplusplus/
make || exit 1
sudo make install || exit 1
echo "[+] Success to build AFL!"

cd unicorn_mode/
./build_unicorn_support.sh || exit 1
# fix the libunicornafl.so
# make clean
# make -j1
# fix the libunicorn.so
cd ./unicorn/
mkdir build; cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j8
sudo make install || exit 1
cd ../../../
echo "[+] Success to build Unicornafl!"

4.2 Ubuntu 20~22

完整安装脚本可以参考我们已经开发好的工具的 AFL 安装部分:https://github.com/IoTS-P/SEmu-Fuzz/blob/main/install_local.sh

这两个版本的系统就是可以少装两个依赖,别的没太大差别。

# base dependency
sudo apt-get install -y build-essential python3-dev automake cmake git flex bison python3-setuptools cargo

# get afl
git config --global core.longpaths true
# Newest: git clone https://github.com/AFLplusplus/AFLplusplus
# Old:
wget https://github.com/AFLplusplus/AFLplusplus/archive/refs/tags/v4.20c.tar.gz
tar xvf v4.20c.tar.gz
mv AFLplusplus-4.20c AFLplusplus
cd AFLplusplus/
make || exit 1
sudo make install || exit 1
echo "[+] Success to build AFL!"

cd unicorn_mode/
./build_unicorn_support.sh || exit 1
#  fix the build_unicorn_support.sh with the content below.
# install unicornafll
cd unicornafl/bindings/python
pip install .
cd ../../
# fix the libunicornafl.so
# make clean
# make -j1
# fix the libunicorn.so
cd ./unicorn/
mkdir build; cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j8
sudo make install || exit 1
cd ../../../
echo "[+] Success to build Unicornafl!"

4.3 收尾

记得编辑自己的终端配置文件,追加一项配置并 source。
例如我用的是zsh,对应的终端配置文件就是~/.zshrc;Ubuntu 默认使用的是 bash,对应的终端配置文件就是 ~/.bashrc

vi ~/.bashrc

追加

export AFL_SKIP_CPUFREQ=1

source:

source ~/.bashrc

添加这个配置是因为跑模糊测试一般都是为了公司,为了实验室而跑,大家都跑在服务器上,不一定有管理员的系统配置权限。而 afl 的这一项功能恰好是需要开启一项系统权限的,与其麻烦系统管理员,不如自己追加配置,把这一项配置给禁用🤕……

5. Python 测试用例简单讲解

5.1 复杂使用示例

看了前面的你们应该也已经知道,Unicorn 是需要自己实现很多东西的😭。它只是一个仿真器框架罢了,灵活是灵活但是真只是个框架。

我毕设基于这个框架实现了点别的东西,把它缺失的外设和中断部分都加上去了,让二进制程序还算正常地能跑起来了。我对 unicorn 的毕生所学都在里面了(bushi),如果想看更复杂的使用示例,可以直接参考我们的 ⭐ SEmu-Fuzz 仓库:https://github.com/IoTS-P/SEmu-Fuzz/tree/main,是针对 ARM v7m 写的。【需要注意的是,我现在已经在开发新的了,这个仓库已经不太维护了,新的仓库代码更加的简洁清晰,毕设这个比较仓促,功能没太多问题但性能不好】

5.2 官方使用示例

官方也是提供了简单的测试用例的,就在 Readme 这里很清晰:

在这里插入图片描述

点了链接,跳转过去,就是 afl++ 的仓库里边:https://github.com/AFLplusplus/AFLplusplus/tree/stable/unicorn_mode/samples。

文件位置:https://github.com/AFLplusplus/AFLplusplus/tree/stable/unicorn_mode/samples/python_simple
文件结构:

在这里插入图片描述

简单概括一下这些文件相互之间的关系:simple_target.bin 这个二进制文件由 simple_target.c 根据 COMPLE.md 的过程编译而成,simple_test_harness.py 和 simple_test_harness_alt.py 都可以用于测试 simple_target.bin,不过,simple_test_harness.py 调用 uc_afl_fuzz 这个封装得更精致的 API,simple_test_harness_alt.py 仅仅调用 uc.afl_forkserver_start,回调函数之类的都得自己重写,更加灵活。

但是🤕!我实际测试了,发现 simple_test_harness_alt.py 还没更新成 unicornafl2 的代码!也就是 simple_test_harness_alt.py 只不过是 unicorn1 时代的残留罢了……【如下两图所示】
在这里插入图片描述
在这里插入图片描述

总之,看 simple_test_harness.py。

运行方法以及整个代码的详细解释,在这个文件中都清清楚楚,明明白白的写出来了,在博客里,没有必要赘述什么:

在这里插入图片描述

被测用例的源码如下:

#define DATA_ADDRESS 	0x00300000

int main(void) {
  unsigned char *data_buf = (unsigned char *) DATA_ADDRESS;

  if (data_buf[20] != 0) {
    // Cause an 'invalid read' crash if data[0..3] == '\x01\x02\x03\x04'
    unsigned char invalid_read = *(unsigned char *) 0x00000000;
  } else if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
    // Cause an 'invalid read' crash if (0x10 < data[0] < 0x20) and data[1] > data[2]
    unsigned char invalid_read = *(unsigned char *) 0x00000000;
  } else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
    // Cause a crash if data[10] is not zero, but [9] and [11] are zero
    unsigned char invalid_read = *(unsigned char *) 0x00000000;
  }

  return 0;
}

很明显,根据他的这个注释可以看出来他在什么情况下会触发 crash,一共有五种情况,为了便于解释,我们把下文中的每一个条件语句都记成数字 if1、if2.1、if2.2、if2.3、if3.1、if3.2、if3.3。5种 crash 的情况分别是:

✅ 代表 true
❌ 代表 false

  1. if1 ✅
  2. if1 ❌,if2.1 ✅,if2.2 ✅
  3. if1 ❌,if2.1 ❌,if3.1 ✅,if3.2 ✅,if3.3 ✅
  4. if1 ❌,if2.1 ✅,if2.2 ❌,if3.1 ✅,if3.2 ✅,if3.3 ✅
  5. if1 ❌,if2.1 ✅,if2.2 ✅,if2.3 ❌,if3.1 ✅,if3.2 ✅,if3.3 ✅

切换到测试文件的目录下面,然后执行这行指令就可以了:

cd unicorn_mode/samples/python_simple
afl-fuzz -U -m none -i ./sample_inputs -o ./output -- python3 simple_test_harness.py @@ 

这个指令的意思是,用 unicorn 模式(对应-U)、不设置内存限制(对应-m none)、指定输入种子所在的文件夹(对应-i ./sample_inputs)、输出到output文件夹(对应-o ./output),去测试 python3 simple_test_harness.py这个程序,并把生成的种子文件作为命令行参数传递给这个程序(对应@@占位符)。

在这里插入图片描述

在这里插入图片描述
被测用例有五条 crash 的路径,所以就有5个 crash,很快就能跑出来,大概500个种子就跑出来了:

在这里插入图片描述

我多跑了一会儿:
在这里插入图片描述

仔细看它的测试用例代码,就会感觉 100 来行的 Python 代码,就为了测个这个,要自己定义内存布局,要写各种映射,还有写钩子函数,好麻烦……

更可怕的是,写完了这一套代码之后,即使想方设法的把这个代码写的可以支持多个测试用例了,由于设计上的原因,切换测试其他架构的测试用例还是很麻烦,比如示例代码是 mips,如果要写 arm 的,还得重新写好多东西……【对 就是中断机制 对中断被挪走了的怨念从开头到结尾形成首尾呼应……】

想想就头秃啊。

但是平常自己普通测试一下,一些规模不大的,就像官方这种小代码应该也是挺方便的……【吧?】

本账号所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_46106285/article/details/139004670。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分布式事务——9种解决方案的原理与分类

目录 一、概要1. 分布式事务的概念2. 分布式事务解决方案分类 二、常见的分布式事务解决方案1. 基础的 2PC&#xff08;二阶段提交&#xff09;1.1 核心思想1.2 简介1.3 主要特点1.3.1 优点1.3.2 缺点 2. 基础的 3PC&#xff08;三阶段提交&#xff09;2.1 核心思想2.2 简介2.3…

【系统架构师】-案例篇(十五)SOA、微服务与数据库

1、可复用构件应具备哪些属性 可用性&#xff1a;构件必须易于理解和使用。 质量&#xff1a;构件及其变形必须能正确工作。 适应性&#xff1a;构件应该易于通过参数化等方式在不同语境中进行配置。 可移植性&#xff1a;构件应能在不同的硬件运行平台和软件环境中工作。 可变…

# 全面解剖 消息中间件 RocketMQ-(2)

全面解剖 消息中间件 RocketMQ-&#xff08;2&#xff09; 一、RocketMQ – RocketMQ 各角色介绍 1、RocketMQ 各角色介绍 Producer : 消息的发送者; 举例:发信者。Consumer : 消息接收者; 举例:收信者。Broker : 暂存和传输消息; 举例:邮局。NameServer : 管理 Broker; 举例…

全网最全爬取-b站爬取弹幕+评论之js逆向与xml降本增效

&#x1f31f; ❤️ 作者&#xff1a;yueji0j1anke 首发于公号&#xff1a;剑客古月的安全屋 字数&#xff1a;801 阅读时间: 10min 声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及…

K-means聚类模型

目录 1.定义 2.K-means聚类模型的优点 3.K-means聚类模型的缺点 4.K-means聚类模型的应用场景 5.对K-means聚类模型未来的展望 6.小结 1.定义 什么是 K-means 聚类模型&#xff1f;K-means 聚类模型是一种无监督学习算法&#xff0c;用于将数据划分为不同的组或簇&#…

概念+bug

模型 迭代模型和增量模型 增量模型是将一个大的需求变成小的功能&#xff0c;然后将每个功能逐个开发几乎完整再上线。 迭代模型会上线一个基础版本&#xff0c;但是基础版本所有的功能都有但是非常简陋&#xff0c;之后再迭代优化上线。 一般都是两个一起用&#xff0c;不…

微服务Day7学习

文章目录 数据聚合聚合分类 自动补全DSL实现Bucket聚合DSL实现Metrics聚合RestAPI实现聚合多条件聚合对接前端接口拼音分词器自定义分词器自动补全查询实现酒店搜索框自动补全 数据同步数据同步思路分析利用mq实现mysql与elasticsearch数据同步 集群介绍搭建ES集群 数据聚合 聚…

T01.如何寻找隐藏目录usr?

当我们打开Mac自带的Shell或者另外安装的zsh等工具时&#xff0c;我们所在的默认目录为用户目录usr。 Mac的这个bin目录&#xff0c;是一个已经包含在环境变量里的目录&#xff0c;程序放在里面或者链接到里面就可以在终端里直接执行。Mac的usr/bin目录是不允许增删文件的&…

tomcat三级指导

版本 ./catalina.sh linux version.bat win 1.确认是否使用了tomcat管理后台 我们先找到配置文件&#xff1a;tomcat主目录下/conf/server.xml 可以查看到连接端口&#xff0c;默认为8080 然后查看manager-gui管理页面配置文件&#xff0c;是否设置了用户登录 配置文件…

Obsidian Git 多端同步

2023年6月&#xff0c;某云笔记限制了免费用户最多同时登录 2 台设备&#xff0c;想要增加设备数量需要付费开通会员。之后我一直想找一款合适的笔记本软件&#xff0c;年底尝试了Obsidian&#xff0c;断断续续摸索了好几天终于成功了。将那时的笔记拿来分享一下。 相关地址&am…

Java轻松转换Markdown文件到Word和PDF文档

Markdown 凭借其简洁易用的特性&#xff0c;成为创建和编辑纯文本文档的常用选择。但某些时候我们需要更加精致的展示效果&#xff0c;例如在专业分享文档或打印成离线使用的纸质版时&#xff0c;就需要将Markdown文件以其他固定的文档格式呈现。通过将 Markdown 转换为 Word 和…

错误代码126:加载x3daudio1_7.dll失败的几种修复方法分享

在使用电脑玩游戏或者工作的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“错误代码[126]:加载x3daudio1_7.dll失败&#xff0c;该文件缺失或损坏!”&#xff0c;那么&#xff0c;什么是x3daudio17.dll文件&#xff1f;它为什么会丢失&#xff1…

剪画小程序:3个方法:告诉你如何将普通的照片转换成动漫二次元风格!

Hello&#xff01;亲爱的小伙伴们&#xff01; 你是否还在纠结于自己的自拍太普通&#xff0c;每次分享到社交账号上都觉得平平无奇&#xff0c;引不起波澜&#xff1f; 假如&#xff0c;你和朋友们一起出去玩&#xff0c;大家都开心地拍着自拍。你看着自己的照片&#xff0c…

多联机分户计费控制系统

中央空调多联机分户计费控制系统&#xff0c;针对国内常见几种品牌的多联机空调系统实行&#xff0c;远程控制与计费管理。系统采用MQTT网络协议&#xff0c;以订阅/发布模式实行设备感知&#xff0c;实现对室外机、室内机的状态监测、实时故障报警、累计分摊费用的实时数据传导…

SSMP整合案例第一步 制作分析模块创建与开发业务实体类

制作分析 我们要实现一个模块的增删改查 实际开发中mybatisplus用的不多&#xff0c;他只能对没有外键的单表进行简单的查询 但在这个案例中我们还是选择mybatisplus开发 模块创建 我们把所有服务器都放在一起 就不用前后端分离 我们尝试用后端开发进行全栈开发 新建项目添…

C++语法|多重继承详解(一)|理解虚基类和虚继承

系列汇总讲解&#xff0c;请移步&#xff1a; C语法&#xff5c;虚函数与多态详细讲解系列&#xff08;包含多重继承内容&#xff09; 虚基类是多重继承知识上的铺垫。 首先我们需要明确抽象类和虚基类的区别&#xff1a; 抽象类&#xff1a;有纯虚函数的类 虚基类是什么呢&a…

精选ThingsBoard物联网关

Thingsboard网关BL104 ThingsBoard物联网网关是一个指可以将数据采集转发至ThingsBoard平台的物联网网关&#xff0c;它使用且仅使用MQTT协议与ThingsBoard平台&#xff08;ThingsBoard IoT Platform&#xff09;进行通讯。这个网关为ThingsBoard平台提供支持更多协议的数据收…

poi操作word模板,对原有的word修改

/*** 化工园区调查表** param templatePath* param outPath* param parkInterview*/public static String getDocx(String templatePath, String outPath, ParkInterview parkInterview){File file new File(templatePath);File file1 new File(outPath);if(!file1.exists()…

2024 年 电工杯(B题)大学生数学建模挑战赛 | 平衡膳食食谱 | 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 CS团队倾注了大量时间和心血&#xff0c;深入挖掘解决方案。通…

怎么查看公网IP?

在网络通信中&#xff0c;每个设备都会被分配一个IP地址&#xff0c;用于在互联网上进行唯一标识和通信。公网IP是指可以被公开访问的IP地址&#xff0c;可以用来建立远程连接或者进行网络访问等操作。怎么查看公网IP呢&#xff1f;下面将介绍几种常用的方法。 使用命令行查询公…