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

news/2024/5/6 7:56:36/文章来源:https://blog.csdn.net/weixin_39190897/article/details/128435897

文章目录

  • 前言
  • 环境搭建
    • 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 javafrom 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 javafrom Method method
select method

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

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

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

2.3 谓词介绍

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

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

import javapredicate 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")andcall.getMethod() = method andsink.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")andcall.getMethod() = method andsink.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::PathGraphclass 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")andcall.getMethod() = method andsink.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 ornode.getType() instanceof BoxedType ornode.getType() instanceof NumberType
}

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

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

override predicate isSanitizer(DataFlow::Node node) {node.getType() instanceof PrimitiveType ornode.getType() instanceof BoxedType ornode.getType() instanceof NumberType orexists(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.luyixian.cn/news_show_240096.aspx

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

相关文章

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.1 消息的可靠投递 7.1.1 confirm【确认模式】

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.1 消息的可靠投递7.1.1 confirm【确认模式】第二天 高级 7 RabbitMQ 高级特性 7.1 消息的可靠投递 7.1.1 confirm【确认模式】 在使用 Ra…

【数据预处理】基于Pandas的数据预处理技术【california_housing加州房价数据集】_后9个任务

文章目录一.需求分析二.需求解决2.1 对第一个特征&#xff08;收入中位数&#xff09;排序后画散点图2.2 对第一个特征&#xff08;收入中位数&#xff09;画分位数图并分析2.3 【选做】对所有特征画分位数图并进行分析2.4 使用线性回归方法拟合第一个特征&#xff08;收入中位…

【C语言进阶】指针练习题

写在前面 这是指有关指针的小题 正文 练习一 int main() {int a[5][5];int (*p)[4];pa;printf("%p,%d", &p[4][2]-&a[4][2], &p[4][2]-&a[4][2] );return 0; } 解析&#xff1a; a[4][2]为如图粉色部分&#xff0c;p[4][2]为如图蓝色部分。a的…

Java项目:springboot药品管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目属于前后端分离的项目&#xff0c;分为两个角色药品管理员和取药处人员 药品管理员&#xff1a; 登录、退出、药品信息录入、药厂信息录入…

买不到的数目(蓝桥杯C/C++A组真题详解)

题目详细&#xff1a; 题目思路&#xff1a; 对于这个题有一个定理 如果 a,b 均是正整数且互质&#xff0c;那么由 axby&#xff0c;x≥0&#xff0c;y≥0 不能凑出的最大数是 &#xff1a; a*b-a-b 具体的证明过程这里就不赘述 感兴趣的同学可以自行查找 这里就提供一种思…

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.2 Consumer Ack7.2.1 Consumer Ack7.2.2 Consumer Ack 小结7.2.3 消息可靠性总结第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack 7.2.…

C#语言实例源码系列-伪装文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

matlab神经网络求解最优化,matlab神经网络训练数据

1、神经网络的准确率是怎么计算的&#xff1f; 其实神经网络的准确率的标准是自己定义的。 我把你的例子赋予某种意义讲解&#xff1a; 1&#xff0c;期望输出[1 0 0 1]&#xff0c;每个元素代表一个属性是否存在。像着4个元素分别表示&#xff1a;是否肺炎&#xff0c;是否肝…

你可能不知道的DOM断点调试技巧

前言 作为一个前端&#xff0c;DOM断点应该是我们非常熟悉的&#xff0c;也是我们日常工作中经常要用到的一种调试技巧&#xff1b;但是下面这些DOM断点调试技巧你可能不知道&#xff0c;且听我一一道来。 监听元素 有这样一种场景&#xff0c;当DOM中某个元素移除或者元素属…

数据结构---图

&#xff08;一&#xff09; 相关知识点 图&#xff08;graph&#xff09;&#xff1a;图是由顶点的有穷非空集合和顶点之间边的集合组成&#xff0c;通常表示为&#xff1a;G(V,E)&#xff0c;其中&#xff0c;G表示一个图&#xff0c;V是图G中的顶点的集合&#xff0c;E是图G…

从模型到服务——iDesktopX处理自动化工具实现BIM模型到三维服务发布

目录前言一、 处理自动化模型二、 算子参数设置1、 使用迭代数据集打开导出后的BIM模型2、 移除重复点、重复面和重复子对象3、 模型生成缓存4、 三维切片缓存发布5、 执行结果前言 BIM模型在SuperMap实际使用的业务流程中常常需要在桌面产品中生成缓存&#xff0c;然后通过iS…

QT多窗口编程与文件IO编程

目录 一、消息对话框 QMessageBox&#xff08;掌握&#xff09; 二、常用窗口类&#xff08;掌握&#xff09; 三、主窗口类 QMainWindow&#xff08;重点&#xff09; 四、parent参数&#xff08;掌握&#xff09; 五、窗口传参 5.1 成员函数/构造函数 5.2 信号槽传参 六、事件…

Android开发进阶——binder通讯学习

什么是binder 通常意义下&#xff0c;binder指的是一种通信机制对Server端来说&#xff0c;Binder指的是Binder本地对象&#xff0c;对于Client端来说&#xff0c;Binder指的是Binder代理对象对于传输过程而言&#xff0c;binder是可以跨进程传输的对象 Binder的基本原理 Bi…

MySQL 管理

文章目录启动及关闭 MySQL 服务器MySQL 用户设置/etc/my.cnf 文件配置管理MySQL的命令启动及关闭 MySQL 服务器 首先&#xff0c;我们需要通过以下命令来检查MySQL服务器是否启动&#xff1a; ps -ef | grep mysqld如果MySql已经启动&#xff0c;以上命令将输出mysql进程列表…

node.js+uni计算机毕设项目基于微信小程序的美甲预约系统(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

Docker安装Zookeeper教程(超详细)

生命无罪&#xff0c;健康万岁&#xff0c;我是laity。 我曾七次鄙视自己的灵魂&#xff1a; 第一次&#xff0c;当它本可进取时&#xff0c;却故作谦卑&#xff1b; 第二次&#xff0c;当它在空虚时&#xff0c;用爱欲来填充&#xff1b; 第三次&#xff0c;在困难和容易之…

【Linux】进程间通信之共享内存

目录&#x1f308;前言&#x1f338;1、System V共享内存&#x1f361;1.1、概念&#x1f362;1.2、原理&#x1f33a;2、共享内存相关函数和指令&#x1f361;2.1、shmget函数&#xff08;创建&#xff09;&#x1f362;2.2、shmctl函数&#xff08;控制&#xff09;&#x1f…

【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里?

相关博客 【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里&#xff1f; 【自然语言处理】【ChatGPT系列】Chain of Thought&#xff1a;从大模型中引导出推理能力 【自然语言处理】【ChatGPT系列】InstructGPT&#xff1a;遵循人类反馈指令来训练语言模型 【自然语言处理…

基于HTML5 技术的开放自动化HMI

人机交互接口&#xff08;HMI&#xff09;是自动化系统中不可或缺的一部分。传统的做法是提供一个HMI 显示屏&#xff0c;并且通过组态软件来配置显示屏的功能&#xff0c;通过modbus 或者以太网与PLC 连接。 现在&#xff0c;事情变得复杂了许多&#xff0c;用户不仅需要通过专…

linux共享内存的使用

共享内存可以由多个程序同时访问的内存&#xff0c;能够避免进程间通信过程中的冗余数据拷贝&#xff0c;是IPC中最快的一种,特别适合用来作大块数据的传输。共享内存可以映射到不同的进程空间&#xff0c;这些进程间的数据传递就不再涉及内核。这个过程其实是把同一块物理内存…