Web安全研究(五)

Automated WebAssembly Function Purpose Identification With Semantics-Aware Analysis

WWW23

文章结构

  1. intro
  2. background
  3. system design
    1. abstraction gen
    2. applying abstractions
    3. classifier
  4. data collection and handling
    1. data acquisition
    2. statistics of collected data
    3. module-level categorization
    4. function-level categorization
  5. evaluation
  6. discussion
  7. related work
  8. conclusion

Intro

WebAssembly(简称Wasm)是最新的网络标准。自2015年首次亮相以来[6],WebAssembly在前端领域引起了巨大轰动。一些知名的科技公司,如eBay、Google和Norton,在面向用户的项目中采用这项技术,以在诸如条形码阅读[35]、模式匹配和TensorFlow.js机器学习应用程序[44]等用例中提高性能,超越JavaScript。目前,所有主要的浏览器都支持WebAssembly[29]。

该语言定义了一种可移植且紧凑的字节码格式,用作其他语言(如C、C++和Rust)的编译目标。这使得将本地程序作为模块移植到Web并以接近本地速度执行成为可能。与直接编写不同,诸如Emscripten [4] 和 Wasmbingden [39] 的编译器生成WebAssembly字节码。WebAssembly还定义了一种文本格式,旨在使调试更加容易。文本格式提供了模块内部结构的可读表示,包括类型、内存限制和函数定义。尽管可读,但与高级语言相比,文本格式的学习曲线仍然相对陡峭。

WebAssembly有两个特性使得人类读者难以解释。

  1. WebAssembly只有四种数值数据类型,即i32、i64、f32和f64,使得一些应用程序的指令序列相似,如字符串操作和加密哈希。WebAssembly has only four numeric data types,i32, i64, f32, and f64, making the instruction sequences of several applications, such as string manipulation and cryptographic hashing,similar.
  2. 其堆栈机设计使得在给定位置推导变量的值变得困难。必须从给定位置跟踪堆栈,以确定在特定代码位置计算的值。its stack machine design makes deriving the value of a variable at a given location difficult. The stack must be traced from a given location to identify the computed value at a specific code location.

源映射(source maps)可用于在高级源语言中找到相应的功能。然而,许多WebAssembly模块,包括恶意模块,都通过第三方服务传递,其中源代码不可用[32]。对于这种情况,终端用户需要手动验证WebAssembly模块的实际功能。先前的研究[14, 32]关注了WebAssembly样本的目的。然而,很少有研究帮助开发人员理解WebAssembly模块实现的功能。

14: An Empirical Study ofReal-WorldWebAssembly Binaries: Security, Languages, Use Cases WWW 21
32: New Kid on the Web: A Study on the Prevalence of WebAssembly in the Wild DIMVA 2019

为此,我们开发了一个自动分类工具WASPur,以帮助开发人员了解应用程序中各个WebAssembly函数的预期功能。WASPur在模块的语法差异上构建了关于语义功能的抽象,这些抽象可用于机器学习分类器,以确定WebAssembly函数实现的功能。具体而言,我们的工作做出了以下贡献:

  • 我们提出了一种中间表示(IR),用于抽象WebAssembly应用程序底层语义,实现对语法鲁棒性的分析。
  • 我们通过爬取真实世界的网站、Firefox插件、Chrome扩展和GitHub存储库,构建了一个多样化的WebAssembly样本数据集。
  • 我们对收集到的WebAssembly样本进行了全面的分析。我们确定了这些样本的目的,并将它们分类为12个类别。
  • 我们开发了一个自动分类工具WASPur,可以根据其功能准确标记给定的WebAssembly函数,准确率为88.07%。

Background

image.png
WebAssembly定义了一种紧凑的字节码格式,旨在通过网络调用进行高效传输。该标准还定义了字节码的文本表示,以允许开发人员调试代码。图1显示了一个WebAssembly模块在字节码和文本格式中的样子。图1(a)中显示的C++代码片段包含一个主函数,该函数分配了两个变量,然后比较它们的值。这段代码编译为图1(b)中显示的WebAssembly二进制代码。二进制格式是WebAssembly模块传递到浏览器并由其编译的方式。WebAssembly二进制代码可以被翻译成其文本格式,如图1©所示,它展示了WebAssembly指令的示例,如i32.sub和i32.load。

WebAssembly模块具有清晰定义的结构。每个模块由10个部分组成,每个部分描述模块的不同组件:

  1. Types - 此部分定义了模块中使用的所有函数类型,包括参数和结果的数据类型。
  2. Functions - 此部分通过它们的类型、使用的局部变量和由一系列WebAssembly指令组成的函数体定义了所有的WebAssembly函数。
  3. Tables - 此部分定义了作为间接函数调用目标使用的函数表,即使用call_indirect。
  4. Memory - 此部分定义了模块的线性内存部分的属性。
  5. Globals - 此部分列出了在模块中所有函数中可访问的全局变量。
  6. Elements - 此部分列出了将用于初始化指定函数表的函数索引。
  7. Data - 此部分列出了将用于初始化指定线性内存部分的字节序列。
  8. Start - 此部分定义了模块初始化后是否调用任何一个函数。
  9. Imports - 此部分声明了从JavaScript导入的函数,将在WebAssembly函数内调用。
  10. Exports - 此部分指定了将导出到主机JavaScript上下文的哪些WebAssembly函数,以便可以在那里调用它们。

我们的分类方法主要关注Functions部分,因为这部分包含了通过WebAssembly指令实现的大部分过程功能。

System

Use a semantics-aware intermediate representation designed to capture the effects produced by wasm instructions.
使用基于语义感知的中间表示来捕获wasm指令产生的影响。

如下图所述,两个关键组件:

  1. IR抽象,将所有函数抽象为IR表示
  2. 分类器,将IR单元输入到神经网络分类器中,分类器在多次出现在WebAssembly 模块中的函数名称进行训练,并输出被检查函数属于相似命名函数组的概率。

image.png

Abstraction gen

定义 1(抽象规则)。抽象规则是一个元组(𝑆, 𝑎, 𝐷𝑒𝑓 ),其中:

  • 𝑆 表示一个或多个堆栈操作,用于模拟 WebAssembly 指令对虚拟堆栈的影响、
  • 𝑎是将 WebAssembly 指令映射到类 C 抽象的转换函数、
  • 𝐷𝑒𝑓是当前代码位置所有存活变量的定义集。

我们提出的抽象规则将 WebAssembly 字节代码抽象为五组:
(1) 数字指令: 在堆栈值上执行数值计算。
(2) 参数指令: 操作虚拟堆栈,无需额外计算。
(3) 控制指令: 利用堆栈中的值改变程序的控制流。
(4) 变量指令: 分配和获取局部变量。
(5) 内存指令: 分配和获取内存值。
下表显示了 WebAssembly 指令的子集,以及我们如何抽象每组指令。
image.png

**数值指令。**WebAssembly执行基于堆栈机体系结构,因此我们的抽象模型基于其对堆栈的影响来对WebAssembly指令进行建模。建模堆栈使我们的抽象能够捕捉程序的数据和控制流。第一组抽象模型是对在堆栈值上执行数值计算的指令。例如,指令“i32.const 𝑐”将32位常数𝑐推送到堆栈上。前缀i32表示𝑐的数据类型为32位整数。类似地,64位整数由i64前缀表示,32位浮点数由f32前缀表示。我们通过将这些指令应用于表示参数、变量和加载值的符号值来捕捉它们。

**参数指令。**该组包括两个WebAssembly指令,“drop”和“select”。这些指令可以从堆栈中删除一个值而不执行其他计算。我们通过它们对虚拟堆栈的影响来对这些指令进行建模。

**控制指令。**WebAssembly支持诸如if、loop和block之类的控制流构造。条件语句如“if 𝐼”被抽象为“if (𝑒)”,其中条件𝑒从堆栈中弹出。在if块范围内定义的抽象存储在内部抽象的列表中。我们使用“block”和“for”抽象分别对“block”和“loop”指令进行建模。两个抽象都定义了一个标签,例如“loop 𝑔:”,用于封装一段代码。‘br 𝑔”和“br_if 𝑔”指令控制控制流是否将转到带标签的块的开始。为了模拟这种行为,我们还将在块中定义的任何抽象存储到内部抽象的列表中。而“for”抽象还包含控制循环是否终止的条件。“call”指令使用显式函数名称进行直接调用,“call_indirect”指令使用对函数表的索引进行间接调用。我们使用相应的“call”和“call_indirect”抽象对这两个指令进行建模。

**变量指令。**变量指令可以从局部或全局变量加载值,也可以为它们分配值。为了对加载变量的指令(如“get_global”)进行建模,我们使用符号值来表示它们在堆栈上的位置。对于分配值给变量的指令(如“set_local”),我们使用“set”抽象来记录目标变量和分配的值的信息。我们还在变量定义集中记录变量分配的历史。例如,为了处理操作“set_local 𝑣”,我们的定义集将被更新以反映局部变量 𝑣 当前包含值 𝑒。

**内存指令。**类似于变量指令,有一些内存指令可以在线性内存中加载(例如,“i64.load”)或存储(例如,“i32.store”)值。我们使用符号值来表示特定内存索引处的值,从而对加载指令进行建模。我们通过构建“store”抽象来对内存存储指令进行建模,该抽象跟踪目标内存位置和值。我们还在变量定义集中记录这些内存存储的历史。例如,“i32.store8”会被抽象为“W8(𝑒2, 𝑒1)” ,其中𝑒2是源地址,𝑒1是目标地址。定义集会更新以反映内存索引 𝑒2 包含值 𝑒1。

我们观察到,WebAssembly应用程序通常使用连续的内存复制操作,因此我们根据两个规则将连续的“store”抽象合并为单个抽象。对连续内存缓冲区的顺序写入被简化为“memcpy”抽象,通过推断“store”抽象中的起始地址、目标地址和要复制的内存长度来实现。对连续内存缓冲区进行写入的语义也可以通过使用循环逐字节写入并类似地推断地址和内存大小来实现。

Applying abstraction

要应用我们的抽象,首先我们为每个函数构建一个函数内控制流图(iCFG)。该图包含通过遍历单个函数的指令序列构建的抽象序列。我们对抽象进行了一些转换,以压缩它们,例如将连续的重复操作组合成循环。

在构建了每个函数的iCFG之后,我们通过在“call”抽象上连接单个iCFG来构建一个函数间控制流图(ICFG)。为了进行图遍历,为每个函数构建一个单独的ICFG,所选函数用作遍历的起点。我们将深度限制为两个调用层级,以防止由递归函数引起的循环。对于“call_indirect”抽象,我们连接所有与声明的函数类型匹配的函数。

Classifier

利用从程序抽象构建的IR,分类器通过预测具有相似IR轨迹的函数的函数名来确定函数的功能。我们将在以下部分详细描述如何对抽象进行编码以及如何训练分类器。

3.3.1 将抽象编码为特征

分类器使用神经网络模型为给定的抽象序列预测标签。输入需要被编码成一个数值表示,以输入到模型中。我们输入神经网络的是在遍历目标函数的函数间控制流图(ICFG)时产生的抽象序列。然后,该序列被视为一个抽象类型字符串,例如,“set set for store if …” 这个字符串被嵌入为一个数值向量,其中整数表示我们定义的八种抽象类型之一。这个向量需要一个预定义的序列长度,因此比这个长度长的抽象轨迹会被截断。

3.3.2 训练分类器

分类器是在收集到的WebAssembly文件的生成函数抽象序列上进行训练的。为了训练和评估分类器,WebAssembly函数被根据它们的抽象序列分组在一起,这里使用非最小化名称的WebAssembly函数。我们使用这些函数名作为分类的标签。标签字符串使用多热编码方案进行编码,将每个标签映射到数值向量的索引。分类器输出一个向量,其中浮点值对应于某个标签应该应用于样本的概率。分类器通过将数据集分成80%的训练集、10%的验证集和10%的测试集进行评估。

3.3.3 神经网络架构

支持我们分类器的神经网络以抽象序列作为输入。一个嵌入层将抽象序列字符串编码为最多250个整数的数值向量。每个隐藏层使用TensorFlow提供的全连接Dense层类型。输出层由189个单元组成,使用SoftMax激活函数。该层中的单元对应于网络预测的标签值的索引。网络配置为使用真实标签和预测标签之间的交叉熵损失作为损失函数,并使用Adam梯度下降方法作为优化算法。我们配置网络在训练模型时使用30次迭代。

我们的模型的分类性能取决于使用适当的超参数值。我们调整神经网络模型的超参数,以确定从给定的抽象序列输入预测标签的合适配置。为了确定最佳的隐藏层单元数、激活函数和层数,我们构建了不同超参数值的神经网络,以确定我们的分类器能够达到的最高准确度值。

Data collection

我们收集WebAssembly样本以构建神经网络模型的训练和评估数据集。在以下部分,我们描述了从各种来源收集WebAssembly二进制样本的过程。我们还详细描述了这些样本以及它们实现的用例。

我们从四个来源收集WebAssembly样本:
(1) Alexa前100万个网站,
(2) 安装用户最多的17,682个热门Chrome扩展,
(3) 安装用户最多的16,385个热门Firefox插件,
(4) 1.12亿GitHub仓库。

4.1.1 Alexa前100万个网站

我们从2018年10月到2020年5月爬取了Alexa前100万个网站。对于每个网站,我们访问了主页和所有一级子页面。我们决定将爬取限制为一级子页面而不是所有子页面,因为对于包含数千个子页面的复杂网站,完整扫描需要数小时。为了下载在页面上运行的WebAssembly二进制文件,我们使用启用了“–dump-wasm-module”标志的Chromium浏览器版本77来转储浏览器解码的任何WebAssembly模块。

4.1.2 Chrome扩展

我们通过使用修改后的Chromium浏览器运行所有安装用户超过1,000的扩展来获取来自Chrome扩展的WebAssembly样本。我们从2019年3月25日到2019年3月30日爬取了Chrome扩展。下载所有Chrome扩展花费了一天的时间,评估每个扩展花费了四天的时间。这导致了总共17,682个Chrome扩展。

4.1.3 Firefox插件

从Firefox插件中获取的样本是通过爬取官方Firefox插件网站以下载.xpi插件存档而获得的。.xpi存档被扫描以查找以“.wasm”结尾的文件。我们在2019年7月30日爬取了Firefox插件。下载和扫描所有插件花费了一天的时间。总共分析了16,385个Firefox插件。

4.1.4 GitHub仓库

我们使用pga命令行工具从Public Git Archive数据集[27]中获取WebAssembly样本。我们指定了“–lang”过滤器以获取使用WebAssembly作为语言过滤器的存储库。然后,我们使用GitHub REST API [15]扫描这些存储库,找到并下载所有WebAssembly二进制文件(.wasm)。这个过程在2019年10月3日花了一天的时间。

表2显示了每个已爬取来源的WebAssembly二进制文件的数量。它显示了每个来源的已爬取应用程序/项目数量,使用WebAssembly的应用程序/项目数量以及从每个来源识别的WebAssembly程序数量。总共,我们从所有来源识别了6,769个WebAssembly样本。这些应用程序/项目可以使用多个WebAssembly文件来实现复杂的用例,因此识别的WebAssembly样本数量超过了应用程序/项目的数量。在收集的6,769个WebAssembly模块中,有1,829个是独特的。
image.png

在1.12亿个GitHub仓库中,我们识别了435个与WebAssembly相关的仓库。表3显示了我们手动检查的结果,包括仓库的用途。这些WebAssembly GitHub仓库包括239个使用WebAssembly构建的仓库(97个应用程序,31个开发工具和111个WebAssembly示例)以及196个提供WebAssembly支持的仓库(68个WebAssembly运行时,36个区块链项目,29个框架,26个编译器,24个工具包和13个文档仓库)。此外,我们在各个组中确定了更细分的子类别,例如在"Applications"组中有25个游戏和3个机器学习应用程序,在"WebAssembly Runtime"组中有8个浏览器引擎和6个WebAssembly虚拟机。

image.png

WebAssembly程序的分类

对于了解WebAssembly程序在野外的预期目的,识别其类别(即预期目的)至关重要。为了发现这些样本的预期目的,我们通过依赖于从WebAssembly二进制文件获取的四种类型的信息(导入函数名称、导出函数名称、内部函数名称和文件来源),对文件进行手动检查和标记。如表4所示,我们将这些样本分为12个不同的类别。我们发现在我们调查的所有WebAssembly样本来源中都有各种各样的类别。对于每个类别,我们在表5中提供了在每个源位置找到的模块数量、文本文件大小的统计数据以及二进制文件大小的统计数据。

模块中的函数名称通常携带有关模块用途的信息描述。对于GitHub存储库中的源文件,我们使用文件在项目上下文中的用途来识别类别特征。对于浏览器扩展,我们查看了扩展的描述页面以及捆绑在扩展存档中的WebAssembly和JavaScript文件,以确定扩展的目的以及WebAssembly模块在其中扮演的角色。

总体而言,我们从模块的导入、导出和内部函数名称中产生了超过204,619个签名。表6总结了这些签名。

image.png
image.png

理解WebAssembly模块中各个函数的目的

理解构成模块的个体WebAssembly函数的目的也有助于开发人员理解整个模块。WebAssembly是一种经过编译的语言,通常经过编译器优化。在许多情况下,这些优化会使模块中定义的WebAssembly函数的函数名最小化,以及附带的JavaScript代码也会被最小化。我们观察到在1,829个总模块中有923个模块使用了最小化的函数名,从而减少了开发人员寻求理解模块功能时的关键信息。

为了识别WebAssembly模块的预期功能,我们利用了收集的模块中存在的函数名。这些函数名可以指示存在C、C++、Rust等常见实用工具的存在,比如malloc和strcmp。其他函数名表明这些函数实现了特定于应用程序的行为,比如AutoThresholdImage和IsPDF等。我们从在至少两个唯一模块中出现的函数的名称中创建标签。我们还将类似的函数名(例如 m a l l o c 、 malloc、 malloc_malloc和$memory.allocate)压缩成代表该组的单个标签,例如malloc。通过这个过程,我们获得了189个不同的函数类别。在多个模块类别中出现的函数名表明这些函数实现了共同的实用工具。

image.png

Evaluation

我们使用从Alexa前100万个网站、Chrome扩展、Firefox插件和GitHub存储库收集的1,829个独特的WebAssembly文件的数据集对WASPur进行训练和评估。为了使用这些样本,我们提取每个函数并为每个函数构建抽象IR。然后,我们将抽象序列编码为数字向量,以在神经网络模型中使用。为了确定提供最佳预测能力的神经网络超参数,我们使用不同数量的层内隐藏单元、不同激活函数和不同层数来测量模型的分类指标。

为了评估WASPur,我们使用了这个WebAssembly模块的数据集来构建一个单独的WebAssembly函数的数据集。对于每个函数,我们记录其名称、抽象遍历序列和其父模块。然后,我们使用函数名称为函数提供一个标签,根据我们在第4.4节中的描述。我们的函数数据集包含了从1,829个独特的WebAssembly文件中提取的11,524,686个函数。其中,151,662个函数有函数名称,而11,373,024个函数没有函数名称,因为经过了优化或缩小的步骤。我们使用这151,662个带标签的函数来训练我们的分类器。

WASPur基于Node.js [8]和Python [9]构建。该系统包含两个组件。抽象生成器组件是一个Node.js应用程序,而分类器组件是用Python实现的。分类器使用了使用Keras [48]和TensorFlow [1]库构建的神经网络模型。分类器模型在一台搭载Intel Core i7 CPU@2.1GHz和64GB RAM的笔记本上进行训练和评估。

image.png

image.png

image.png

image.png

没有跟SOTA的对比

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

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

相关文章

SpringBoot框架简介

SpringBoot框架简介 简单介绍 前言: 我们大家都知道Spring,Boot是启动的意思,所以SpringBoot其实是一个启动Spring项目的一个工具,从根本上讲,SpringBoot就是一些库的集合,它能够被任意项目的构建系统所使…

YOLOv8 加持 MobileNetv3,目标检测新篇章

🗝️YOLOv8实战宝典--星级指南:从入门到精通,您不可错过的技巧   -- 聚焦于YOLO的 最新版本, 对颈部网络改进、添加局部注意力、增加检测头部,实测涨点 💡 深入浅出YOLOv8:我的专业笔记与技术总结   -- YOLOv8轻松上手, 适用技术小白,文章代码齐全,仅需 …

qsort使用举例和qsort函数的模拟实现

qsort使用举例 qsort是C语言中的一个标准库函数,用于对数组或者其他数据结构中的元素进行排序。它的原型如下: void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 我们可以去官网搜来看一看:…

基于Vue+SpringBoot的大病保险管理系统 开源项目

项目编号: S 031 ,文末获取源码。 \color{red}{项目编号:S031,文末获取源码。} 项目编号:S031,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大…

基于灰狼算法(GWO)优化的VMD参数(GWO-VMD)

代码的使用说明 基于灰狼算法优化的VMD参数 代码的原理 基于灰狼算法(Grey Wolf Optimizer, GWO)优化的VMD参数(GWO-VMD)是一种结合了GWO和VMD算法的优化方法,用于信号分解和特征提取。 GWO是一种基于群体智能的优化…

Transformer中WordPiece/BPE等不同编码方式详解以及优缺点

❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…

C语言 字符函数汇总,模拟实现各字符函数(炒鸡详细)

目录 求字符串长度 strlen 示例 模拟实现strlen 长度不受限制的字符串函数 strcpy 示例 模拟实现strcpy strcat 模拟实现strcat strcmp 示例 模拟实现strcmp 长度受限制的字符串函数介绍 strncpy 示例 模拟实现strncpy strncat 示例 模拟实现strncat s…

MySQL数据库索引以及使用唯一索引实现幂等性

📑前言 本文主要是MySQL数据库索引以及使用唯一索引实现幂等性的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页放风讲故事 &#x1f30…

数据结构:红黑树讲解(C++)

红黑树 1.前言2.红黑树简述2.1概念2.2性质 3.红黑树的插入3.1关于新插入节点的颜色3.2节点的定义3.3插入新节点3.4判断插入后是否需要调整3.5插入后维持红黑树结构(重点)3.5.1cur、p、u为红,g为黑3.5.2cur、p为红,g为黑&#xff0…

MISRA 2012学习笔记(5)-Rules 8.10

文章目录 Rules8.10 基本类型模型(The essential type model)8.10.1 原理8.10.2 基本类型(Essential type)Rule 10.1 操作数不得具有不适当的基本类型Rule 10.2 在加减法运算中,不得不当使用本质为字符类型的表达式Rule 10.3 表达式的值不得赋值给具有较窄基本类型或…

【数据结构(二)】单链表(3)

文章目录 1. 链表介绍2. 单链表应用实例2.1. 顺序添加方式2.1.1. 思路分析2.1.2. 代码实现 2.2. 按照编号顺序添加方式2.2.1. 思路分析2.2.2. 代码实现 3. 单链表节点的修改3.1. 思路分析3.2. 代码实现 4. 单链表节点的删除4.1. 思路分析4.2. 代码实现 5. 单链表常见面试题5.1.…

影刀sqlite的插入方法

影刀sqlite的插入方法 变量外面不用加‘’

YOLO免费数据集网站收集

目录 Roboflow Universe: Open Source Computer Vision Community Find Open Datasets and Machine Learning Projects | Kaggle ​编辑 【火焰和烟雾图像数据集】-计算机视觉数据集-极市开发者平台 (cvmart.net) 开放数据集- 飞桨AI Studio星河社区 - 人工智能学习与实训社…

【iOS】——知乎日报第五周总结

文章目录 一、评论区展开与收缩二、FMDB库实现本地持久化FMDB常用类:FMDB的简单使用: 三、点赞和收藏的持久化 一、评论区展开与收缩 有的评论没有被回复评论或者被回复评论过短,这时就不需要展开全文的按钮,所以首先计算被回复评…

【LeetCode刷题-树】-- 572.另一棵树的子树

572.另一棵树的子树 方法:深度优先搜索暴力匹配 深度优先搜索枚举root中的每一个节点,判断这个点的子树是否与subroot相等 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right…

电子学会2023年6月青少年软件编程(图形化)等级考试试卷(四级)真题,含答案解析

青少年软件编程(图形化)等级考试试卷(四级) 一、单选题(共10题,共30分) 1. 下列积木运行后的结果是?( )(说明:逗号后面无空格) A.

读书笔记--从一到无穷大的关键金句和阅读感悟

借着休假,重新研读了十多年前读过的乔治.伽莫夫所著图书《从一到无穷大--ONE TWO THREE...INFINITY》,该书作为20世纪最经典的科普类图书之一,当时读的懵懵懂懂,现在重新阅读又有了不同的感受,再结合过去的科研工作&am…

计算机毕业设计选题推荐-内蒙古旅游微信小程序/安卓APP-项目实战

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

CBAM注意力机制(结构图加逐行代码注释讲解)

学CBAM前建议先学会SEnet(因为本篇涉及SEnet的重合部分会略加带过)->传送门 ⒈结构图 下面这个是自绘的,有些许草率。。。 因为CBAM机制是由通道和空间两部分组成的,所以有这两个模块(左边是通道注意力机制&#…

【MATLAB】全网唯一的11种信号分解+模糊熵(近似熵)联合算法全家桶

有意向获取代码,请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有18种信号分解算法,绝对不亏,知识付费是现今时代的趋势,而且都是我精心制作的教程,有问题可随时反馈~也可单独获取某一算法的代码&#xff0…
最新文章