MoeCTF 2025 wp
MoeCTF 2025
学习逆向一年了,重温Moe
speed
动调即可
1 | enc = [0x6D,0x6F,0x65,0x63,0x74,0x66,0x7B,0x4A,0x75,0x73,0x74,0x5F,0x64,0x79,0x6E,0x40,0x6D,0x69,0x63,0x5F,0x64,0x33,0x62,0x75,0x67,0x67,0x31,0x6E,0x67,0x7D] |
moectf{Just_dyn@mic_d3bugg1ng}
reverse
moectf{open_your_IDA_and_start_reverse_engineering!!}
base
catch
假的xor实则凯撒密码
1 | def solve(): |
moectf{S4m3_Tr1ck_with_@flower_desuwa}
upx
upx脱壳后解密很简单,但是发现不大对,后来跟moe的头异或了下发现还要异或0xa
1 | enc = [35,43,39,54,51,60,3,72,100,11,29,118,123,16,11,58,63,101,118,41,21,55,28,10,8,33,62,60,61,22,11,36,0x29,0x24,0x56] |
moectf{Y0u_c4n_unp4ck_It_vvith_upx}
ez3
直接解开
1 | from z3 import * |
moectf{Y0u_Kn0w_z3_S0Iv3r_N0w_a1f2bdce4a9}
ezandroid
1 | bW9lY3Rme2FuZHJvaWRfUmV2ZXJzZV9JNV9lYXN5fQ== |
解码得到moectf{android_Reverse_I5_easy}
flower
花指令
1 | jz short Label |
1 | 把jz、jnz→jmp; |
对方法u,c,p即可
1 | enc2 = [79, 26, 89, 31, 91, 29, 93, 111, 123, 71, 126, 68, 106, 7, 89, 103, 14, 82, 8, 99, 92, 26, 82, 31, 32, 123, 33, 119, 112, 37, 116, 43] |
key偷偷做了修改
moectf{f0r3v3r_JuMp_1n_7h3_a$m_a9b35c3c}
2048_master_re
一个xxtea动调得到n即可写代码解密
1 |
|
moectf{@_N1c3_cup_0f_XXL_te4_1n_2O48}
tea
1 |
|
ezPy
1 | ciphertext = "wyomdp{I0e_Ux0G_zim}" |
moectf{Y0u_Kn0W_pyc}
have_fun
没看出来想考察什么
1 | s = "GEOI^LQbj\\" + "".join(map(chr, [0x001E, 0x0075, 0x004C, 0x007F, 0x0044, 0x0057])) |
moectf{H@v4_fUn}
mazegame
maze.txt
1 | 11111111111111111111111111111111111111111111111111111111 |
1 | def load_maze_txt(path="maze.txt"): |
moectf{ssddddwwddssddddssddssssddwwddwwddwwwwddddssssaassssaaaassaassaawwaawwwwaaaassddssaassddssssaaaassddddddwwwwddddssddddwwddwwaawwddddssssssssssssaaasssdddssssaassssaaaassaassaawwaawwwwaaaassddssaassddssssaaaassddddddwwwwddddssddddwwddwwaawwddddssssssssssssaaawawwwaassaawwaassaaaaaaaaaawwwwaassssssddddssssssdddddddddwwdddssddwwwdddsssdddddwwawwddddddddddddddddddddssddddddddwwwwawwwwwwwwdwwwwwwwwwwwaawwdwwwwwwwwwwdwwwwwwaaaasssssssssssssssssssssssssssssssssssssaaawwaaaaaaaaaaaaaaaaaaawwwddddddddwwddddddddddwwwawaawawwwwwwwwwwwwwddwwwwaassaawwaassaaaaaaaaaawwwwaawwddwwaawwdwwwdwwwwddddddddddssddddssssdsdssddssaassaaaawwaaaassssaaaaaawwddddwwwwaawwawaassdsssdd}
upx_revenge
upx无法秒了,上秘密武器也不行,只能手动脱壳了
插入
动调发现意思Base64编码
Base64原理简单补充:
原始字节:b'A'
(0x41)
二进制:01000001
Base64 编码流程:
- 拆成 6 比特:
010000
(16),010000
(16) … - 查码表:索引 16 是
Q
,再查索引 16 还是Q
→ 得到"QQ=="
。
解码时
拿到字符串 "QQ=="
:
- 看第一个字符
'Q'
,在码表中的索引是 16 → 6 比特010000
。 - 第二个
'Q'
,索引也是 16 → 6 比特010000
。 - 把这些 6 比特拼起来,再截掉填充,还原出原始的
01000001
→ 就是字节0x41
。
这是自己设计的Base64因此要重新构建
1 | table = [0x4f,0x4c,0x4d,0x4a,0x4b,0x48,0x49,0x46,0x47,0x44,0x45,0x42,0x43,0x40,0x41,0x5e,0x5f,0x5c,0x5d,0x5a,0x5b,0x58,0x59,0x56,0x57,0x54,0x6f,0x6c,0x6d,0x6a,0x6b,0x68,0x69,0x66,0x67,0x64,0x65,0x62,0x63,0x60,0x61,0x7e,0x7f,0x7c,0x7d,0x7a,0x7b,0x78,0x79,0x76,0x77,0x74,0x3e,0x3f,0x3c,0x3d,0x3a,0x3b,0x38,0x39,0x36,0x37,0x25,0x21] |
这三步把四个6位索引b1b2b3b4拼回三个8位原字节;有“=”填充时按规则省略相应输出字节即可。
moectf{Y0u_Re4l1y_G00d_4t_Upx!!!}
latin1 的特点
- 单字节编码:latin1 是一种单字节字符集,每个字符占用 1 个字节,编码范围为 0x00-0xFF。
- 兼容 ASCII:latin1 向下兼容 ASCII 编码,0x00-0x7F 范围与 ASCII 完全一致。
- 局限性:仅支持西欧语言字符,不支持中文、表情符号等复杂字符。
- 性能优势:由于其单字节特性,处理效率较高,适合对字符集要求不高的场景。
utf8mb4 的特点
- 多字节编码:utf8mb4 是变长字符集,每个字符占用 1 至 4 个字节。
- 支持 Unicode:能够存储几乎所有语言的字符,包括中文、阿拉伯文、表情符号等。
- 国际化支持:适用于需要多语言支持的应用,尤其是现代化的全球化系统。
- 性能开销:由于多字节特性,utf8mb4 在存储和处理上会占用更多的内存和 CPU 资源。
应用场景
- latin1:适用于仅需支持西欧语言的系统,如传统的英文网站或应用。
- utf8mb4:适用于需要支持多语言、表情符号或特殊字符的系统,如社交媒体、国际化电商平台等。
guess
RC4
1 | def rc4_ksa(key): |
moectf{RrRRccCc44$$_w1th_fl0w3r!!_3c6a11b5}
A simple program
tls中hook了strcmp
1 |
|
moectf{Y0u_P4ssEd!!}
Two cups of tea
KEY
主逻辑是xxtea
1 |
|
moectf{X7e4_And_xx7EA_I5_BeautifuL!!!!!}
ezandroid.pro
1 | from gmssl.sm4 import CryptSM4, SM4_DECRYPT |
moectf{SM4_Android_I5_Funing!!!}
rusty_sudoku
逻辑摘要:读入一行→去空白→必须81位且仅‘1..9’或‘.’→与题面a68718379181594比对(非‘.’位置不能改)→构盘→校验数独是否解完→对原始81字节答案做MD5(小写)→输出flag
题目:.6..8..7.18.3……7.9….1…8…15.9..4.2..54…2..9…..3948…..5..7..3….5.
解:369184572185327694274956831632879415897541263541632789756213948918465327423798156
MD5:a8c79927d4e830c3fe52e79f410216a0
moectf{a8c79927d4e830c3fe52e79f410216a0}