宁波市第六届网络安全大赛2023|Writeup

是谁520还在打CTF呀🫵

Misc

ZIP

拿到附件是一个zip压缩包,根据提示,可以判断密码可能需要爆破,并且在9位之内,字符集为{0,1}

接下来使用ARCHPR来爆破ZIP密码:

密码长度设置为9,爆破字符集自定义为01:

很快密码就爆破出来了,ZIP密码为01001101

flag{c0c1371022c8c1be946cdf4084423370}

BeautifulImage

打开附件是一张图片:

第一反应是LSB,使用StegSolve.jar打开分析该图片,发现了LSB隐写:

复制出来直接base64解密:

flag{24edd76e46c22c65cc5bddd3c6e4f6f3}

SimpleDocument

拿到附件之后是一张图片:

可以foremost看看,分离出一个PDF文件,发现没有什么内容,但是在拖动鼠标点击的过程中发现有白色字体:

复制出来就是flag
flag{625d7f13d1646c3ab86be95a6ee05dd9}

hacker_traffic

拿到附件之后先strings一下看看有没有非预期,可以看到password is (md5(virus_file) + lhost_ip),猜测是要提取ELF木马文件,再来分析它的回连地址。

附件是一个USB流量包,里面有大量U盘传输的数据:

发现存在大量的ELF文件,一共有100个:

可以使用tshark、python来提取这100个ELF文件,提取出来后,可知所有ELF文件运行后都会打印一个MD5的值:

在第62个ELF文件里面发现有一个Ping命令的操作,IP地址是192.168.3.201

192.168.3.201这个就是lhost_ip,那么还差一个virus_file。将该ELF文件MD5之后和IP地址拼接在一起解密ZIP压缩包,但是提示密码错误……开始自闭,各种尝试发现TCP在传输的过程中会有冗余数据,所以我们需要计算该ELF文件的真正大小,删掉冗余数据。

readelf -h ELF_61
Start of section headers:              14736 (bytes into file)
Size of this header:                      64 (bytes)
Size of program headers:              56 (bytes)
Number of program headers:         11
Size of section headers:                64 (bytes)
Number of section headers:           30
Section header string table index:   29

这里计算方法可以参考:https://ctf-wiki.org/executable/elf/structure/basic-info/

然后把冗余数据删掉,保留16656字节:

再计算文件的MD5,MD5 (ELF_61) = 0f82ecb23adc35a4a5e3d8bdabbafe15
结合之前的lhost_ip,压缩包密码为0f82ecb23adc35a4a5e3d8bdabbafe15192.168.3.201
打开之后发现是一个经过伪随机+shuffle生成s盒进行的置换异或加密的py脚本

from flag import secret
key = "x.x.x.x"


def encrypt_flag(flag, key):
    random.seed(key)
    table = list(range(0, 38))
    random.shuffle(table)
    flag = [flag[i] for i in table]
    ascii_flag = [ord(c) for c in flag]
    random.seed(key)
    xor_key = random.randint(0, 255)
    encrypted_flag = [c ^ xor_key for c in ascii_flag]
    return base64.b64encode(bytes(encrypted_flag)).decode("ascii")
print(encrypt_flag(flag, key))
# VFVWU1kGBgIMUlMBVFcBBgRRBFAHVFBVUFkbUB0DAQMEBVIGAlE=

这个python脚本的含义就是:

  • 使用给定的密钥对随机数生成器进行初始化。
  • 创建一个包含数字0到37的列表。
  • 使用随机数生成器对该列表进行洗牌。
  • 使用洗牌后的列表重新排列标志中的字符。
  • 将标志中的字符转换为ASCII码。
  • 使用相同的密钥再次初始化随机数生成器。
  • 生成一个随机的XOR密钥。
  • 将标志的每个ASCII码与XOR密钥进行异或操作。
  • 将加密后的结果转换为Base64编码。
  • 返回加密后的结果。

最后再写出对应的解密脚本:

import base64
import random

def decrypt_flag(encrypted_flag, key):
    random.seed(key)
    xor_key = random.randint(0, 255)
    decrypted_flag = []
    encrypted_flag = base64.b64decode(encrypted_flag.encode("ascii"))
    for c in encrypted_flag:
        decrypted_flag.append(c ^ xor_key)
    random.seed(key)
    table = list(range(0, 38))
    random.shuffle(table)
    flag = [None] * 38
    for i, j in enumerate(table):
        flag[j] = chr(decrypted_flag[i])
    return "".join(flag)

encrypted_flag = "VFVWU1kGBgIMUlMBVFcBBgRRBFAHVFBVUFkbUB0DAQMEBVIGAlE="
key = "192.168.3.201"
decrypted_flag = decrypt_flag(encrypted_flag, key)
print(decrypted_flag)

flag{9d621041fb59a4a0bd034f753d2cfe0c}

Crypto

Morse的笔记本

打开之后是一个txt文本

你知道吗。今天我竟然在街上捡到了100元钞票,我当时简直惊呆了,太幸运了。于是我赶紧把钞票捡起来!心里面十分高兴。走了一段路之后,我看见了一个老奶奶在街角卖菜!我就想。这100元钞票对我来说并不是很重要。但对她可能就很有用了。于是我走过去!把钞票递给了她。她非常感激。说我是个好心人。我也因此感到十分快乐!因为我知道。这个世界因为有我们每一个人的善良而变得更美好,今天天气真的很好,我和小丽!小明越好一起去公园玩,在公园里,我们看见了一只可爱的小松鼠,它在树枝上蹦来蹦去!十分活泼可爱。我们还看见了一些漂亮的花朵,它们在微风中轻轻摇曳。像在跳舞一样!我们一边走一边欣赏,一边笑一边玩。真是度过了一个美好的下午。回家的路上!我感到心情特别愉悦。因为我知道。只要心怀善意!天下没有做不成的事情。我经常会感叹人生的短暂。时间的流逝。但我从未停止过前进的步伐!人生路上,有时候你会遇到阻碍。但只要你努力地挑战,不放弃。就能突破困境!实现自己的梦想,所以,不管你遇到什么样的挑战,都不要气馁!坚持下去,你一定会收获成功的喜悦。因为!只有那些坚定自己方向的人,才能走得更远,更自信。当我们遭遇挫折和失败的时候!不要被打倒。要用心去学习,从失败中汲取经验教训。然后重新站起来!更加坚定地追求自己的目标。成功并不是一蹴而就的,需要我们付出长久的努力和坚持!但只要我们一直前进,终究会到达成功的彼岸!所以。让我们一起勇敢面对人生的挑战。迎接成功的喜悦。


mesr{997a9k414dx8m4061u74v15m1y32201k}

根据题目名称,猜测是文本中的标点符号转morse code

逗号 句号 感叹号
- . 间隔

morse decode is PASSWORDISCONGRATS

.--. .- ... ... .-- --- .-. -.. .. ... -.-. --- -. --. .-. .- - ...

然后尝试维吉尼亚解密,密钥为CONGRATS
kqfl{997j9k414kf8k4061g74i15g1h32201k}
再进行凯撒解密,ROT21可得flag
flag{997e9f414fa8f4061b74d15b1c32201f}