视频讲解

这里下载视频讲解。提取码: 2333

起因

最近,即将举行网鼎杯,由于我们学校以前都没对安全方面的比赛进行重视,所以几乎没人玩CTF。现在老师们也打算筹建这么一支安全竞赛方面的队伍,所以搞个院赛看看人群中是否有大神存在。作为刚入门CTF的小萌新,我主动请缨搭建院赛做题环境(原因是对这个挺感兴趣,只不过非常菜。当然,我只是对这方面当作业余爱好玩玩题目涨涨见识,真想往这方面转已经来不及了)

PS:还是乖乖去做增删改查吧

环境搭建

采用开源的CTFd作为平台,按照官方文档安装后,对导航栏汉化了一部分。CTFd的功能还是挺多的,各种数据,图表都支持的非常好。

出题构思

出题都出的非常简单(其实是因为自己水平不行,出不出太难的😅)

签到题

一个摩斯密码

1
.. .-.. --- ...- . -.-. ... ..- ... -

厂里人都应该知道的

出题思路:降低了难度,flag没加密。找flag只要往IDA一扔。

源码(忽略变量命名不规范):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
using namespace std;

int main()
{
cout << "if you are CSUSTer,you should know the password. Now input it." << endl;
string a;
string b = "https://www.csust.edu.cn";
cin >> a;
if ( a == b ){
cout << "flag{csuster_jiu_shi_zhe_me_sa}" << endl;
}else{
cout << "wrong!" << endl;
}

return(0);
}

眼见为实

出题思路:生成一个假密码base64一下并拆分成一个个字符生成二维码,欺骗大家去解二维码的内容,其实找答案用记事本打开凯撒一下就OK。:-)哈哈哈哈

生成图片的源码:

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
import base64

import imageio
import qrcode
from PIL import Image


def save(string, imgs):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=0
)
qr.add_data(string)
qr.make(fit=True)

img = qr.make_image()
img = img.convert("RGBA")

icon = Image.open("csust.png")

img_w, img_h = img.size
factor = 4
size_w = int(img_w / factor)
size_h = int(img_h / factor)

icon_w, icon_h = icon.size
if icon_w > size_w:
icon_w = size_w
if icon_h > size_h:
icon_h = size_h
icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)

w = int((img_w - icon_w) / 2)
h = int((img_h - icon_h) / 2)
img.paste(icon, (w, h), icon)

img.save(imgs)


def create_gif(image_list, gif_name, duration=0.1):
frames = []
for image_name in image_list:
frames.append(imageio.imread(image_name))
imageio.mimsave(gif_name, frames, 'GIF', duration=duration)


str = '白忙活了,密码不在这里!眼见不一定为实!'.encode('utf-8')
bs64 = base64.b64encode(str).decode("utf-8")

png_list = []
for i, v in enumerate(bs64):
save(v, "data/%d.png" % i)
png_list.append("data/%d.png" % i)
create_gif(png_list, "result.gif")

生成图片后,追加了一个凯撒编码后的文本(偏移量+3)。

1
echo cixd{zprpq_flqixy_fp_sbov_dlla} >> result.gif

参禅悟道

作者:由sqs同学友情提供

出题思路:制作一个pptx文件,改后缀为zip后,往里面仍一个佛曰加密。pptx本来就是zip包啦,要不然咋pptx的体积比ppt小那么多,因为被压缩了。降低了难度,本来可以放在更里面的文件夹,伪装成配置文件的话可玩性可能更高。

扔的内容如下:

1
2
3
佛曰:爍冥心爍缽無冥故蘇漫切梵吉怯輸三梵蒙穆不怯槃爍怯跋奢究即侄楞奢
室皤般冥一婆知真怯逝摩冥度奢度諳薩侄知冥能怛蒙罰死盧滅實皤究娑明冥吉
夷逝侄依冥羯除俱夷奢特無故藐冥菩侄怖梵死三漫集怯夜怛以度尼

日记里的愿望

出题思路:小鹤双拼加字母转数字,第三个是音调。(刚入坑小鹤双拼)

1
2
|23,15,3|25,3,4|4,8,1|13,1,3|14,19,2|
|wǒ|yào|dāng|mǎ|nóng|

简单的压缩包

出题思路:想到长沙理工大学的合并日期,然后就出了这个题。压缩包密码是200304,可以自行蛮力法破解。然后是jsfuck编码(太长了,我就不贴了)。降低了难度,修改了文件日期是长沙理工大学合并日期作为密码提示。

你豪横你就消除222行

出题思路:以前做过一个坚持10秒的题还挺好玩,所以改编了一个这个。降低了难度,让大家直接可以搜222,本来还可以绕一绕的,让大家一个个去找函数可能更好玩。

改自此处的源码,加了个

1
2
3
if(this.lines == 222){
frame.setTitle(Encipher.DecodePasswd("ZK8(SCE1`u8IIK7&L1SdA TJQgXZ7_V>Y3"));
}

加密函数是网上随便找的,具体作者不详。

你是管理员吗

改自此处的源码,原来的源码有些错误,SQL约束攻击。只把flag注释了一部分,降低了难度。本来全部注释,或者把flag放在Header里可能更好玩。

理工大最强大脑非你莫属

出题思路:我是最强大脑粉丝(虽然好像很多都是假的),所以自己出了一个还算是有新意的题。对每次请求生成uuid传入前端,并把uuid作为键存入答案、ip(代码记录的ip用的是request.remote_addr,经过nginx代理后就是本地地址,所以正式开发应该注意获取由nginx注入的真实ip)、超时时间信息。前端每次提交都带上这个,以确定是否超时和答案的正确性。Python的字典是线程安全的,所以不用担心像Java的HashMap并发问题。

解题思路:写个油猴子脚本即可,Python也行,或者手速快也行的咯。

1
2
3
4
5
6
7
8
9
10
// ==UserScript==
// @name web2
// @match https://web2.looyeagee.cn/
// ==/UserScript==

(function() {
'use strict';
var sum=0;for(var i = 0;i<list.length-1;i++)sum+=list[i];
document.getElementsByName("sum")[0].value = sum;
})();

题目源码(Python):

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
# coding:utf8
import io
import json
import sys
import random
import time
import uuid
import base64
from flask import Flask, render_template, request

all_result = {}

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False
app.debug = True

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030')


@app.route('/', methods=['POST', "GET"])
def hello_world():
myuuid = uuid.uuid4()
list_rand = []
rand_sum = 0
for i in range(15):
suiji = random.randint(10000, 99999)
list_rand.append(suiji)
rand_sum += suiji
all_result[str(myuuid)] = {
"time": int(time.time()) + 12,
"sum": rand_sum,
"ip": request.remote_addr
}
return render_template("new.html", l=str(base64.b64encode(json.dumps(list_rand).encode("utf-8")), "utf-8"),
u=myuuid)


@app.route('/submit', methods=['POST'])
def submit():
rand_sum = request.form.get("sum")
myuuid = request.form.get("u")

if rand_sum is not None and myuuid is not None and len(rand_sum) >= 5 and len(myuuid) == 36 and all_result.get(
myuuid) is not None:
temp = all_result.get(myuuid)
if str(temp["sum"]) == rand_sum and temp["time"] > int(time.time()):
temp["success"] = True
return render_template("submit.html", text="flag{csuster_ni_zhen_kuai!}")
return render_template("submit.html", text="要么你算错了,要么你超时了噢!(或者你乱提交东西!)")


@app.route('/get_json', methods=['GET'])
def get_json():
return json.dumps(all_result)


if __name__ == '__main__':
app.run(port=5678)

new.html(请忽略我用过时标签,太懒了不想写样式)

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
<html>
<head>
<title>你是理工大的最强大脑吗</title>
</head>
<body>
<center><h1><span>请在数字显示完毕5秒内提交这些数字累加之和</span></h1></center>
<center><h1><span id="s" style="color:red;">预备!</span></h1></center>
<form action="/submit" method="POST">
<input name="u" type="hidden" value="{{u}}"/>
<center><input name="sum" type="number"/></center>
<center><input type="submit"/></center>
</form>
<script>

var list = eval(window.atob('{{l}}'));
list.push("快输入答案吧!");

function change(s) {
document.getElementById("s").innerText = s;
}

for (var i = 0; i < list.length; i++) {
(function (i) {
setTimeout(() => change(list[i]), 500 * (i + 1))
})(i)
}

</script>
</body>
</html>

submit.html(请忽略我用过时标签,太懒了不想写样式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>looyeagee版权所有</title>
</head>
<body>
<center>
<h1>
{{text}}
</h1>
</center>
</body>
</html>

运气爆棚

攻防世界原题lottery,作了汉化和小改动:把原有的git泄漏改成了www.zip

审计代码api.php,发现弱类型比较,把传入的用户输入的数字构造成[true,true,true,true,true,true,true]即可。

你来我家蹭WiFi吧!

出题思路:用aircrack-ng监听网卡并抓包。包是自己抓的,密码还真是我家WiFi密码(到现在也没改噢)

aircrack-ng很强大,可以监听WiFi(当然前提是你的网卡得支持),然后把别人踢下线,趁别人重连时,获取握手包来跑密码,简直是蹭网神器。(小提醒:大家还是不要连陌生的WiFi,别人可以搞个假dns服务器,引导你去假的网站,而且别人可以很容易获取你请求的信息的,当然加密协议除外。我们应该使用Https协议来访问网站,而且一定不能忽略证书错误提示。)

解题思路:用aircrack-ng跑字典即可。

儿时的回忆

出题思路:用电脑蓝牙给手机传个文件。svg是在线制作的,故意把字体调成白色嘻嘻嘻。降低了难度,本来可以修改一下svg的图层的高度为1,这样啥都看不到。让大家自行尝试高度可能更好玩。

解题思路:用WireShark过滤obex包,找到传文件的那条包文,利用value的十六进制字符串转成二进制文件取出flag.zip即可,或者直接用binwalk分离文件。我把难度降低了,一般蓝牙是分包发送的,不过我的flag文件太小,所以一次性就发完了。大文件的话binwalk是分不出来的,因为数据被拆分了。

looyeagee.cn

出题思路:域名加上TXT记录,并将flag16进制编码了一下。

解题思路:nslookup -q=TXT looyeagee.cn

然后解码即可

PWN

攻防世界原题

nc ctf.looyeagee.cn 7001

执行ls看到flag

cat flag即可

图1:pwn

啥事留个言呗

WP:https://blog.csdn.net/weixin_43940853/article/details/105121265