CodeQL代码静态污点分析引擎排查漏洞模式

news2024/12/23 16:09:56

文章目录

  • 前言
  • 环境搭建
    • 1.1 codeql基础
    • 1.2 vscode插件
    • 1.3 生成数据库
    • 1.4 HelloWorld
  • codeql语法
    • 2.1 语法结构
    • 2.2 常用类库
    • 2.3 谓词介绍
    • 2.4 污点分析
  • 漏洞检测
    • 3.1 初步结果
    • 3.2 解决误报
  • 总结

前言

对于代码审计的工作,最早期的安全人员会以人工审计的方式来审计项目代码,通过查找危险函数并跟进危险函数的参数是否可控,如果可控则说明存在安全漏洞。但是随着项目数量的增加,纯靠人工的方式很难实现所有项目漏洞的覆盖测试。所以近些年出现了不少优秀的自动化代码安全审计产品,比如非常有名的 Checkmarx,Fortify SCA。但是这些软件都是商业的,价格比较贵。

与此同时,Github 为了解决其托管的海量项目的安全性问题,收购了 CodeQL 的创业公司,并宣布开源 CodeQL 的规则部分,这样全世界的安全工程师就可以贡献高效的 QL 审计规则给 Github(GitHub实验室对高质量的 CodeQL 规则发起了奖金计划),帮助它解决托管项目的安全问题。而对于安全工程师,也就多了一个非商业的开源代码自动化审计工具。

简单来说,CodeQL 是一种用于漏洞挖掘的代码审计工具,它可以根据已有的漏洞模型在庞大的代码库中找出相同类型的漏洞的变种,即可以帮助安全研究员或开发人员更快速精准地定位漏洞之处。研究员根据特有的 CodeQL 语法编写 CodeQL 规则,这个规则实质上就是描述已有漏洞的特征,若在目标代码库中存在该特征的代码段就定位出来,方便进一步分析是否为漏洞,极大提高了效率。

CodeQL 目前支持进行漏洞挖掘的语言包括:C/C++、C#、Go、Java、JavaScript、Python、Ruby。而 QL 是一门类似 SQL 的查询语言,通过对源码进行完整编译,并在此过程中把源码文件的所有相关信息(调用关系、语法语义、语法树)存在数据库中,然后编写代码查询该数据库来发现安全漏洞(硬编码 / XSS 等)。

环境搭建

CodeQL 本身包含两部分:

  1. 解析引擎:解析引擎用来解析我们编写的规则,虽然不开源,但是可以直接在官网下载二进制文件直接使用;
  2. SDK:SDK完全开源,里面包含大部分现成的漏洞规则,也可以利用其编写自定义规则。

1.1 codeql基础

首先下载解析引擎 CodeQL CLI,它是一个可执行的命令行工具,可以使用 CodeQL CLI运行 CodeQL 分析、创造 CodeQL 数据库、开发和测试自定义 CodeQL 查询。
在这里插入图片描述
本人是 Win10 笔记本,下载 codeql-win64.zip 并解压缩,然后在系统环境变量 PATH 中添加:

D:\Security\CodeQL\codeql-win64

最后验证环境变量配置是否成功:
在这里插入图片描述
接着下载 CodeQL SDK,或者说是标准的扫描规则 CodeQL libraries and queries。以下仓库包含了标准的 CodeQL 库和查询语句:

https://github.com/github/codeql

下载后是一个 codeql-main.zip 压缩包,解压到与解析引擎同一根目录下:
在这里插入图片描述
在此补充说明下:

  1. micro_service_seclab 文件夹是 Github 某大佬提供的用于 CodeQL 测试的开源漏洞靶场,下载地址:micro_service_seclab;
  2. 而 Database 文件夹则是我手动创建的,用于存放 CodeQL 编译 micro_service_seclab 项目生成的数据库,具体过程下文会提到。

1.2 vscode插件

VsCode 的扩展里提供了 CodeQL 的插件,可用于开发和调试 CodeQL 规则,在扩展里面搜索 codeql 后直接点击安装即可:
在这里插入图片描述
然后在如下图位置点击“拓展设置”:
在这里插入图片描述
填入本地下载并解压缩后的解析引擎 CodeQL CLI 的路径:
在这里插入图片描述
接着可以(也可以先忽略此步)在 VSCode 打开扫描规则 CodeQL libraries and queries(即上文下载的 codeql-main 文件夹):
在这里插入图片描述
注意,由于到这里我们尚未建立存在漏洞的代码项目的数据库,所以还不能直接运行 Run Query进行漏洞扫描。但是至此,CodeQL 的基本开发环境已搭建完毕。

1.3 生成数据库

下文会以 Github 某大佬提供的用于 CodeQL 测试的开源漏洞靶场为例(下载地址:micro_service_seclab),来介绍如何使用 CodeQL 来编写具体的规则分析源码里面的 SQL 注入漏洞点。

由于 CodeQL 的处理对象并不是源码本身,而是中间生成的 AST 结构数据库,所以需要把项目源码转换成 CodeQL 能够识别的 CodeDatabase。

抽象语法树(abstract syntax tree,AST) 是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构。

如下命令可进行 CodeDatabase 的生成工作:

codeql database create Database/micro-service-seclab-database  --language="java" --command="mvn clean install --file pom.xml" --source-root=micro_service_seclab

参数解析:

  1. Database/micro-service-seclab-database:指定了生成的数据库的数据存放路径;
  2. --language="java":代表该项目是 Java 语言开发的;
  3. --command="mvn clean install --file pom.xml" :编译命令(因为 Java 是编译语言,所以需要使用--command命令先对项目进行编译,再进行转换,Python和 PHP 这样的脚本语言不需要此命令),--command参数如果不指定,则会使用默认的编译命令和参数;
  4. --source-root=micro_service_seclab/:项目源码本地存放路径。

编译如果出错,比如本人遇到如下报错:
在这里插入图片描述

可以在 pom.xml 中添加如下代码来避免(参考:https://blog.51cto.com/ios9/3113441):

</project>
    ……
	<build>
		<plugins>
			<plugin>
				……
			</plugin>
			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                   <testFailureIgnore>true</testFailureIgnore>
                 </configuration>
             </plugin>
		</plugins>
	</build>
</project>

最后成功创建本地数据库:
在这里插入图片描述
在这里插入图片描述
导入数据库

切换到 VSCode 编辑器中,通过如下方式来导入刚刚生成的数据库,选择目录 micro-service-seclab:
在这里插入图片描述
在这里插入图片描述

1.4 HelloWorld

导入完数据库后,我们便可以正式开始编写 QL 查询规则来对目标代码的 AST 数据库进行特定漏洞规则的匹配查询,但是这需要掌握一定的 QL 语法才行,下面先简单编写 QL 查询语句来输入 “Hello World"。

在 VSCode 打开扫描规则 CodeQL libraries and queries(即上文下载的 codeql-main 文件夹),然后在如下图所示的目录里新建 demo.ql 文件并写入select "Hello World", 然后鼠标右键选择CodeQL: Run Query即可执行。
在这里插入图片描述
成功输出 “Hello World”,代表 CodeQL 开发环境和靶场数据库环境均成功准备完毕,可以进行下一步的 CodeQL 污点分析和规则编写(语法)的学习。

codeql语法

在对上文生成的存在大量漏洞的项目代码生成数据库进行 micro-service-seclab 漏洞检查之前,需要先来学习下 CodeQL 的基本语法。

本章节大部分摘自 FreeBuf 博文:CodeQL从入门到放弃,l4yn3大佬文章写得很好很详细,强烈推荐。

上面提到过,CodeQL 的核心引擎是不开源的,这个核心引擎的作用之一是帮助我们把 micro-service-seclab 转换成 CodeQL 能识别的中间层数据库。然后我们需要编写 QL 查询语句来获取我们想要的数据。
在这里插入图片描述
正如上图所述,由于 CodeQL 开源了所有的规则和规则库部分,所以我们能够做的就是编写符合我们业务逻辑的 QL 规则,然后使用 CodeQL 引擎去跑我们的规则,从而发现靶场的安全漏洞。

下面来简单地介绍一下本案例涉及到的 CodeQL 基本语法。

2.1 语法结构

CodeQL 的查询语法有点像 SQL,如果你学过基本的 SQL 语句,基本模式应该不会陌生。

import java
 
from int i
where i = 1
select i

第一行表示我们要引入 CodeQL 的类库,因为我们分析的项目是 java 的,所以在 QL 语句里,import java必不可少。

  • from int i,表示定义一个变量 i,它的类型是 int,此处代表获取所有的 int 类型的数据;
  • where i = 1,表示当 i 等于 1 的时候,符合条件;
  • select i,表示输出 i。

一句话总结就是:在所有的整形数字 i 中,当 i==1 的时候,我们输出 i。打印一下看看:
在这里插入图片描述
整体上,QL 查询的语法结构为:

from [datatype] var
where condition(var = something)
select var

2.2 常用类库

上面我们提到,我们需要把我们的靶场项目,使用 CodeQL 引擎转换成 CodeQL 可以识别的 database(micro-service-seclab-database),这个过程当中,CodeQL 引擎把我们的 java 代码转换成了可识别的 AST 数据库。

AST Code 大体长这个样子(注意需要在 workspace 中将源码文件夹添加进工作区后选择 XXX.java 文件后再在 QL 标签中点击 AST,才能看到对于 java 文件的语法树结构):
在这里插入图片描述
我们的类库实际上就是上面 AST 的对应关系。

怎么理解呢?比如说我们想获得所有的类当中的方法,在 AST 里面 Method 代表的就是类当中的方法;比如说我们想过的所有的方法调用, MethodAccess 获取的就是所有的方法调用。

我们经常会用到的 QL 类库大体如下:
在这里插入图片描述
结合 QL 的语法,我们尝试获取 micro-service-seclab 项目当中定义的所有方法:

import java
 
from Method method
select method

在这里插入图片描述
我们再通过 Method 类内置的一些方法,把结果过滤一下。比如我们获取名字为 getStudent 的方法名称。

import java
 
from Method method
where method.hasName("getStudent")
select method.getName(), method.getDeclaringType()

在这里插入图片描述
其中,method.getName() 获取的是当前方法的名称,而 method.getDeclaringType() 获取的是当前方法所属 class 的名称。
在这里插入图片描述

2.3 谓词介绍

和 SQL 语言一样,where 部分的查询条件如果过长,会显得很乱。CodeQL 提供一种机制可以让你把很长的查询语句封装成函数。这个函数,就叫谓词。

比如上面的案例,我们可以写成如下,获得的结果跟上面是一样的:

import java
 
predicate isStudent(Method method) {
   exists(|method.hasName("getStudent"))
}
 
from Method method
where isStudent(method)
select method.getName(), method.getDeclaringType()

语法解释:

  • predicate 表示当前方法没有返回值;
  • exists 表示子查询,是 CodeQL 谓词语法里非常常见的语法结构,它根据内部的子查询返回 true or false,来决定筛选出哪些数据。

2.4 污点分析

个人认为 CodeQL 作为静态代码分析工具,最核心的能力优势的就是可以实现污点分析。什么是污点分析?举个例子就明白了。

eval(md5($_POST['a']));

上述 PHP 代码 eval 函数可以执行系统命令,安全人员会重点关注、审计该类函数的参数是否外部可控,如果外部完全可控那么便是一个代码执行漏洞了。此例中 a 参数显然是外部传递过来的,但是此处并构不成代码执行漏洞,因为在传递给 eval 函数之前,程序调用 md5 函数对外部传入的参数进行了编码转换。

在这个例子中我们就引入了污点分析。污点分析可以抽象成一个三元组<sources,sinks,sanitizers>的形式:

  1. source 即漏洞污染链条的输入点:代表直接引入不受信任的数据或者机密数据到系统中(比如获取 http 请求的参数部分,就是非常明显的Source);
  2. sink 即漏洞污染链条的执行点:代表直接产生安全敏感操作(违反数据完整性)或者泄露隐私数据到外界(违反数据保密性),比如 SQL 注入漏洞,最终执行 SQL 语句的函数就是 sink (这个函数可能叫 query、exeSql 等);
  3. sanitizer 即无害处理:代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害(它又称为净化函数,简单说就是在整个的漏洞链条当中,如果存在一个方法阻断了整个传递链,那么这个方法就叫sanitizer)。

上述案例中,$_POST['a']为 source,eval()函数为 sink,md5 函数就是无害化处理的 sanitizer。

概括来说,污点分析就是:分析程序中由污点源引入的数据是否能够不经无害处理,而直接传播到污点汇聚点。如果不能,说明系统是信息流安全的;否则,说明系统产生了隐私数据泄露或危险数据操作等安全问题。

下文我们想编写的 QL 规则文件是排查 micro_service_seclab 项目中的 SQL 注入漏洞,下面来看看如何通过 QL 语法正确设置 source、sink 和检测 sanitizer。

1、设置Source

在 CodeQL 中我们通过以下方法来设置source:

override predicate isSource(DataFlow::Node src) {
}

思考一下,在我们的靶场系统 (micro-service-seclab) 中,source 是什么?

我们使用的是 Spring Boot 框架,那么 source 就是 http 参数入口的代码参数,在下面的代码中,source 就是 username:

@RequestMapping(value = "/one")
public List<Student> one(@RequestParam(value = "username") String username) {
    return indexLogic.getStudent(username);
}

本例中我们设置 Source 的代码为:

override predicate isSource(DataFlow::Node src) { 
    src instanceof RemoteFlowSource 
}

这是 SDK 自带的规则,里面包含了大多常用的 Source 入口。我们使用的 SpringBoot 也包含在其中,我们可以直接使用。

2、设置Sink

在 CodeQL 中我们通过以下方法设置 Sink:

override predicate isSink(DataFlow::Node sink) {

}

在本案例中,我们的 sink 应该为 query 方法 (Method) 的调用(MethodAccess),所以我们设置 Sink 为:

override predicate isSink(DataFlow::Node sink) {
   exists(Method method, MethodAccess call |
       method.hasName("query")
       and
       call.getMethod() = method 
       and
       sink.asExpr() = call.getArgument(0)
   )
}

注:以上代码使用了 exists 子查询语法,格式为 exists(Obj obj| somthing), 上面查询的意思为:查找一个 query() 方法的调用点,并把它的第一个参数设置为 sink。

在靶场系统 (micro-service-seclab) 中,sink 就是:

jdbcTemplate.query(sql, ROW_MAPPER);

因为我们测试的注入漏洞,当 source 变量流入这个方法的时候,才会发生注入漏洞!

3、Flow数据流

设置好 Source 和 Sink,就相当于搞定了首尾,但是首尾是否能够连通才能决定是否存在漏洞!一个受污染的变量,能够毫无阻拦的流转到危险函数,就表示存在漏洞!

这个连通工作就是 CodeQL 引擎本身来完成的。我们通过使用config.hasFlowPath(source, sink)方法来判断是否连通。比如如下代码:

from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"

我们传递给 config.hasFlowPath(source, sink) 我们定义好的 source 和 sink,系统就会自动帮我们判断是否存在漏洞了。

漏洞检测

介绍完基本的 QL 语法及污点分析过程后,下面来看看如何通过自定义的 QL 规则,检测出靶场系统的 SQL 注入漏洞。

3.1 初步结果

在 CodeQL 中,我们使用官方提供的 TaintTracking::Configuration 方法定义 source 和 sink,至于中间是否是通的,这个后面使用 CodeQL 提供的config.hasFlowPath(source, sink)来帮我们处理。

class VulConfig extends TaintTracking::Configuration {
  VulConfig() { this = "SqlInjectionConfig" }

  override predicate isSource(DataFlow::Node src) { 
     src instanceof RemoteFlowSource 
  }

  override predicate isSink(DataFlow::Node sink) {
    exists(Method method, MethodAccess call |
      method.hasName("query")
      and
      call.getMethod() = method 
      and
      sink.asExpr() = call.getArgument(0)
    )
  }
}

CodeQL 语法和 Java 类似,extends 代表集成父类TaintTracking::Configuration。这个类是官方提供用来做数据流分析的通用类,提供很多数据流分析相关的方法,比如 isSource(定义source),isSink(定义sink)src instanceof RemoteFlowSource 表示 src 必须是 RemoteFlowSource 类型。在 RemoteFlowSource 里,官方提供很非常全的 source 定义,我们本次用到的 Springboot 的 Source 就已经涵盖了。

最终第一版写的 QL 漏洞查询规则脚本 demo.ql 如下:

/**
 * @id java/examples/vuldemo
 * @name Sql-Injection
 * @description Sql-Injection
 * @kind path-problem
 * @problem.severity warning
 */

import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.QueryInjection
import DataFlow::PathGraph

class VulConfig extends TaintTracking::Configuration {
  VulConfig() { this = "SqlInjectionConfig" }

  override predicate isSource(DataFlow::Node src) { 
     src instanceof RemoteFlowSource 
  }

  override predicate isSink(DataFlow::Node sink) {
    exists(Method method, MethodAccess call |
      method.hasName("query")
      and
      call.getMethod() = method 
      and
      sink.asExpr() = call.getArgument(0)
    )
  }
}

from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"

注:上面的注释和其它语言是不一样的,不能够删除,它是程序的一部分,因为在我们生成测试报告的时候,上面注释当中的 name,description 等信息会写入到审计报告中。

最后来见证效果,通过上述规则脚本,Run Query 最终可拿到注入漏洞的信息。一共报了 5 处漏洞点,并展示了存在漏洞的受控参数从入口点到漏洞触发点的完整传递链路:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
批量产洞大概就是这样了吧……凭借如此详尽的数据信息,安全人员可以快速地判断出该结果是否是误报,并确认最终的有效漏洞的污点链路,从而给研发人员提供准确的修复建议。

3.2 解决误报

在上面自动审计出来的SQL注入漏洞当中,发现了一个误报问题。
在这里插入图片描述
这个方法的参数类型是List<Long>,不可能存在注入漏洞。这说明我们的规则里,对于List<Long>,甚至 List<Integer> 类型都会产生误报,source 误把这种类型的参数涵盖了。

我们需要采取手段消除这种误报,这个手段就是isSanitizer,它是 CodeQL 的类 TaintTracking::Configuration 提供的净化方法。它的函数原型是:

override predicate isSanitizer(DataFlow::Node node) {}

在 CodeQL 自带的默认规则里,对当前节点是否为基础类型做了判断。

override predicate isSanitizer(DataFlow::Node node) {
  node.getType() instanceof PrimitiveType or
  node.getType() instanceof BoxedType or
  node.getType() instanceof NumberType
}

表示如果当前节点是上面提到的基础类型,那么此污染链将被净化阻断,漏洞将不存在。

由于 CodeQL 检测 SQL 注入里的 isSanitizer 方法,只对基础类型做了判断,并没有对这种复合类型做判断,才引起了这次误报问题。那我们只需要将这种复合类型加入到 isSanitizer 方法,即可消除这种误报。

override predicate isSanitizer(DataFlow::Node node) {
    node.getType() instanceof PrimitiveType or
    node.getType() instanceof BoxedType or
    node.getType() instanceof NumberType or
    exists(ParameterizedType pt| node.getType() = pt and pt.getTypeArgument(0) instanceof NumberType )
}

以上代码的意思为:如果当前 node 节点的类型为基础类型,数字类型和泛型数字类型(比如 List<Long>)时,就切断数据流,认为数据流断掉了,不会继续往下检测。

重新执行query,我们发现刚才那条误报已经被成功消除:
在这里插入图片描述

关于 CodeQL 更多高级查询语法可参见:https://codeql.github.com/codeql-query-help/java/、CodeQL语法。

总结

可以看到,对于需要进行详细污点分析的漏洞模式,借助 CodeQL 进行漏洞排查是极其有效的。但是个人认为如果只是一些简单的漏洞特征匹配即可、不涉及污点分析的漏洞模式,直接使用 Python 脚本进行静态代码检索匹配反而更为快捷,毕竟 CodeQL 存在两个潜在的大时间成本:编译生成 AST 数据库、编写 QL 规则。

最后总结下使用 CodeQL 进行漏洞挖掘的主要流程:

  1. 使用 CodeQL 命令,根据目标源代码编译生成 database,该 database 包含整个代码的 AST 树,CodeQL 就是查询该 database 来进行漏洞发现的;
  2. 根据已知漏洞提炼出漏洞特征,并编写出 CodeQL 规则,该规则用以查询目标 database 找出类似的漏洞。在这一步有两个难点:一个是需要对漏洞进行总结归纳,提炼出漏洞特征,即是什么因素引发了漏洞;另一个是根据漏洞特征编写高质量的 CodeQL 规则,这里需要对 CodeQL 的规则的编写语法有着一定的熟悉;
  3. 根据 CodeQL 规则运行的结果进行代码审计,分析目标代码是否真正存在漏洞,确认漏洞的成因及触发条件。

本文参考文章:

  • CodeQL从入门到放弃;
  • CodeQL query help for Java;
  • 漏洞发现:代码分析引擎 CodeQL;
  • 深入理解CodeQL(Github上对CodeQL全网资源整合的项目);

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

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

相关文章

【学习笔记】jenkins持续集成入门

jenkins持续集成入门 文章目录学习源一、jenkins简介和安装安装&#xff1a;插件:安装插件&#xff1a;二、配置Jenkins系统邮箱三、使用jenkins实现持续集成&#xff08;一&#xff09;使用Jenkins实现简单的本地Python项目代码执行准备工作&#xff1a;使用Jenkins管理-手动构…

PHP开发工具PhpStorm v2022.3——完全支持PHP 8.2

PhpStorm是一个轻量级且便捷的PHP IDE&#xff0c;其旨在提高用户效率&#xff0c;可深刻理解用户的编码&#xff0c;提供智能代码补全&#xff0c;快速导航以及即时错误检查。可随时帮助用户对其编码进行调整&#xff0c;运行单元测试或者提供可视化debug功能。 PhpStorm v20…

PM说丨浅谈PDCA与Scrum的“异曲同工”之妙

文章目录一、前言二、PDCA与Scrum介绍1、 PDCA循环&#xff08;戴明环&#xff09;2、 Scrum三、PDCA与Scrum对比四、总结一、前言 笔者最近参与到一个生产制造型企业的ERP系统升级改造项目&#xff0c;实施过程中涉及到QMS与质量管理相关内容。 在了解质量管理体系的过程中发…

如何优雅地使用git?

文章目录Oh shit gitgitmojigit命令思维导图Oh shit git https://ohshitgit.com/ 这个网站针对一些在使用git中可能遇到的问题都做了详细介绍&#xff0c;并且形象生动。 例如&#xff1a;Oh shit&#xff0c;我想改个地方&#xff0c;但我已经提交&#xff08;commited&#…

现代C++ 05

智能指针与内存管理 1.1 RAII 与引用计数 了解 Objective-C/Swift 的程序员应该知道引用计数的概念。引用计数这种计数是为了防止内存泄露而产生的。 基本想法是对于动态分配的对象&#xff0c;进行引用计数&#xff0c;每当增加一次对同一个对象的引用&#xff0c;那么引用对…

云安全攻击手段及防御策略

恶意软件是我们必须面对的现实&#xff0c;我们每天都需要与蠕虫、病毒、间谍软件和其他行恶意软件作斗争&#xff0c;而云恶意软件是我们需要面对的又一种类别。它已经发展十多年&#xff0c;早在2011年就托管在亚马逊简单存储服务存储桶中。云安全提供商Netskope报告称&#…

SpringCloud01--黑马【上】

SpringCloud01 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff…

三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法

三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法 本次和大家分享三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法,由于汇川IT6000系列触摸屏组态软件中没有三菱FX5U系列PLC的连接驱动,所以采用MODBUS TCP通信的方式实现。 具体步骤可…

黄海冷水区微生物群落的季节演替及温度响应模式

期刊&#xff1a;Applied and Environmental Microbiology 影响因子&#xff1a;5.005 发表时间&#xff1a;2022 样本类型&#xff1a;水体 客户单位&#xff1a;中国海洋大学 凌恩客户中国海洋大学发表在《Applied and Environmental Microbiology》上的文章…

vue3 antd项目实战——table表格 根据属性值设置背景颜色【rowClassName添加行样式 + /deep/样式穿透 + css不可控】

根据数据属性值添加table表格行样式&#xff08;rowClassName&#xff09;知识调用场景复现利用rowClassName编写行样式编写行样式函数➕筛选条件编写特定的行样式取消相应的斑马纹样式知识调用 文章中可能会用到的知识链接vue3ant design vuets实战【ant-design-vue组件库引入…

如何检测时间序列中的异方差(Heteroskedasticity)

时间序列中非恒定方差的检测与处理&#xff0c;如果一个时间序列的方差随时间变化&#xff0c;那么它就是异方差的。否则数据集是同方差的。 异方差性影响时间序列建模。因此检测和处理这种情况非常重要。 让我们从一个可视化的例子开始。 下面的图1显示了航空公司乘客的时间…

Zotero快速入门

文章目录一、前言二、下载和安装Zotero三、界面初识和基本操作3.1 创建分类3.2 文献导入3.2.1 自动导入3.2.2 手动导入3.3 内置pdf管理3.4 同步3.5 插件3.5.1 安装方法3.5.2 插件推荐四、与word/wps协同引用文献4.1 使用内置格式4.1.1 添加索引4.1.2 添加书目4.2 自定义格式4.2…

基于AD Event日志监测域内信息探测行为

01、简介当攻击者获得内网某台域内服务器的权限&#xff0c;就会以此为起始攻击点&#xff0c;尽可能地去收集域的信息&#xff0c;以获取域控权限作为内网的终极目标。例如&#xff0c;攻击者会在内网中收集域管理员用户列表和特定敏感用户的信息&#xff0c;通过定位域管理员…

【c++】STL--vector

前言 想必大家已经对string有所了解了&#xff0c;string是专门用于字符串的。今天讲到的vector则是表示可变大小数组的序列容器。就像数组一样&#xff0c;vectoer也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组…

从根本上理解Synchronized的加锁过程

伸手摘星&#xff0c;即使一无所获&#xff0c;亦不致满手污泥。 请关注公众号&#xff1a;星河之码 作为一个Java开发&#xff0c;对于Synchronized这个关键字并不会陌生&#xff0c;无论是并发编程&#xff0c;还是与面试官对线&#xff0c;Synchronized可以说是必不可少。 …

顶刊实证复现:金融投资行为与企业技术创新 -动机分析与经验证据(思路梳理+全数据源+python代码)

标题&#xff1a;金融投资行为与企业技术创新 ——动机分析与经验证据 参考文献 作者&#xff1a;段军山 庄旭东 数据概况 1、数据来源&#xff1a; 第三方数据库 2、样本&#xff1a;2009-2018 中国 A 股市场的上市公司科技数据和财务数据 3、数据处理&#xff1a; (1)由…

Filter和Listener学习笔记

1.什么是Filter 2.定义过滤器 &#xff08;注意导的Filter的包来源是Javax.servlet&#xff09; /* 定义一个过滤器的步骤&#xff1a;1. 自定义一个类实现Filter接口2. 把过滤器规则定义在doFilter方法里面3. 使用WebFilter注解配置过滤的路径*///过滤的路径 //WebFilter(&qu…

用拙劣的Python技术画出的圣诞树(勿喷)

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 一、前言 今天晚上,准备睡觉的我看见了CSDN有活动了,我就立马飞奔到电脑前面 这不,CSDN又举办了一场活动,看着令人心动的奖励和丰富的勋章,我的口水都从眼睛里流出来了(夸张),我准备创造一颗圣诞树,但是又想到我…

「设计模式」责任链模式

「设计模式」责任链模式 文章目录「设计模式」责任链模式一、概述二、结构三、案例实现四、优缺点五、应用场景六、模拟过滤器机制七、拓展八、小结一、概述 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;为请求创建了一个接收者对象的链。这种模式给予…

高频时序数据的储存与统计方案

文章目录问题背景解决办法第一步&#xff0c;梳理数据和计算要求第二步&#xff0c;确定存储和计算方案第三步&#xff0c;确定技术选型和方案第四步&#xff0c;实施优化方案后记问题背景 发电设备中常常会放置传感器&#xff08;DCS&#xff09;来采集数据以监控设备运转的状…