网络靶场实战-Qiling Fuzz实例分析

背景

在上一小节中,介绍了qiling框架的背景和基础使用,并以相关的CTF和qilinglab实例进行练习加深对qiling框架的使用,后续并简单介绍了qiling fuzz的功能。

在这一小节,我们将对qiling fuzz iot设备进行测试以及以实例的方式对其进行学习。

qiling fuzz 基础

qiling和AFL++环境的搭建在前面的小节中已经说过,这里就不再演示。我们进入到qiling的qiling/example/fuzzing目录下,qiling框架官方库提供了几个fuzz的example供我们学习和测试。我们先对tenda ac15进行测试。

图片

根据README文档中的介绍,我们首先需要提取tenda ac 15文件系统并放置于脚本同级目录中,操作步骤如下:

1. wget https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
2. unzip US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
3. binwalk -e US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
4. mv xxx/squashfs-root ./rootfs;cd rootfs
5. rm -rf webroot;mv webroot_ro webroot
6. mv etc_ro etc

随后我们需要运行saver_tendaac15_httpd.py

图片

使用netstat -pantl查看监听端口,当发现python3程序正在监听8080端口时,说明tenda ac仿真成功。

图片

此时我们运行./addressNet_overflow.sh生成snapshot.bin文件。

图片

运行./fuzz_tendaac15_httpd.sh进行fuzz,经过10分钟左右出现了crash。

图片

产生的crash文件内容如下

图片

这样我们就完成对实例中tenda ac15的fuzz复现。官方提供demo的saver和fuzz脚本如下,现在我们对其进行简单分析并学习。

图片

图片

通过上一小节中对qiling基础的学习,我们可以对两个脚本中的函数功能进行拆分。

saver.py

保存快照

def save_context(ql, *args, **kw):
    ql.save(cpu_context=False, snapshot="snapshot.bin")

替换网卡名称

def patcher(ql):
    br0_addr = ql.mem.search("br0".encode() + b'\x00')
    for addr in br0_addr:
        ql.mem.write(addr, b'lo\x00')

检查停止地址

def check_pc(ql):
    print("=" * 50)
    print("Hit fuzz point, stop at PC = 0x%x" % ql.arch.regs.arch_pc)
    print("=" * 50)
    ql.emu_stop()

网络设置

def nvram_listener():
    server_address = 'rootfs/var/cfm_socket'
    data = ""
    
    try:
        os.unlink(server_address)
    except OSError:
        if os.path.exists(server_address):
            raise  

    sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
    sock.bind(server_address)
    sock.listen(1)
  
    while True:
        connection, client_address = sock.accept()
        try:
            while True:
                data += str(connection.recv(1024))
        
                if "lan.webiplansslen" in data:
                    connection.send('192.168.170.169'.encode())
                else:
                    break  
                data = ""
        finally:
                connection.close()

仿真流程

def my_sandbox(path, rootfs):
    ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
    ql.add_fs_mapper("/dev/urandom","/dev/urandom")
    ql.hook_address(save_context, 0x10930)
    ql.hook_address(patcher, ql.loader.elf_entry)
    ql.hook_address(check_pc, 0x7a0cc)
    ql.run()

fuzz.py

替换网卡名称

def patcher(ql):
    br0_addr = ql.mem.search("br0".encode() + b'\x00')
    for addr in br0_addr:
        ql.mem.write(addr, b'lo\x00')

fuzz流程

def main(input_file, enable_trace=False):
    # 生成qiling实例
    ql = Qiling(["rootfs/bin/httpd"], "rootfs", verbose=QL_VERBOSE.DEBUG, console = True if enable_trace else False)

    # 恢复快照内容
    ql.restore(snapshot="snapshot.bin")

    # 变异数据地址点定位
    fuzz_mem=ql.mem.search(b"CCCCAAAA")
    target_address = fuzz_mem[0]

    # target_address为fuzz变异点,place_input_callback函数通过afl++对数据进行变异
    def place_input_callback(_ql: Qiling, input: bytes, _):
        _ql.mem.write(target_address, input)
    # fuzz函数定义
    def start_afl(_ql: Qiling):
        ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])

    ql.hook_address(callback=start_afl, address=0x10930+8)

    # qiling实例运行
    try:
        ql.run(begin = 0x10930+4, end = 0x7a0cc+4)
        os._exit(0)
    except:
        if enable_trace:
            print("\nFuzzer Went Shit")
        os._exit(0)

通过功能的拆分以及我们的分析,可以知道fuzz大致流程是:

1.运行saver.py生成qiling实例仿真运行,此时运行addressNet_overflow.sh触发相关执行流程,当pc寄存器运行到0x10930地址时,触发保存快照功能。

2.fuzz.sh会调用afl++并执行fuzz.py脚本对其input输入进行数据变异。

3.fuzz.py脚本中,首先会恢复快照状态,并在内容中寻找数据变异点,并接受afl++的变异数据将其写入数据变异点进行fuzz。

了解了大致fuzz流程,我们可能存在几点疑虑:

1.saver.py脚本中如何知道在哪个地址触发保存快照功能?在仿真的httpd程序触发执行addressNet_overflow.sh执行流程后,程序将变异数据存储至内存完成后,就可以触发快照保存功能。 

2.addressNet_overflow.sh脚本中为什么定义page为CCCCAAAA?CCCCAAAA为poc的溢出标识,以便后续我们进行查找定位。

3.fuzz.py脚本中为什么先要替换br0?tenda ac15路由器设备启动时会检测br0网卡状态,我们本地没有这个网卡所以替换成了lo。

4.fuzz.py脚本中如何知道ql.run的起始和结束地址?起始地址是保存快照后面的指令,需要保证执行流程的连贯性(保存寄存器状态除外),结束地址便是漏洞函数可以触发crash后的函数结束地址。

这里1、4还是不太清楚,带着疑问我们接着往下分析:

根据addressNet_overflow.sh脚本中的poc,我们使用ida进行定义,发现漏洞函数如下,产生漏洞的原因便是没有对用户发送post包data数据中的entrys、mitInterface、page参数进行过滤,并使用sprintf危险函数进行了写入。

图片

那么我们要fuzz的函数就是formAddressNat函数了,首先第1点saver.py脚本中该如何定位保存地址点,这里其实当v1=sprintf(xxx)执行完毕后,已经将用户参数数据保存到v6中时,就已经可以保存快照了(后续fuzz.py也要进行相应修改)。这里作者定位的是0x10930,那么后续fuzz的起始地址和结束地址分别就是0x10930执行流程的后面下一条指令和formAddressNet函数的结束地址。

图片

在分析的过程中,我们可以打开QL_VERBOSE.DISASM来清楚的查看汇编指令的执行流程和对应指令的寄存器信息。

分析完tenda ac同理example中的dir815实例也是同样的流程,只不过dir815的fuzz脚本并没有使用保存快照功能,而是直接使用ql.mem.search进行查找变异数据点以及使用ql.mem.write对变异数据进行写入。

图片

图片

分析完上面的流程后,我们对fuzz的流程有了大概理解。后面我们以dlink dir645路由器中的两个栈溢出实例进行fuzz测试。

qiling fuzz 实例

以经典的dir645栈溢出为例,我们使用qiling框架对两个栈溢出漏洞进行fuzz测试。

首先下载固件并使用binwalk -Me 固件名进行提取,简单查看后发现本次分析的程序hedwig.cgi和authentication.cgi均为软链接(链接到htdocs/cgibin),qiling对软连接的处理不是很友好,建议将所有软连接替换为源文件。

hedwig.cgi栈溢出

我们首先将cgibin拖入ida进行简单分析,进入main函数后发现,main程序根据传入参数与相关"*.cgi"进行比较,随后进入相关的cgi_main函数中,那我们先分析一下hedwig.cgi触发的栈溢出

图片

fuzz的第一步就是摸清楚程序的执行流程,我们先简单编写仿真程序的脚本,随后将其改为fuzz脚本。该仿真脚本定义了俩个hook函数,当程序执行执行地址处后会执行该hook函数,并打印出"Hit at xxx func"。

图片

执行仿真脚本,发现我们定义的俩个hook都被触发,说明我们简单分析后的执行流程确实没错,并且调试信息后续还打印出了一下回应信息。

图片

我们继续在ida中查找定位该信息,发现是LABEL_25中的处理,根据交叉引用,我们追踪该信息产生的原因是env中没有REQUEST_METHOD

图片

图片

那么我们在env中设置该环境变量然后传入给qiling实例就可以了,接着往下分析发现程序的溢出点位于sess_get_uid中,并通过QL_VERBOSE.DISASM信息,我们理清楚了大概的产生漏洞流程。定位了栈溢出地址后,那么我们根据漏洞产生流程设置相关的env参数数据并传入qiling实例中,随后我们使用mem.search()替换成为变异数据,程序仿真时就会取出环境变量中的值进行处理从而产生栈溢出。

注:由于程序是从env中读取变量的值,所以也就不存在前面提到的拷贝到内存中然后触发保存快照功能指定流程,这里可以直接触发保存快照的功能。

图片

最终编写saver.py脚本如下:

import ctypes, os, pickle, socket, sys, threading
sys.path.append("..")
from qiling import *
from qiling.const import QL_VERBOSE


MAIN = 0x402770
HEDWIGCGI_MAIN = 0x40bfc0
SESSION_UID = 0x4083f0
SAVE_ADDRESS = 0x40c070

def test_print1(ql: Qiling)->None:
    print("Hit at main func")

def test_print2(ql: Qiling)->None:
    print("Hit at hedwig func")

def test_print3(ql: Qiling)->None:
    print("Hit at session uid func")

def saver(ql: Qiling):
    print('[!] Hit Saver 0x%X'%(ql.arch.regs.arch_pc))
    ql.save(cpu_context=False, snapshot='./context.bin')

def my_sandbox(path, rootfs):
    env_vars = {
            "REQUEST_METHOD": "POST",
            "REQUEST_URI": "/hedwig.cgi",
            "CONTENT_TYPE": "application/x-www-form-urlencoded",
            "REMOTE_ADDR": "127.0.0.1",
            "HTTP_COOKIE": "uid=AAAABBBB"
    }
    ql = Qiling(path, rootfs,env=env_vars,verbose=QL_VERBOSE.DEBUG)
    ql.hook_address(test_print1, MAIN)
    ql.hook_address(test_print2, HEDWIGCGI_MAIN)
    ql.hook_address(test_print3, SESSION_UID)
    ql.hook_address(saver, SAVE_ADDRESS)
    ql.run()

if __name__ == "__main__":
    my_sandbox(["rootfs/htdocs/web/hedwig.cgi"], "rootfs")

执行后,保存的快照为context.bin,我们可以使用strings定位栈溢出标识字符串。

图片

图片

接下来我们编写fuzz.py,前面我们触发快照的地址为getenv("REQUEST_METHOD") 执行后的一条指令,那么我们在编写fuzz.py中ql.run的起始地址时就应该为下一条指令,这里为了方便我直接让其跳过if判断直接从cgibin_parse_request处开始执行(0x40c0a4)。结束地址呢,这里直接指定hedwigcgi_main函数的结尾就可以(0x40c598),因为有溢出数据时程序执行到函数最后一定会触发crash。

图片

最终hedwig.cgi栈溢出fuzz.py的脚本如下:

import os, pickle, socket, sys, threading
sys.path.append("../../../")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz

def main(input_file, enable_trace=False):
    ql = Qiling(["rootfs/htdocs/web/hedwig.cgi"], "rootfs", verbose=QL_VERBOSE.DEBUG)
    ql.restore(snapshot="context.bin")
    fuzz_mem=ql.mem.search(b"AAAABBBB")
    target_address = fuzz_mem[0]

    def place_input_callback(_ql: Qiling, input: bytes, _):
        _ql.mem.write(target_address, input)

    def start_afl(_ql: Qiling):
        ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])

    ql.hook_address(callback=start_afl, address=0x40c0a4)
    
    try:
        ql.run(begin = 0x40c0a4, end = 0x40c598)
        os._exit(0)
    except:
        if enable_trace:
            print("\nFuzzer Went Shit")
        os._exit(0)

if __name__ == "__main__":
    if len(sys.argv) == 1:
        raise ValueError("No input file provided.")

    if len(sys.argv) > 2 and sys.argv[1] == "-t":
        main(sys.argv[2], enable_trace=True)
    else:
        main(sys.argv[1])

不到1分钟就fuzz到了crash,还是比较快的。

图片

authentication.cgi栈溢出

和上面的分析同理,我们首先跟一下程序的执行流程,authentication.cgi的处理函数为authenticationcgi_main函数。

图片

进入到authenticationcgi_main函数后,我们发现和上面的hedwig类似,也是同样获取env中的变量进行处理。

图片

那么我们将前面的脚本进行修改,这里直接将HEDWIGCGI_MAIN改为0x40afcc。

图片

运行后发现执行触发了俩个hook函数,说明确实执行到了authenticationcgi_main函数中。

图片

authentication.cgi触发栈溢出的执行流程为REQUEST METHOD方法为POST,并且需要设置"CONTENT_TYPE"和"CONTENT_LENGTH"环境变量。

图片

那么我们在env变量中设置如下参数并传入qiling实例。

注:CONTENT_LENGTH中的999在程序执行时还没有溢出,v73定义的1024字节。

图片

运行后发现已经执行我们想要其执行的流程了,并且需要我们输入一些信息才可执行后面的流程。

图片

图片

input中含有的内容如下,需要包含"id=xxx&password=xxx"

图片

图片

再次执行,输入"id=1&password=123"后,程序正常执行。那么我们的fuzz思路如下:

传入env环境变量,使其按照漏洞触发流程进行执行,随后在程序赋值content_length时,进行hook,将需要用到的寄存器修改成afl++变异数据的大小(其实这里应该取出所有header的字节,不过这里不是很影响),随后进行调用start_afl进行fuzz。写入栈溢出标识地址的content格式为:b"id=1&password="+input 

图片

根据上面的信息,我们编写的fuzz.py如下:

import ctypes, os, pickle, socket, sys, threading
sys.path.append("../../../")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions import pipe
from qiling.extensions.afl import ql_afl_fuzz


MAIN = 0x402770
AUTHENTICATION_MAIN = 0x40afcc
CONTENT_LENGTH = 0x40b48c
CONTENT_SIZE = 0x40b4b4
size = 0

def test_print1(ql: Qiling)->None:
    print("Hit at main func")

def test_print2(ql: Qiling)->None:
    print("Hit at authentication func")

def test_print3(ql: Qiling):
    print("address:",hex(ql.arch.regs.s0))

def test_print4(ql: Qiling):
    print("Hit at exit func")

def test_size(ql: Qiling):
    global size
    ql.arch.regs.s0 = size
    ql.arch.regs.a2 = size
    print("Hit at test_size func")

def main(input_file, enable_trace=False):
    env_vars = {
            "REQUEST_METHOD": "POST",
            "REQUEST_URI": "/authentication.cgi",
            "CONTENT_TYPE": "application/x-www-form-urlencoded",
            "REMOTE_ADDR": "127.0.0.1",
            "CONTENT_LENGTH": "100"
    }
    ql = Qiling(["rootfs/htdocs/web/authentication.cgi"], "rootfs",env=env_vars,verbose=QL_VERBOSE.DEBUG)
    ql.os.stdin = pipe.SimpleInStream(0)
    if not enable_trace:
        ql.os.stdout = pipe.NullOutStream(sys.stdout.fileno())
        ql.os.stderr = pipe.NullOutStream(sys.stderr.fileno())

    def place_input_callback(ql: Qiling, input: bytes, _: int):
        global size
        content = b"id=1&password="+input
        size = len(content)
        ql.os.stdin.write(content)
        ql.hook_address(test_size,CONTENT_SIZE)

    def start_afl(_ql: Qiling):
        ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])


    ql.hook_address(test_print1, MAIN)
    ql.hook_address(test_print2, AUTHENTICATION_MAIN)
    ql.hook_address(test_print3, CONTENT_LENGTH)
    ql.hook_address(test_print4,address=0x40bc90)

    ql.hook_address(callback=start_afl, address=AUTHENTICATION_MAIN)

    try:
        ql.run()
        os._exit(0)
    except:
        if enable_trace:
            print("\nFuzzer Went Shit")
        os._exit(0)


if __name__ == "__main__":
    if len(sys.argv) == 1:
        raise ValueError("No input file provided.")
    if len(sys.argv) > 2 and sys.argv[1] == "-t":
        main(sys.argv[2], enable_trace=True)
    else:
        main(sys.argv[1])

运行后发现,afl++给到的变异数据确实传入了进去。

但是fuzz了一会儿发现没crash,原来是read(fd=0x0,buf=0x7ff3c940,length=0x64),这里读取的length还是100,也就是说afl++不管变异多少数据都只读取100字节,这说明我们的hook有问题。

图片

打开QL_VERBOSE.DUMP模式,查看read时寄存器变量的值,确实hook没生效。那么我们直接在其调用read函数时hook,使其寄存器变成我们变异数据的长度就可以了。

图片

图片

重新改正脚本

import ctypes, os, pickle, socket, sys, threading
sys.path.append("../../../")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions import pipe
from qiling.extensions.afl import ql_afl_fuzz


MAIN = 0x402770
AUTHENTICATION_MAIN = 0x40afcc
CONTENT_LENGTH = 0x40b48c
CONTENT_SIZE = 0x40b4a8
size = 1000

def test_print1(ql: Qiling)->None:
    print("Hit at main func")

def test_print2(ql: Qiling)->None:
    print("Hit at authentication func")

def test_print3(ql: Qiling):
    print("address:",hex(ql.arch.regs.s0))

def test_print4(ql: Qiling):
    print("Hit at exit func")

def test_size(ql: Qiling):
    global size
    ql.arch.regs.s0 = size
    ql.arch.regs.a1 = size
    print("Hit at test_size func")

def main(input_file, enable_trace=False):
    global size
    env_vars = {
            "REQUEST_METHOD": "POST",
            "REQUEST_URI": "/authentication.cgi",
            "CONTENT_TYPE": "application/x-www-form-urlencoded",
            "REMOTE_ADDR": "127.0.0.1",
            "CONTENT_LENGTH": "100"
    }
    ql = Qiling(["rootfs/htdocs/web/authentication.cgi"], "rootfs",env=env_vars,verbose=QL_VERBOSE.DEBUG)

    ql.os.stdin = pipe.SimpleInStream(0)
    if not enable_trace:
        ql.os.stdout = pipe.NullOutStream(sys.stdout.fileno())
        ql.os.stderr = pipe.NullOutStream(sys.stderr.fileno())

    def place_input_callback(ql: Qiling, input: bytes, _: int):
        global size
        content = b"id=1&password="+input
        size = len(content)
        ql.os.stdin.write(content)

    def start_afl(_ql: Qiling):
        ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])


    ql.hook_address(test_print1, MAIN)
    ql.hook_address(test_print2, AUTHENTICATION_MAIN)
    ql.hook_address(test_print3, CONTENT_LENGTH)
    ql.hook_address(test_print4,address=0x40bc90)
    ql.hook_address(callback=start_afl, address=AUTHENTICATION_MAIN)
    ql.hook_address(test_size,CONTENT_SIZE)

    try:
        ql.run()
        os._exit(0)
    except:
        if enable_trace:
            print("\nFuzzer Went Shit")
        os._exit(0)

if __name__ == "__main__":
    if len(sys.argv) == 1:
        raise ValueError("No input file provided.")
    if len(sys.argv) > 2 and sys.argv[1] == "-t":
        main(sys.argv[2], enable_trace=True)
    else:
        main(sys.argv[1])

运行后,3分钟左右fuzz出crash。

图片

图片

综上,我们以实例的方式分析并fuzz了dir645路由器的俩个栈溢出漏洞,可能很多人觉得在fuzz时已经知道了漏洞点和执行流程,使用qiling进行fuzz有点多余。但是对于我们没有实体设备或者qemu不能完全仿真时,即使我们知道了漏洞点,我们也没法去简单测试或验证,那么这时qiling框架就是一个比较好的选择。这个小节中qiling 的fuzz思路像是在验证漏洞而且比较基础,而在真正fuzz漏洞时,也许我们可以hook危险函数并进行fuzz,又或者其他思路,这些就靠大家的思维拓展了。

总结

在这小节中,我们使用qiling框架分析并测试了tenda ac15、dir 815以及dir 645实例设备的栈溢出漏洞,掌握了在分析fuzz时的基础思路。熟练掌握qiling框架的使用,对于后续我们的漏洞测试方面还是有很多的帮助。

图片

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

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

相关文章

中级信息系统管理工程师-必会题锦集

文章目录 中级信息系统管理工程师-必会题锦集题目一CPU[解析]试题二 CPU[解析] 中级信息系统管理工程师-必会题锦集 题目一CPU CPU中(1)不仅要保证指令的正确执行,还要能够处理异常事件。 A. 运算器 B. 控制器 C. 寄存器组 D. 内部总线 [解…

1.C++入门(上)

目录 1.C关键字 2.命名空间 作用域方面的优化 a.命名空间定义 b.命名空间使用 3.C 输入&输出 1.C关键字 C有63个关键字,C语言有32个关键字,存在重叠如荧光笔标出 2.命名空间 作用域方面的优化 如果变量,函数和类的名称都存在于全…

SpringBootWeb请求

文章目录 前言一、Postman介绍 二、简单参数三、实体参数四、数组集合参数五、日期参数六、JSON参数七、路径参数 前言 在上一篇文章中,已经基于SpringBoot的方式开发一个web应用,浏览器发起请求 /hello 后 ,给浏览器返回字符串 “Hello Wor…

C++笔试强训day7

目录 1.字符串中找出连续最长的数字串 2.岛屿数量 3.拼三角 1.字符串中找出连续最长的数字串 链接 我的思路很简洁,就是双指针遍历,然后不断更新左位置left和右位置right和长度len。 然后我写代码的时候代码思路没跟上原本思路,直接把所有…

遇坑分享24.4.25

在对数组进行排序算法时&#xff0c;如果我使用多个下标进行元素交换的时候&#xff0c;可能会出错。 以下面的直接选择排序&#xff08;排列升序&#xff09;为例&#xff1a; public static void selectSort1(int[] arr){int left0;int rightarr.length-1;while(left<rig…

2024HWqax线上产品培训试题(天眼)

最近做了qax笔试题&#xff0c;分享一下&#xff0c;仅供学习参考&#xff0c;侵删

力扣HOT100 - 200. 岛屿数量

解题思路&#xff1a; 岛屿题目一般使用dfs。 1.判断是否越界 2.用0&#xff0c;1&#xff0c;2三个状态标识当前格子的状态&#xff08;三个状态比两个状态更清晰&#xff09; 3.向周围四个方向遍历 class Solution {public int numIslands(char[][] grid) {int cnt 0;fo…

【Spring篇 | 补充】三级缓存解决循环依赖

文章目录 7.三级缓存解决循环依赖7.1何为循环依赖&#xff1f;7.2三级缓存解析7.3三级缓存解决循环依赖7.3.1实例化A7.3.2创建B的需求7.3.3实例化B7.3.4注入A到B7.3.5B创建完成7.3.6回溯至A7.3.7清理二级缓存 7.4为什么不能用二级缓存解决循环依赖&#xff1f; 7.三级缓存解决循…

删除docker的容器与镜像

如果您想要卸载通过 docker pull influxdb 命令下载的 InfluxDB 容器&#xff0c;您需要执行以下步骤&#xff1a; 1. **停止正在运行的 InfluxDB 容器**&#xff1a; 首先&#xff0c;您需要停止任何正在运行的 InfluxDB 容器。您可以使用以下命令来查找正在运行的 InfluxD…

Xilinx 7系列 clock IP核的使用(二)

在 Clocking Wizard 中的输出时钟设置部分&#xff0c;主要目的是生成并配置系统所需的特定时钟频率和信号。这一功能在硬件设计和开发中非常关键&#xff0c;因为它允许用户精确地控制各个部分的时钟信号&#xff0c;以满足特定的性能、功耗和时序要求。 1 配置输出时钟 要启…

宝宝洗衣机买什么样的好?诚意推荐四款实力超群的婴儿洗衣机

近几年家用洗衣机标准容积的大大增加&#xff0c;从5Kg、6Kg升级到9Kg、10Kg。大容量洗衣机满足了家庭中清洗大件衣物、床上用品的需求。但由于普通大型洗衣机所洗衣物混杂&#xff0c;很多时候由于宝宝小件衣物数量不多&#xff0c;却也并不适合放在一起扔进大型洗衣机中清洗。…

macOS 一些系统图标的存放位置 icns

macOS 一些系统图标的存放位置 icns macOS 中有很多好看的图标&#xff0c;有时候就想用一下它&#xff0c;我来告诉你他们的具体位置。 系统图标位置&#xff0c;像各种通用文件类型的图标都在这里面&#xff0c;里面好多高清的系统图标 /System/Library/CoreServices/Core…

使用PlantUML绘制活动图、泳道图

最近在学PlantUML 太漂亮了 给大家欣赏一下 我也记录一下 startuml |使用前| start :用户打开旅游App; |#LightSkyBlue|使用后| :用户浏览旅游信息; |#AntiqueWhite|登机前| :用户办理登机手续; :系统生成登机牌; |使用前| :用户到达机场; |登机前| :用户通过安检; |#Light…

快速入门Web开发(中)后端开发(有重点)

你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github gitee 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我会尽力带来有趣的内容 CSDN 图片导入做的不是很好&#xff0c;因此如果有没有…

这个合租室友真的没有一点公德心,还好他搬走了

这个合租室友真的没有一点公德心&#xff0c;还好他搬走了 这个出租屋有四个房间。 有三个卧室&#xff0c;和一个隔断。 我住三个卧室中的一个。下图中右边那个就是我住的。 2023年下半年&#xff0c;左边那个屋子来了一个新租户小白。 在住的过程中&#xff0c;隔断间的租…

Pulsar Meetup 深圳 2024 会务介绍

“ Hi&#xff0c;各位热爱 Pulsar 的小伙伴们&#xff0c;Pulsar Meetup 深圳 2024 报名倒计时啦&#xff0c;快来报名。这里汇集了腾讯、华为和谙流科技等大量 Pulsar 大咖&#xff0c;干货多多&#xff0c;礼品多多&#xff0c;不容错过啊。 ” 活动介绍 由 AscentStream 谙…

华为ensp中链路聚合两种(lacp-static)模式配置方法

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月26日11点54分 链路聚合&#xff08;Link Aggregation&#xff09;&#xff0c;又称为端口聚合&#xff08;Port Trunking&#xff09;&#xff0c;是一种将多条物理…

C++:拷贝构造函数的初始化列表

拷贝构造函数的初始化列表是在拷贝构造函数的定义中出现的一组初始值&#xff0c;用于初始化新创建的对象的成员变量。它的语法是在构造函数的声明后面使用冒号&#xff08;:&#xff09;来开头&#xff0c;然后列出要初始化的成员变量和它们的初始值。初始化列表的优点在于它允…

Linux--进程控制(1)

文章衔接&#xff1a; Linux--环境变量-CSDN博客 Linux--地址空间-CSDN博客 目录 1.进程创建 2.进程的终止 2.1想明白&#xff1a;终止是在做什么&#xff1f; 2.2进程终止的三种情况 2.3 进程如何终止 3.进程等待 &#xff08;wait/waitpid&#xff09; 1.进程创建 在li…

vue中form表单中select下拉v-model绑定有数值,但下拉框不显示值的情况

vue中form表单中select下拉v-model绑定有数值&#xff0c;但下拉框不显示值的情况 场景复现&#xff1a; 我将后端获取的数据手动赋值值给select的下拉v-model绑定对象对应的值&#xff0c;但在前端下拉框不显示我赋值的通过v-model给的值&#xff0c;通过控制台打印v-mode的值…