CodeQL从入门到入土

news2024/11/24 16:47:02

为什么在现在写这文章

CodeQL传闻找到了Log4j的漏洞,这段时间上边要求,把公司系统内部常见的问题用CodeQL写检测脚本,用于系统长期检测。主要是记录这段时间的学习,以及自己总结的常用写法。

一个需求,不同人写出来的脚本可能完全不同,各种内置库用法多样,表达式和参数等各种类型之间的转换也很麻烦,本文会提供案例一步一步从分析需求一步一步走下去。

CodeQL是什么

如果你已经了解CodeQL是什么,可以直接跳过这个章节。

当谈及代码分析和漏洞检测工具时,CodeQL无疑是一款备受推崇的解决方案。作为一种革命性的语义代码查询语言,CodeQL在软件安全领域展现出了卓越的实力。

语义分析的特点是,搜索规则能在一定程度上理解代码上下文,内置的数据流判断十分强大,也可以自行补充各种例外场景。最基础的脚本需要定义,source(输入源),sink(污染点),比如检测SSRF漏洞,source为外部用户输入,sink为创建URL链接的点,可能是new URL(),也可能是其他的不在默认库里的,可自行添加。

CodeQL是由GitHub开发的一种强大的静态代码分析工具。它基于高级数据流分析技术,可深入理解代码结构、语义和行为。这意味着CodeQL能够超越传统的基于规则或模式匹配的静态分析方法,更全面地检测代码中潜在的安全风险和缺陷。

它提供了一个灵活的查询语言,使开发者能够针对不同编程语言和框架编写自定义的代码查询。通过CodeQL,开发者可以发现诸如内存泄漏、空指针引用、SQL注入等常见的漏洞,并及时修复这些问题,从而提高代码的质量和安全性。

与其他工具相比,CodeQL具有独特的优势。首先,它不仅仅是一个工具,而是一个完整的静态分析平台,提供了丰富的内置库和查询示例,帮助开发者快速上手。其次,CodeQL支持多种编程语言,包括C、C++、Java、Python等,使其适用于各种项目和团队。此外,CodeQL还具备可扩展性,可以根据具体需求进行定制和扩展,以应对不同项目的特殊需求。

CodeQL安装

CodeQL本身包含两部分解析引擎+SDK。

1、官方规则库,各种内置的ql脚本,这部分是开源的,地址:codeql-sdk

1706804974_65bbc6eea53ee2569726b.png!small?1706804975346

默认推荐将路径添加进path环境变量(多个版本另外说)。

1706804994_65bbc7026a52c137b6798.png!small?1706804995628

命令行运行codeql -v,输出结果说明安装成功。

2、数据库编译引擎,不开源,只有二进制执行文件。将源代码转换为CodeQL脚本能识别的抽象语法树。

地址:codeql-cli

下面以java为例,利用codeql引擎对java代码进行编译,在pom文件目录执行。

codeql database create java-database --language=java --command="mvn clean install -Dmaven.test.skip=true --settings 路径/setting.xml"

源码目录会生成 java-database目录,打开看看里面有src.zip文件才算编译成功。

因此,编写一个最简单的CodeQL脚本,需要代码中指定SDK路径,编写代码后用解析引擎运行。

编译中的注意点:

1、源码目录不能有中文

2、网络问题导致编译错误,比如公司内部网络可能要加证书啥的

CodeQL基本语法&常用语法总结

基本语法

CodeQL的查询语法有点像SQL语法,基本结构如下:

import <language> /*导入对应的语言包*/
from [datatype] vat /*构建数据类型表,便于理解可以认为是声明变量*/
where condition[var = something] /*设置逻辑表达式*/
select var /*打印结果*/

其实就三个步骤,定义数据类型,设置条件,进行查询

谓词

在CodeQL中谓词可以说是最常见的概念,叫做 Predicates,可以理解为类似函数。PS:谓词首字母要小写。

谓词也分为有返回词和无返回词(下面有例子)

先说无返回值的,个人比较常用。

个人拙见说下无返回值谓词的作用。CodeQL的查询大概是这么个流程,定义一张大的数据表,然后根据脚本一步一步缩小数据表的内容,同时构建各种数据之间的关系,最后把满足条件的数据查询出来。那谓词的作用,就是用来缩小数据范围,也就是做限定。最简单的例子,定义一张整数类型的数据表,然后限制数据只能在1-10之间,这就是无返回值谓词的作用,用于限定数据集

比如:

predicate isList(Parameter p){                      //声明谓词,入参为参数类型
    p.getType().toString().indexOf("List<") != -1   //要求参数的类型有List字样
}
//所以这个谓词的作用是,限制入参是List类型

class Vul extends TaintTracking::Configuration{
    override predicate isSource(DataFlow::Node source){
	exists(
            Parameter p | isList(p)     //无返回值谓词,通常用于限制,常配合exists使用
            and p = source.asParameter()//存在参数p,满足谓词isList的限制
        )
    }
}

有返回值的谓词。

其实就是类似函数,没有 predicate关键词,多了一个特征词 result,result的值就是这个谓词的返回结果。

int test(int i){
    result = i + 1
    and i in [1..19]
}
select test(3)  //输出4

大概是这样的形式,等用到的时候再多试试。

CodeQL的写法是很灵活的。举个例子,打印1到10之间的数字。

用类的写法是这样:

import java
class Mynum extends int{
    Mynum(){
        this in [1..10]
    }
}
from int i
where i instanceof Mynum
select i

用无返回值谓词写法是这样:

import java
predicate myNum(int i){
    i in [1..10]
}
from int i
where myNum(i)
select i

用返回值谓词的写法是这样:

import java
int myNum(int i){
    result = i
    and i in [1..10]
}
from int i
select myNum(i)

这几种写法结果是一样的

类的定义

CodeQL里面的类不是建立一个对象,更类似建立一个数据集,类型取决于继承的类,基本可以继承任意类,包括boolean、float、int、string等基本类型。举个例子,定义Mybatis的xml文件。

class MyBatisMapperXmlFile extends XmlFile{     //继承XmlFile,定义为一个xml文件
    MyBatisMapperXmlFile(){                     //定义是一个怎么样的xml文件
        count(XmlElement e|e=this.getAChild())=1 and  //要求xml文件有<mappeer>节点
    	this.getAChild().getName()="mapper"
    }
}
class MyBatisMapperXmlElement extends XmlElement{          //定义为一个xml元素
    MyBatisMapperXmlElement(){				   //定义是怎么样的xml元素
        this.getFile() instanceof MyBatisMapperXmlFile
//定义xml元素属于MyBatisMapperXmlFile
    }
}

迭代

就是类调用自己,通常用在嵌套场景。比如类成员变量里还有类,多层嵌套。

+和*的含义如下:

parentOf+(p),表示对变量p应用一次或多次谓词parentOf,等价于ancestorOf(p)。

parentOf*(p),表示对变量p应用零次或多次谓词parentOf,要么返回p的祖先,要么是变量p自身。

示例:

比如已经定义了parentOf(),用于求出某个人的父母,那么可以借助其定义childof:

Person childOf(Person p){
    P = parentOf(result)
}
// 在此基本上可以定义祖先
Person ancestorOf(Person p){
    result = parentOf(p) or
    result = parentOf(ancestorOf(P))
}
//  再定义亲属
Person relativeOf(Person p){
    parentOf*(result) = parentOf*(p)
}

这部分有点抽象,看不懂没关系,后续有案例

常见语法总结

方法描述
Method方法类,获取当前项目中所有的方法,获取的是方法声明
MethodAccess(老2.13.1)方法调用类,获取所有的方法实际调用,比如List.add(),add就是方法调用
MethodCall(老2.13.1)方法调用类,获取所有的方法实际调用,比如List.add(),add就是方法调用
Parameter参数类,Parameter表示获取当前项目当中所有的参数
Annotation注解类,获取所有注解,一般用于判断特定注解或获取切面路由
Expr表达式类,所有的有值、有类型统称为表达式,能跟各种类型互相转换
XmlFileXML文件,很多项目都用得到,比如mybatis的$占位符

那么每个类怎么去看有什么方法呢?

1、直接看官网文档,关键词搜

2、直接看依赖库源代码的说明

两者内容基本一样,但前者比较方便查询。

1706805787_65bbca1b044ae6a7670fc.png!small?1706805787658

1706805795_65bbca23aadf3c9bb8371.png!small?1706805796397

这够直观了吧。列举几个常用的,如果看文档看没看到就找份实际跑下:

MethodCall方法描述
getAnArgument获取方法调用的所有参数
getArgument获取指定参数,比如getArgument(0)获取第一个参数
getEnclosingCallable获取包含此调用方法的类或是方法
getMethod获取方法的实现,MethodCall是方法的调用
getQualifier获取方法调用的主体,即谁调用的

这里吐个槽,CodeQL更新还是比较快的,真的有点佛,这就导致了很多问题,用最新版的话,很多以前的参考代码运行不了,而且每次更新最要命的是,很多类直接就删了或是改名字,不是简单的增加或删除几个谓词,是直接类名就改了,我水平低还没看出改名字的必要性。

之前让ChatGPT根据需求简单写个QL脚本,根本运行不了,很多语法都变了。写这文章的时候才发现不久前写的脚本一些类(MethodAccess)在官方文档找不到了,原来是改了名字(MethodCall)。

不同版本CodeQL切换的注意点

用于生成database的codeql.exe版本和codeql规则代码版本需要保持一致

1、新建个文件夹,放最新的codeql-cli,和codeql的依赖库

2、用最新你的codeql-cli去编译数据库

3、vscode里QL插件的设置要改,要重新配置codeql-cli的路径(没改是执行不了最新语法的)

继承&实现

在CodeQL中看源码经常有种写法,定义一个抽象类,然后由其他类去继承。

而代码中用 instanceof 判断的是抽象类,实际上判断都是所有继承抽象类的其他类的限制

比如输入流,RemoteFlowSource,这是系统内置用来获取外部输入流的

// 定义抽象类原创输入流
abstract class RemoteFlowSource extends DataFlow::Node {
  abstract string getSourceType();
}
// 继承抽象类,限制为外部输入流
private class ExternalRemoteFlowSource extends RemoteFlowSource {
  ExternalRemoteFlowSource() { sourceNode(this, "remote") }
  override string getSourceType() { result = "external" }
}
// 继承抽象类,限制为RMI类型的输入
private class RmiMethodParameterSource extends RemoteFlowSource {
  RmiMethodParameterSource() {
    exists(RemoteCallableMethod method |
      method.getAParameter() = this.asParameter() and
      (
        this.getType() instanceof PrimitiveType or
        this.getType() instanceof TypeString
      )
    )
  }
  override string getSourceType() { result = "RMI method parameter" }
}

大多都直接限制所有类为外部输入流,也可以额外自己补充特定输入流。

override predite isSource(DataFlow::Node source){ source instanceof RemoteFlowSource}

污点追踪

什么是source和sink?代码自动化审计的污点分析中,最核心的三元组概念,就是(source、sink、sanitizer)。

source是指漏洞污染链条的输入点,比如外部可控变量,入参等,就是非常明显的source。

sink是指漏洞污染链条的执行点,比如SQL注入漏洞,最终执行SQL语句的函数就是sink(这个函数可能叫query或者exesql,或是其他自定义封装的)

sanitizer又叫净化函数,是指在整个漏洞链条当中,如果存在一个方法阻断了整个传播链,就叫sanitizer。

再补充一个isAdditionalTaintStep,用于强制把两个节点关联,比如节点A是污染点,节点B是节点业务特性需求点,实际上也是污染点,但CodeQL内部的数据流关联没把这两个点关联,导致节点B没被识别为污染点。这时候就能用isAdditionalTaintStep强制关联两个节点了。

class TestVul extends TaintTracking::Configuration{
    TestVul(){
        this = "Test"
    }
    predicae isTaintedString(Expr expSrc, Expr expDest){
        // 想要强制关联的两个表达式的关系
    }
    override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2){
        isTaintedString(node1.asExpr(), node2.asExpr())
    }
    override predicate isSource(DataFlow::Node Source){
        // source.asParameter
        // source.asExpr
    }
    override predicate isSink(DataFlow::Node sink){
        // sink.asParameter
        // sink.asExpr
    }
}

CodeQL常用句式

这部分是个人比较常用的,以后会持续补充,做个记录,便于查询。

先谈点CodeQL脚本的编写思路,四个字由内到外,比如编写一个检测 mybatis $ 占位符的脚本,而且要关联到 java 代码的数据流,不是简单地检测所有相关 mapper xml文件有无$字符。因此需要梳理相关数据流,其中比较关键的是,怎么让 xml 对应的方法和 java 代码的方法相关联。

具体分析下需求,最习惯的思路是,获取所有的数据流,判断所有相关的方法是否有进行数据库操作,再获取相关的 mapper xml 文件,一步一步正向获取,但这种思维来写CodeQL非常容易卡壳。实际上写法是由内到外,先判断所有相关 mappe xml文件,再去找对应的方法,判断数据流,就是把小的数据先搜索到再对比是否属于那个大的目标

java代码和xml文件关联

// java代码和xml文件关联
// codeql-main\java\ql\src\semmle\code\xml\MyBatisMapperXML.qll
class MyBatisMapperSqlOperationWithProgram extends MyBatisMapperXmlElement{
    MyBatisMapperSqlOperationWithProgram(){
        this instanceof MybatisMapperSqlOperation // xml 文件是数据库相关的
    }
	
    // 根据xml文件中的update、detele、select、insert元素找到对应的java方法
    // <select id="findStuCount" resultType="java.lang.Integer">
    Method getMethod(){
        result.getName() = this.getAttribute("id").getValue() and // 获取id指定的方法
        result.getDeclaringType() = this.getParent().(MyBatisMapperXmlElement).getNamespaceRefType()
	// getDeclaringType 获取抽象类的接口声明
	// getNamespaceRefType 获取mapper文件中对应的方法
	// <mapper namespace="com.ttice.icewkment.mapper.ArticleClassMapper">
    }
}

获取指定注解

import java
class PostAnn extends Annotation{
    PostAnn(){
this.getType().hasQualifiedName("org.springbootframework.web.bind.annotation","PostMapping")
    // 指定注解类包名,注解类名
    }
}

获取指定方法

import java
class JalorProgramCheckMethod extends Method{
    JalorProgramCheckMethod(){	  this.hasQualifiedName("com.ttice.icewkment.service","ArticleService","GetList")
	// 指定包名、类名、方法名
    }
}

显示源码位置

import java
from Call c, Method m
where m = c.getCallee() and m.hasName("insert")
select c,c.getLocation.getFile().getRelativePath()+":"+c.getLocation().getStartLine(),c.getCaller()

查询某个类型的变量

import java
from Variable v, PrimitiveType pt
where pt = v.getType() and pt.hasName("int")
select v,v.getLocation()

查询类,成员参数有集合类型

import java
import semmle.code.java.Collections
// 定义一个字段,字段是Collections类型
class Listfield extends Field{
    Listfield(){
        // CollectionType 是 java.util.Collection 参数化的引用类型
        this.getType() instanceof CollectionType
    }
}
// 带有list字段的类
class ClassWithList extends Class{
    ClassWithList(){
        // 类中有List字段,或者继承的类有list,或者字段类有list
        exists(Field f | this.getAField() = f and f instanceof Listfield) or 
	exists(ClassWithList svo | this.getAnAncestor = svo) or 
	exists(Field f, ClassWithList svo | this.getAField() = f and f.getType()=svo)
    }
}
from Class c
where c instanceof ClassWithList
select c

上面这些组装来组装去也差不多,实在找不到的话去看看官方文档。

CodeQL实际案例

由上面可知,CodeQL是强项在于,你十分了解漏洞或是不规范代码的写法,并且中间还要有数据流向的判断,不然直接用IDEA全局搜不也挺方便,CodeQL还要编译。

所以这里就选了个非常清晰的小需求。批量操作场景下的参数个数检测,分析需求如下:

1、任意入参可当作 source,因为中间可能有字符串分割,比如通过逗号分隔成 List类型

2、最终是要进行数据库操作(增删查改),这里假定源码是springboot框架,数据库操作用的是mybatis,设定的场景是集合类型入参(有一种场景是String入参,在mybatis进行分割查询,这类型先不讨论)

3、需要分析入参跟最后数据库操作的数据流,并分析是否有@size注解

代码如下:

/**
 * @id java/examples/vuldemo
 * @name Dos
 * @description Dos
 * @kind path-problem
 * @problem.severity recommendation
 * @tags security
 */
 import java
 import semmle.code.java.dataflow.FlowSources
 import DataFlow::PathGraph
 // 去除set方法
 class NoSetClass extends Parameter{
    NoSetClass(){
        not(
            this.getCallable().getReturnType().toString() = "void"
            and this.getCallable().toString().matches("set%")
            and this.getCallable().getNumberOfParameters() = 1 
        )
    }
 }
 // 获取参数,要求没有注解或是有注解但注解不是Size
 class NoAnnOrnotAn extends Parameter{
    NoAnnOrnotAn(){
        exists(
            Annotation an | not an.getType().hasName("Size")
            and this=an.getTarget()
        )
        or not exists(
            Annotation an|this=an.getTarget()
        )
    }
 }
 // 实际获取的入参,用上面的条件限制
 class ListParameter extends Parameter{
    ListParameter(){
        this.getType() instanceof CollectionType
        and this instanceof NoAnnOrnotAn
        and this instanceof NoSetClass
    }
 }

 class Batch_Dos extends TaintTracking::Configuration{
    Batch_Dos(){
        this = "FuckDos"
    }
    // source类型声明
    override predicate isSource(DataFlow::Node source){
        source.asParameter() instanceof ListParameter
    }
	// sink定义为dao操作,涉及集合类型
    override predicate isSink(DataFlow::Node sink){
        exists(MethodAccess m,Expr e | sink.asExpr()=e
            and m.getAnArgument().getType() instanceof CollectionType
            and m.getAChildExpr().toString().indexOf("Dao") = m.getAChildExpr().toString().length() - 3
            and e = m.getAnArgument()
        )
    }
}

from Batch_Dos batch, DataFlow::PathNode source, DataFlow::PathNode sink
where batch.hasFlowPath(source,sink)
select source.getNode(),source,sink,"source"

题外话

初入计算机行业的人或者大学计算机相关专业毕业生,很多因缺少实战经验,就业处处碰壁。下面我们来看两组数据:

  • 2023届全国高校毕业生预计达到1158万人,就业形势严峻;
  • 国家网络安全宣传周公布的数据显示,到2027年我国网络安全人员缺口将达327万。

一方面是每年应届毕业生就业形势严峻,一方面是网络安全人才百万缺口。

6月9日,麦可思研究2023年版就业蓝皮书(包括《2023年中国本科生就业报告》《2023年中国高职生就业报告》)正式发布。

2022届大学毕业生月收入较高的前10个专业

本科计算机类、高职自动化类专业月收入较高。2022届本科计算机类、高职自动化类专业月收入分别为6863元、5339元。其中,本科计算机类专业起薪与2021届基本持平,高职自动化类月收入增长明显,2022届反超铁道运输类专业(5295元)排在第一位。

具体看专业,2022届本科月收入较高的专业是信息安全(7579元)。对比2018届,电子科学与技术、自动化等与人工智能相关的本科专业表现不俗,较五年前起薪涨幅均达到了19%。数据科学与大数据技术虽是近年新增专业但表现亮眼,已跻身2022届本科毕业生毕业半年后月收入较高专业前三。五年前唯一进入本科高薪榜前10的人文社科类专业——法语已退出前10之列。

“没有网络安全就没有国家安全”。当前,网络安全已被提升到国家战略的高度,成为影响国家安全、社会稳定至关重要的因素之一。 

网络安全行业特点

1、就业薪资非常高,涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万!

2、人才缺口大,就业机会多

2019年9月18日《中华人民共和国中央人民政府》官方网站发表:我国网络空间安全人才 需求140万人,而全国各大学校每年培养的人员不到1.5W人。猎聘网《2021年上半年网络安全报告》预测2027年网安人才需求300W,现在从事网络安全行业的从业人员只有10W人。

行业发展空间大,岗位非常多

网络安全行业产业以来,随即新增加了几十个网络安全行业岗位︰网络安全专家、网络安全分析师、安全咨询师、网络安全工程师、安全架构师、安全运维工程师、渗透工程师、信息安全管理员、数据安全工程师、网络安全运营工程师、网络安全应急响应工程师、数据鉴定师、网络安全产品经理、网络安全服务工程师、网络安全培训师、网络安全审计员、威胁情报分析工程师、灾难恢复专业人员、实战攻防专业人员…

职业增值潜力大

网络安全专业具有很强的技术特性,尤其是掌握工作中的核心网络架构、安全技术,在职业发展上具有不可替代的竞争优势。

随着个人能力的不断提升,所从事工作的职业价值也会随着自身经验的丰富以及项目运作的成熟,升值空间一路看涨,这也是为什么受大家欢迎的主要原因。

从某种程度来讲,在网络安全领域,跟医生职业一样,越老越吃香,因为技术愈加成熟,自然工作会受到重视,升职加薪则是水到渠成之事。

黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

 1.学习路线图 

 攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。 

 因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。 

 还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

 因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取 

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

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

相关文章

二叉树-距离是K的二叉树节点(hard)

目录 一、问题描述 二、解题思路 1.总体思路&#xff08;DFSBFS结合&#xff09; 2.下面举具体例子来对思路进行解释 (1)返回值在一侧的情况 (2)返回值在两侧的情况 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 1.总体思路&#xff08;DFSBFS结合&#xff0…

【2024亲测无坑】Oracle--19C在Centos7上的静默安装(rpm版)

一、Oracle 19c Linux安装&#xff08;Centos 7&#xff09; 1.查看磁盘可用空间及配置ip地址 [rootlocalhost /]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 1.4G 0 1.4G 0% /dev tmpfs 1.4G …

Docker-Portainer可视化管理工具

Docker-Portainer可视化管理工具 文章目录 Docker-Portainer可视化管理工具介绍资源列表基础环境一、安装Docker二、配置Docker加速器三、拉取Portainer汉化版本镜像四、运行容器五、访问可视化界面 介绍 Portainer是一款开源的容器管理平台&#xff0c;它提供了一个直观易用的…

Nature|高性能柔性纤维电池 (柔性智能织物/可穿戴电子/界面调控/柔性电池/柔性电子)

2024年4月24日,复旦大学彭慧胜(Huisheng Peng)院士团队,在《Nature》上发布了一篇题为“High-performance fibre battery with polymer gel electrolyte”的论文,陆晨昊(Chenhao Lu)、Haibo Jiang和Xiangran Cheng为论文共同第一作者。论文内容如下: 一、 摘要 用聚合物凝…

基于Spring Boot的智能分析平台

项目介绍&#xff1a; 智能分析平台实现了用户导入需要分析的原始数据集后&#xff0c;利用AI自动生成可视化图表和分析结论&#xff0c;改善了传统BI系统需要用户具备相关数据分析技能的问题。该项目使用到的技术是SSMSpring Boot、redis、rabbitMq、mysql等。在项目中&#…

AMD平台,5600X+6650XT,虚拟机安装macOS 14(2024年6月)

AMD平台安装macOS 14的麻烦&#xff0c;要比Intel平台多的多&#xff0c;由于macOS从13开始&#xff0c;对CPU寄存器的读取进行了改变&#xff0c;导致AMD平台只要安装完macOS 13及以后版本&#xff0c;开机后就报五国语言错误&#xff0c;不断重启。改vmx文件&#xff0c;被证…

基于springboot的学生宿舍管理系统(带 1w+字文档)

基于springboot的学生宿舍管理系统(带 1w字文档) 基于 springbootvue 前后端分离的学生宿舍管理系统&#xff1a;前端 vue2、elementui&#xff0c;后端 maven、springmvc、spring、mybatis&#xff1b; 项目简介 本项目可供学习参考&#xff0c;商业慎用。项目带完整安装部署…

Python基础教程(二十二):XML解析

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

微服务架构思考

时间&#xff1a;2024年06月16日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频地址&#xff1a; https://xima.tv/1_HvQZkj?_sonic0https://xima.tv/1_HvQZkj?_sonic0 大家好&#xff0c;欢迎来到小蒋聊技术&#xff0c…

Vue - 实现登录页面

1、技术框架 1、技术框架Vue-Cli Vue3.0 2、界面推荐大小&#xff1a; 1920 * 1080 3、UI组件&#xff1a;elementui 4、icon: element-plus/icons-vue 5、node版本&#xff1a;v20.14.0 2、效果图 3、源代码部分截图 4、其他 有需要的请联系作者。需要购买&#xff0c;不白…

ABBYY Finereader 15软件安装包下载

软件简介&#xff1a; FineReader PDF提供实用、简易的工具&#xff0c;将纸质文档和PDF结合起来&#xff0c;提高了数字工作场所的效率。 FineReader 15最大特色是采用了ABBYY最新推出的基于AI的OCR技术&#xff0c;可以更轻松地在同一工作流程中 对各种文档进行数字化、检索…

明日周刊-第13期

在这期间发生了很多的事&#xff0c;导致拖更了一周。接下去努力不断更&#xff0c;哈哈哈希望如此。配图是最近上映的一部电影《狗阵》的海报&#xff0c;看完之后感悟颇深&#xff0c;希望大家都能去电影院感受一下。 文章目录 一周热点资源分享言论歌曲推荐 一周热点 最近一…

跨语言翻译的突破:使用强化学习与人类反馈提升机器翻译质量

在人工智能领域&#xff0c;知识问答系统的性能优化一直是研究者们关注的焦点。现有的系统通常面临知识更新频繁、检索成本高、以及用户提问多样性等挑战。尽管采用了如RAG&#xff08;Retrieval-Augmented Generation&#xff09;和微调等技术&#xff0c;但它们各有利弊&…

类Copy方法:BeanUtils.copyProperties

类Copy方法&#xff1a;BeanUtils.copyProperties 需求场景 比如有时候我们想要把数据库里面的数据导出到excel表中&#xff0c;比如想要把数据库中的用户数据导出到excel表格中&#xff1b; 假设我们程序代码中与数据库对接的实体类是User&#xff0c;用于展示到前端的实体类…

aarch64系统中给qt编译的可执行程序加上图标

在qt中编译的可执行程序图标是默认是一种格式 而且无法替换改图标&#xff0c;看起来不够美观&#xff0c;可以使用.desktop的链接文件来链接编译的执行程序&#xff0c;通过点击.desktop图标来去运行可执行程序。 实现步骤&#xff1a; 创建一个以.desktop结尾的文件并记得给…

Es 索引查询排序分析

文章目录 概要一、Es数据存储1.1、_source1.2、stored fields 二、Doc values2.1、FieldCache2.2、DocValues 三、Fielddata四、Index sorting五、小结六、参考 概要 倒排索引 优势在于快速的查找到包含特定关键词的所有文档&#xff0c;但是排序&#xff0c;过滤、聚合等操作…

室内定位技术解析:蓝牙信标在室内导航中的应用

室内定位技术&#xff0c;作为现代导航领域的重要突破&#xff0c;解决了GPS在室内空间定位的局限&#xff0c;为我们提供了一种全新的空间认知和利用方式。本文将以蓝牙技术为例&#xff0c;深入解析室内定位的工作原理、关键技术和系统构成&#xff0c;以及在现代导航中的应用…

库的制作 与 使用 (Linux下)

目录 动静态库的制作 前置知识 库的基本构造 问题 分析 要给什么文件 如何更好的让别人使用 库的生成 静态库的生成 makefile参考 动态库的生成 makefile参考&#xff08;包含动态库和静态库生成&#xff09; 库的使用 法一&#xff1a;放入系统路径 弊端 法二…

【MATLAB】语法

MATLAB 基本语法(%{和%}) 赋值 函数名值&#xff1b;for for i1:10循环语句 end//while x0; sum0; while x<100sumsumx;x; end//if if x > 1f x^2 1; elsef 2 * x endswitch onum input(请输入一个数); switch num case -1 //注意case后面没有冒号disp(I am…

[Linux] TCP协议介绍(3): TCP协议的“四次挥手“过程、状态分析...

TCP协议是面向连接的 上一篇文章简单分析了TCP通信非常重要的建立连接的"三次握手"的过程 本篇文章来分析TCP通信中同样非常重要的断开连接的"四次挥手"的过程 TCP的"四次挥手" TCP协议建立连接 需要"三次握手". "三次挥手&q…