DeadSec CTF 2024-MISC-Writeup

2 篇文章 0 订阅
1 篇文章 0 订阅

本次比赛的官网在https://deadsec.ctf.ae/,有需要的可以在里面下载源代码以及题目。

mic check

这道题是让你输入字符之后,经过一定判断,只有正确才能让你输入下一个字符,字符的长度也是随之增加的。起先我以为这道题是考察的字符串顺序的转换,但到后面发现并不对,这道题考察的是输入字符串的速度,随着输入,需要输入的字符串逐渐增多,靠手敲是完成不了的,所以我们需要脚本来帮我们实现。

from pwn import *

#将34.69.226.63 31914变成列表
#s[0] = 34.69.226.63
#s[1] = 31914
s = "34.132.190.59 32346".split()

#这行代码的目的是创建一个远程连接
p = remote(s[0], int(s[1]))

#因为要完成100次,所以要循环100下
for i in range(100):
    #每循环一次,输出记录一次
    print(f"\rwaiting {i}",end="")
    #这行代码使用了p.recvuntil()方法,这个方法通常在pwntools这样的库中提供,用于接收网络连接中的数据直到遇到指定的分隔符。
    #作用是从与程序p建立的连接中接收数据,直到收到字节字符串b'submit test words > '为止
    line = p.recvuntil(b'submit test words > ')
    #连接之后,题目是一下这样
    #line.split()[3]刚好是v
    #split会默认按照空白字符(如空格、换行符等)分割字符串,并返回一个列表
    #mic test >  v [1/100]
    #submit test words > v
    c = line.split()[3]

    p.send(c+b"\n")

#end=""是一个参数,它告诉print函数在打印完成后不要添加任何额外的换行符。默认情况下,print函数在打印完毕后会自动换行
#p.recv()是调用一个网络连接对象p的recv方法。这个方法会接收来自网络的数据,直到没有更多的数据可读。
#.decode()是一个方法,它将字节字符串解码成普通字符串。通常,解码会使用UTF-8编码,但也可以使用其他编码方式。
print("\nthe flag is >> ",p.recv().decode(),end="")

脚本的实现思路我己经放在代码里面了,运行代码之后,需要一定时间的等待,我们就得到了flag

DEAD{mic is working!}

GoLParty

这是一个生命游戏,需要我们连续答对题目,这里有一个类似的脚本复现,我们将其修改之后,便可以用,一下是修改的脚本。

​
from pwn import *
import numpy as np
import sys

context.log_level = 'error'


class InfiniteGameOfLife:
    def __init__(self):
        self.live_cells = set()

    def add_live_cell(self, x, y):
        self.live_cells.add((x, y))

    def remove_live_cell(self, x, y):
        self.live_cells.discard((x, y))

    def get_neighbors(self, x, y):
        return [(x + dx, y + dy) for dx in range(-1, 2) for dy in range(-1, 2) if not (dx == 0 and dy == 0)]

    def count_live_neighbors(self, x, y):
        return sum((nx, ny) in self.live_cells for nx, ny in self.get_neighbors(x, y))

    def next_generation(self):
        new_live_cells = set()
        potential_cells = set()
        for cell in self.live_cells:
            potential_cells.add(cell)
            potential_cells.update(self.get_neighbors(cell[0], cell[1]))

        for cell in potential_cells:
            live_neighbors = self.count_live_neighbors(cell[0], cell[1])
            if cell in self.live_cells and live_neighbors in [2, 3]:
                new_live_cells.add(cell)
            elif cell not in self.live_cells and live_neighbors == 3:
                new_live_cells.add(cell)

        self.live_cells = new_live_cells

    def total_live_cells(self):
        return len(self.live_cells)


conn = remote('34.69.226.63', 30819)
conn.recvuntil(b'Game On :D\x1b[m\n\n')
while True:
    try:
        board = conn.recvuntil(b'\n\n[*] Enter', drop=True, timeout=1)
    except:
        print(conn.recvall())
        break
    board = board.replace(b'\xe2\x96\xa0', b'#')
    conn.recvuntil(b'live cells after ')
    itercount = conn.recvuntil(b' ', drop=True)
    conn.recvuntil(b'generations: ')

    itercount = int(itercount.decode())
    board = np.array([[1 if c == ord('#') else 0 for c in r] for r in board.strip().split(b"\n")])
    game = InfiniteGameOfLife()
    for x in range(35):
        for y in range(70):
            if board[x, y] == 1:
                game.add_live_cell(x, y)

    for i in range(itercount):
        game.next_generation()
    conn.sendline(str(game.total_live_cells()).encode())
    conn.recvuntil(b'[+] Correct!\n')
    print(f"correct! {itercount=} {game.total_live_cells()=}")
conn.close()
sys.exit()

​

DEAD{GoL_P4rty_W4s_4_Fun_4nd_1ntr1gu1ng_G4m3}

Welcome

这是一道签到题,没有什么可说的,根据题目所给的提示,flag就在rule聊天栏里面

DEAD{welcome_to_deadsec_ctf_2024}

Forgotten Password

题目的提示是

I was going to create this extremely easy forensics challenge for you, but accidentally used the flag as the password when I encrypted the archive. This flag is now deleted, and since it is not possible to brute-force it, I guess that means this challenge can no longer be solved, or can it?

The script to generate the challenge is included.

题目给了一个py脚本,以及一个有密码的压缩包

from io import BytesIO
import os
import subprocess
import pycdlib # pip install pycdlib

try:
    FLAG = open("flag.txt","r").read()
except FileNotFoundError:
    FLAG = "fake_flag_for_testing"

iso = pycdlib.PyCdlib()
iso.new(interchange_level=4)

iso.add_fp(BytesIO(FLAG.encode()), len(FLAG), '/flag.txt;1')

iso.write('challenge.iso')
iso.close()

subprocess.check_output(["zip", "challenge.zip", "challenge.iso", "-P", FLAG])

脚本的目的就是生成一个iso文件,而压缩包里面的文件就是iso文件,提示就可以考虑可能就是明文攻击,那么我们不妨先用脚本生成两个iso,观察其有没有线索,将两个生成的iso脚本放到010中观察,发现不同的点只有生成的时间,而比赛的iso不清楚时区,所以无法从这里得到有用的线索。

于是我们将iso压缩成zip文件,再将压缩包放到010中,发现有32字节的/x00


我们可以尝试使用bkcrack爆破,这个00字节虽然有32个,但是我们无法得知是在何处开始,我们使用多个zip文件进行比较,我猜测空字节从偏移量64开始,有32个,所以我只是选择了偏移量范围内的某个地方,在那里我们只需要得到我们已知的连续12个空字节,64或70也可以作为偏移量。

于是我们直接使用bkcrack脚本进行爆破,在这里需要注意变量的参数,68是偏移量,000000000000000000000000是已知的十六进制的字节。

.\bkcrack.exe -C .\challenge.zip -c challenge.iso -x 68 000000000000000000000000

得到key是6b13ebc5 cc0be8ac 709e18f9

.\bkcrack.exe -C .\challenge.zip -k 6b13ebc5 cc0be8ac 709e18f9 -D flag.zip

得到flag.zip之后,我们可以成功将其解压,得到challenge.iso,再将其放到010中,我们就可以看到flag

最终我们得到flag

DEAD{weird_how_this_encryption_is_the_default_in_2024}

Flag injection

这道题的提示是

I heard pyjails were too easy, so I made it harder by banning symbols. As a consolation, I'll let you change the flag :)

本题还给了一个python代码,如下:

from string import ascii_lowercase
from time import sleep
from os import getenv

ALPHABET     = set(ascii_lowercase + "_")
SECRET_FLAG  = getenv("FLAG", "DEAD{test_flag_which_is_exactly_this_long}")
SECRET_FLAG  = SECRET_FLAG.replace("{", "_").replace("}", "_").replace("DEAD","dead")

assert len(SECRET_FLAG) == 42, "Bad flag length"
assert set(SECRET_FLAG).issubset(ALPHABET), "Bad flag chars"

def get_flag():
    print(SECRET_FLAG)

def split_flag():
    start_offset = int(input("Start of flag substring: "))
    end_offset   = int(input("End of flag substring: "))
    new_flag     = SECRET_FLAG[start_offset:end_offset]
    assert       len(new_flag) >= 13, "Can't have such a small piece"
    anything     = input("Anything to add? Tell me: ").strip()[:20]
    assert       set(anything).issubset(ALPHABET), "That's a crazy thing to add!"
    new_flag     += anything
    globals()[new_flag] = ":)"

if __name__ == "__main__":
    split_flag()
    what_to_do = input("What should I do now? Tell: ")
    if not set(what_to_do).issubset(ALPHABET):
        print("Plz no hack :(")
    else:
        # No brute force for you. Test locally instead!
        sleep(10)
        print(eval(what_to_do))

我们来一点一点分析这道题的源代码

    start_offset = int(input("Start of flag substring: "))
    end_offset   = int(input("End of flag substring: "))
    new_flag     = SECRET_FLAG[start_offset:end_offset]
    assert       len(new_flag) >= 13, "Can't have such a small piece"

这段代码的意思就是输入一个开始的数字,输入一个结束的数字,两个数字的差要小于13,并且结束的数字不能大于42,那么我们从0开始。

anything  = input("Anything to add? Tell me: ").strip()[:20]

在此时输入的值的长度不能超过20,所以构造20长度的任意字符串

what_to_do = input("What should I do now? Tell: ")

他会根据你输入的What should I do now? Tell:猜测你想要的东西。
我们所要得到的flag的格式是DEAD{XXXX},但是在代码的最前面我们发现,他将DEAD和{}全都替换成了dead以及下划线,所以flag的格式就要变成dead_XXXX_

SECRET_FLAG  = getenv("FLAG", "DEAD{test_flag_which_is_exactly_this_long}")
SECRET_FLAG  = SECRET_FLAG.replace("{", "_").replace("}", "_").replace("DEAD","dead")


那么我们不妨告诉它dead[注意在这里是有长度限制],然后不停的引导题目把flag都告诉我们

最后拼接起来就是

dead_ivswjlvahxmifksxjgifrzfhljkdprcaubac_

DEAD{ivswjlvahxmifksxjgifrzfhljkdprcaubac}

MAN in the middle

题目所给的提示是

Do you know that even the signals without encryption are vulnerable to the MAN in the middle attack?

首先拿到的是一个音频文件,放到Audacity里面,将波形放大,发现有两个有规律的波形

将其放到010中,观察其十六进制,发现大量的\xFF\x7F和\x01\x80,去掉头部,保存为flag.data,把他转换成01串,以下是转化字符串的脚本:

def convert_waveform_to_binary(input_file, output_file):
    with open(input_file, 'rb') as f:
        data = f.read()

    binary_data = []
    for i in range(0, len(data), 88):
        sample = data[i:i+88]
        if sample == b'\xFF\x7F' * 44:
            binary_data.append('1')
        elif sample == b'\x01\x80' * 44:
            binary_data.append('0')
        else:
            print(f"Unexpected value: {sample[:8]}... (showing first 8 bytes)")

    binary_string = ''.join(binary_data)

    with open(output_file, 'w') as f:
        f.write(binary_string)

    print(f"Decoded binary data written to {output_file}")

convert_waveform_to_binary('flag.data', 'output.txt')

得到大量的01字符串并且保存在output.txt里面,然后我们发现生成的01串是由10和10组成,那么我们直接按照01和10替换成1和0就行。

with open('output.txt', 'r') as file:
    binary_str = file.readline().strip()

converted_str = ""

for i in range(0, len(binary_str), 2):
    pair = binary_str[i:i + 2]
    if pair == "10":
        converted_str += "0"
    elif pair == "01":
        converted_str += "1"
    else:
        pass

print(converted_str)

得到:

0110110101100001011011100110001101101000011001010111001101110100011001010111001000100000011001010110111001100011011011110110010001101001011011100110011100100000011010010111001100100000011000010010000001101101011001010111010001101000011011110110010000100000011011110110011000100000011001010110111001100011011011110110010001101001011011100110011100100000011001000110100101100111011010010111010001100001011011000010000001100100011000010111010001100001001000000110100101101110001000000111011101101000011010010110001101101000001000000110010101100001011000110110100000100000011000100110100101110100001000000110111101100110001000000110010001100001011101000110000100100000011010010111001100100000011100100110010101110000011100100110010101110011011001010110111001110100011001010110010000100000011000100111100100100000011101000111011101101111001000000111011001101111011011000111010001100001011001110110010100100000011011000110010101110110011001010110110001110011001011000010000001100101011011100111001101110101011100100110100101101110011001110010000001100001001000000111010001110010011000010110111001110011011010010111010001101001011011110110111000100000011000010111010000100000011101000110100001100101001000000110110101101001011001000110010001101100011001010010000001101111011001100010000001100101011000010110001101101000001000000110001001101001011101000010000001110000011001010111001001101001011011110110010000101110001000000111010001101000011010010111001100100000011101000111001001100001011011100111001101101001011101000110100101101111011011100010000001110011011001010111001001110110011001010111001100100000011000010111001100100000011000100110111101110100011010000010000001100001001000000110001101101100011011110110001101101011001000000110000101101110011001000010000001100100011000010111010001100001001000000111001101101001011001110110111001100001011011000010110000100000011011010110000101101011011010010110111001100111001000000110100101110100001000000110100001101001011001110110100001101100011110010010000001100101011001100110011001100101011000110111010001101001011101100110010100100000011001100110111101110010001000000111001101111001011011100110001101101000011100100110111101101110011011110111010101110011001000000110001101101111011011010110110101110101011011100110100101100011011000010111010001101001011011110110111000101110001000000110010001100101011101100110010101101100011011110111000001100101011001000010000001100010011110010010000001100111001011100010000001100101001011100010000001110100011010000110111101101101011000010111001100101100001000000110110101100001011011100110001101101000011001010111001101110100011001010111001000100000011001010110111001100011011011110110010001101001011011100110011100100000011010010111001100100000011101110110100101100100011001010110110001111001001000000111010101110011011001010110010000100000011010010110111000100000011101100110000101110010011010010110111101110101011100110010000001100011011011110110110101101101011101010110111001101001011000110110000101110100011010010110111101101110001000000111000001110010011011110111010001101111011000110110111101101100011100110010110000100000011010010110111001100011011011000111010101100100011010010110111001100111001000000110010101110100011010000110010101110010011011100110010101110100001011100010000001101001011101000111001100100000011100000111001001101001011011010110000101110010011110010010000001100001011001000111011001100001011011100111010001100001011001110110010100100000011011000110100101100101011100110010000001101001011011100010000001101001011101000111001100100000011100100110111101100010011101010111001101110100011011100110010101110011011100110010000001100001011001110110000101101001011011100111001101110100001000000111010001101001011011010110100101101110011001110010000001100101011100100111001001101111011100100111001100100000011000010110111001100100001000000110010101100001011100110110010100100000011011110110011000100000011000110110110001101111011000110110101100100000011100100110010101100011011011110111011001100101011100100111100100101100001000000110000101110011001000000111010001101000011001010010000001110010011001010110011101110101011011000110000101110010001000000111010001110010011000010110111001110011011010010111010001101001011011110110111001110011001000000110010101101110011000010110001001101100011001010010000001110100011010000110010100100000011100100110010101100011011001010110100101110110011001010111001000100000011101000110111100100000011011010110000101101001011011100111010001100001011010010110111000100000011100110111100101101110011000110110100001110010011011110110111001101001011110100110000101110100011010010110111101101110001000000111011101101001011101000110100000100000011101000110100001100101001000000111010001110010011000010110111001110011011011010110100101110100011101000110010101110010001011100010000001100010011110010010000001100101011011010110001001100101011001000110010001101001011011100110011100100000011101000110100001100101001000000110001101101100011011110110001101101011001000000111001101101001011001110110111001100001011011000010000001110111011010010111010001101000011010010110111000100000011101000110100001100101001000000110010001100001011101000110000100100000011100110111010001110010011001010110000101101101001011000010000001101101011000010110111001100011011010000110010101110011011101000110010101110010001000000110010101101110011000110110111101100100011010010110111001100111001000000110110101101001011101000110100101100111011000010111010001100101011100110010000001110100011010000110010100100000011100100110100101110011011010110010000001101111011001100010000001110011011110010110111001100011011010000111001001101111011011100110100101111010011000010111010001101001011011110110111000100000011011000110111101110011011100110010110000100000011011010110000101101011011010010110111001100111001000000110100101110100001000000110000100100000011100100110010101101100011010010110000101100010011011000110010100100000011000110110100001101111011010010110001101100101001000000110011001101111011100100010000001101000011010010110011101101000001011010111001101110000011001010110010101100100001000000110010001101001011001110110100101110100011000010110110000100000011001000110000101110100011000010010000001110100011100100110000101101110011100110110110101101001011100110111001101101001011011110110111000101110001000000110000101101110011001000010000001101000011001010111001001100101001000000110100101110011001000000111100101101111011101010111001000100000011001100110110001100001011001110011101000100000011001000110010101100001011001000111101101101101001101000110111001100011011010000011001100110101001101110011001101110010010111110011010001011111001101110110100000110011010111110111011100110001011011100111110100100000011001110110111101101111011001000010000001101010011011110110001000100001

然后将其二进制转ascii码即可得到flag

DEAD{m4nch3573r_4_7h3_w1n}

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值