MADer也要当CTFer
是个mkv文件,打开只有十几秒的视频,但是下面时长5小时,肯定有问题

然后看到后缀是mkv,搜一下这个mkv能封装视频、音频、字幕文件,下个小工具箱导出文件

有个字幕.ass文件

后面的text字段是标准的16进制,写个脚本提取
import rewith open("只是刚好情窦初开遇到你.ass", "r", encoding="utf-8") as f:lines = f.readlines()dialogue_lines = [line for line in lines if line.startswith("Dialogue:")]texts = []
for line in dialogue_lines:parts = line.strip().split(",", 9) # ASS 字幕 text 是第10个字段(索引9)if len(parts) >= 10:texts.append(parts[9])# 保存为 txt
with open("subtitle_texts.txt", "w", encoding="utf-8") as out:for text in texts:out.write(text + "\n")print(f"提取完成,共 {len(texts)} 行字幕文本。")
提取出来直接导入16进制文件

文件头是rifx,搜了一下是个ae的文件,是.aep,但是我的ae打不开。。。。就直接在线预览,搜了一下flag


只有这俩,但是说明flag肯定在,找找又发现

发现他们都在这个左边,我就直接慢慢看左边,没看到,最后我用记事本按这个方法找到了,不知道为什么在线预览没有,在记事本里他们前面的字符都一样我就这样找到的


得到flagflag{l_re@IIy_w@nn@_2_Ie@rn_AE}
会飞的雷克萨斯
看到这个题目就知道答案了,大名鼎鼎的四川小孩,嘻嘻,但是我刚开始以为是找左边三位小数md5加密(我没加群!!!!!!)。下次flag形式发题目描述里吧,求求你。
现在dy搜一下这件事,是四川省内江市资中县的事情
地图直接搜
得到flagflag{四川省内江市资中县春岚北路城市中心内}
曼波曼波曼波
qr码是假的

有一个smn.txt,看起来就像是要base64转图片(赛马娘),但是=在前面说明应该是需要逆序,直接在线逆序!!!!


然后b64转图片

得到图片

然后就是正常的隐写,foremost/binwalk分离

里面是个zip,解压一张老隐写图和一段提示解压zip,密码XYCTF2025

俩看起来一样的图,直接blindwatermark分离!!!!!


得到flagXYCTF{easy_yin_xie_dfbfuj877}
Greedymen
这个写个脚本直接出
from collections import defaultdict
import mathdef get_factors(n):factors = set()for i in range(1, int(math.sqrt(n)) + 1):if n % i == 0:factors.add(i)if i != 1 and i != n // i:factors.add(n // i)factors.discard(n)return factorsdef simulate_game(level_max, counter):board = {i: 'unassigned' for i in range(1, level_max + 1)}my_score = 0opponent_score = 0steps = []while counter > 0:best_choice = Nonebest_net_gain = float('-inf')for num in range(1, level_max + 1):if board[num] != 'unassigned':continuefactors = get_factors(num)if all(board[f] != 'unassigned' for f in factors):continue # can't pick this number, all factors already chosengain = numcost = sum(f for f in factors if board[f] == 'unassigned')net_gain = gain - costif net_gain > best_net_gain:best_net_gain = net_gainbest_choice = numif best_choice is None:break # no more valid moves# Assign number to selfboard[best_choice] = 'me'my_score += best_choice# Assign its unassigned factors to opponentfor f in get_factors(best_choice):if board[f] == 'unassigned':board[f] = 'opponent'opponent_score += fcounter -= 1steps.append(f"Choose {best_choice}: +{best_choice} (Opponent gets factors {get_factors(best_choice)})")# Assign remaining numbers to opponentfor num, status in board.items():if status == 'unassigned':board[num] = 'opponent'opponent_score += numreturn {'steps': steps,'my_score': my_score,'opponent_score': opponent_score,'final_result': 'Win' if my_score > opponent_score else 'Lose','difference': my_score - opponent_score}# Simulate all 3 levels
level1 = simulate_game(50, 19)
level2 = simulate_game(100, 37)
level3 = simulate_game(200, 76)# Saving the results into a text file
with open("game_simulation_results.txt", "w", encoding="utf-8") as file:for i, level in enumerate([level1, level2, level3], 1):file.write(f"Level {i}:\n")file.write(f"Steps:\n")for step in level['steps']:file.write(f" {step}\n")file.write(f"My Score: {level['my_score']}\n")file.write(f"Opponent Score: {level['opponent_score']}\n")file.write(f"Final Result: {level['final_result']}\n")file.write(f"Score Difference: {level['difference']}\n\n")
输出:

整理得到
47, 49, 35, 39, 26, 46, 33, 45, 38, 44, 34, 50, 30, 28, 42, 40, 32, 24, 3697, 91, 95, 85, 77, 93, 62, 87, 99, 81, 94, 69, 86, 63, 92, 82, 66, 76, 74, 54,
88, 75, 50, 100, 98, 70, 68, 56, 84, 60, 90, 52, 78, 80, 64, 48, 72199, 187, 169, 185, 161, 155, 183, 122, 177, 145, 175, 133, 159, 171, 153, 194, 141, 188, 178, 129,
172, 166, 123, 164, 158, 117, 195, 130, 105, 189, 147, 135, 98, 196, 182, 165, 110, 154, 148, 146,
78, 156, 104, 114, 190, 152, 142, 102, 170, 136, 134, 126, 124, 186, 90, 180, 140, 116, 174, 120,
80, 160, 128, 112, 168, 108, 162, 100, 150, 96, 144, 92, 138, 88, 132, 198
直接输入,连赢三局,得到flag



flag:flag{Greed, is......key of the life.}
Moon
有个.py和.pyd文件,py文件里面使用了pyd
import moon print("I tried my best, to live an ordinary life.")
print("But I hope you can look up and see the moonlight through reverse engineering on the streets full of sixpence.")user_input = input("Enter your flag: ").strip()result, error = moon.check_flag(user_input)if error:print("Error.")
elif result:print("I think you have found the right way.")
else:print("You seem to be lost.")
就要知道pyd在python那个版本下的,在自己的3.12不对,运气好直接在虚拟机的3.11直接成功


然后用ida看了看,找到很多函数


有xor异或的函数,还有targethex(用于异或的16进制),seed种子
然后让ai分析了一下,找了找函数,交叉引用了两个关键函数,check和xor发现
这个check:
__int64 __fastcall sub_180001A00(__int64 a1, __int64 *a2, __int64 a3, __int64 a4)
{__int64 v4; // rcx__int64 *v5; // rbpint v7; // esi__int64 v8; // rax__int64 v9; // rbx__int64 v10; // rbx__int64 v11; // rdx_QWORD v13[3]; // [rsp+40h] [rbp-18h] BYREF__int64 v14; // [rsp+68h] [rbp+10h] BYREFv4 = 0LL;v5 = &a2[a3];v14 = 0LL;v7 = a4;v13[1] = 0LL;v13[0] = (char *)off_18000B618 + 192;if ( !a4 ){if ( a3 == 1 ){v8 = *a2;return sub_180001B70(v4, v8);}goto LABEL_14;}if ( a3 ){if ( a3 == 1 ){v8 = *a2;v9 = *(_QWORD *)(a4 + 16);v14 = *a2;goto LABEL_7;}
LABEL_14:PyErr_Format(PyExc_TypeError,"%.200s() takes %.8s %zd positional argument%.1s (%zd given)","check_flag","exactly",1uLL,byte_1800084C0,a3);v11 = 2805LL;goto LABEL_15;}v10 = *(_QWORD *)(a4 + 16);v8 = sub_180003EA0(a4, v5, *((_QWORD *)off_18000B618 + 24));v14 = v8;if ( !v8 ){if ( PyErr_Occurred() ){v11 = 2789LL;goto LABEL_15;}goto LABEL_14;}v9 = v10 - 1;
LABEL_7:if ( v9 > 0 ){if ( (int)sub_1800040C0(v7, (_DWORD)v5, (unsigned int)v13, a4, (__int64)&v14, a3, (__int64)"check_flag") < 0 ){v11 = 2794LL;
LABEL_15:sub_180005D40("moon.check_flag", v11, 10LL, "moon.py");return 0LL;}v8 = v14;}return sub_180001B70(v4, v8);
}
和xor:
__int64 __fastcall sub_180001130(__int64 a1, __int64 *a2, __int64 a3, __int64 a4)
{__int64 *v5; // r14_QWORD *v6; // r8_QWORD *v8; // rcx__int64 v9; // rbx__int64 v10; // rdi__int64 v11; // rdx__int128 v13; // [rsp+40h] [rbp-58h] BYREF_QWORD v14[3]; // [rsp+50h] [rbp-48h] BYREFv14[2] = 0LL;v5 = &a2[a3];v6 = off_18000B618;v13 = 0LL;v8 = (_QWORD *)((char *)off_18000B618 + 264);v14[0] = (char *)off_18000B618 + 264;v14[1] = (char *)off_18000B618 + 136;if ( !a4 ){if ( a3 == 2 ){v9 = *a2;*((_QWORD *)&v13 + 1) = a2[1];return sub_180001370(v8, v9, *((_QWORD *)&v13 + 1));}
LABEL_25:PyErr_Format(PyExc_TypeError,"%.200s() takes %.8s %zd positional argument%.1s (%zd given)","xor_crypt","exactly",2uLL,"s",a3);v11 = 2531LL;goto LABEL_26;}if ( a3 ){if ( a3 != 1 ){if ( a3 != 2 )goto LABEL_25;*((_QWORD *)&v13 + 1) = a2[1];}v9 = *a2;*(_QWORD *)&v13 = *a2;}else{v9 = v13;}v10 = *(_QWORD *)(a4 + 16);if ( a3 ){if ( a3 != 1 )goto LABEL_15;goto LABEL_13;}*(_QWORD *)&v13 = sub_180003EA0(a4, v5, *v8);v9 = v13;if ( !(_QWORD)v13 ){if ( PyErr_Occurred() ){v11 = 2503LL;goto LABEL_26;}goto LABEL_25;}v6 = off_18000B618;--v10;
LABEL_13:*((_QWORD *)&v13 + 1) = sub_180003EA0(a4, v5, v6[17]);if ( !*((_QWORD *)&v13 + 1) ){if ( PyErr_Occurred() ){v11 = 2511LL;}else{PyErr_Format(PyExc_TypeError,"%.200s() takes %.8s %zd positional argument%.1s (%zd given)","xor_crypt","exactly",2uLL,"s",1uLL);v11 = 2513LL;}goto LABEL_26;}--v10;
LABEL_15:if ( v10 > 0 ){if ( (int)sub_1800040C0(a4, (_DWORD)v5, (unsigned int)v14, a4, (__int64)&v13, a3, (__int64)"xor_crypt") < 0 ){v11 = 2518LL;
LABEL_26:sub_180005D40("moon.xor_crypt", v11, 3LL, "moon.py");return 0LL;}v9 = v13;}return sub_180001370(v8, v9, *((_QWORD *)&v13 + 1));
}
分析了一下,40c0应该就是chek函数,1b70就是xor函数,并且xor函数传参是两个

xor_crypt 的关键逻辑:
- 要求 2 个参数(
a2[0],a2[1]):v9 = *a2是第一个参数(待加密或解密的数据)*((_QWORD *)&v13 + 1) = a2[1]是 key
- 调用
sub_180001370(v8, v9, key)执行 XOR 操作,最后返回结果
所以 xor_crypt(data, key) = sub_180001370(data, key) 是我们要重点还原的函数,几乎可以肯定它就是执行字节级异或。
反正ai分析了很多

最后尝试直接用 Python 脚本调用 .pyd,测试 xor_crypt()与 check_flag(),观察行为。

说是moon.xor_crypt()要两个参数,而moon.check_flag()要一个参数,moon.check_flag()这个好理解,直接是输入flag检查,moon.xor_crypt()这个根据上面的分析,应该是有个密钥(也就是看到的seed种子,后面试出来的,嘻嘻)然后就有了接下来的ai对话:
问了一下模型,让他写了个脚本,找出模块内有哪些变量/函数/模块
import sys
import os
import importlib.util
import inspectdef load_pyd_module(pyd_path):module_name = os.path.splitext(os.path.basename(pyd_path))[0]spec = importlib.util.spec_from_file_location(module_name, pyd_path)if spec is None:raise ImportError(f"Could not load spec from {pyd_path}")module = importlib.util.module_from_spec(spec)spec.loader.exec_module(module)return moduledef hlep_raw(module):print(f"分析模块:{module.__name__}")print("=" * 60)for name in dir(module):if name.startswith("__"):continueprint(f"发现对象: {name}")try:obj = getattr(module, name)print(f" 类型: {type(obj)}")print(f" 文档: {getattr(obj, '__doc__', '无')}")except Exception as e:print(f" 无法访问: {e}")if __name__ == "__main__":if len(sys.argv) != 2:print("用法: python hlep.py <路径/模块.pyd>")sys.exit(1)pyd_path = sys.argv[1]if not os.path.isfile(pyd_path) or not pyd_path.endswith(".pyd"):print("请提供有效的 .pyd 文件路径")sys.exit(1)try:mod = load_pyd_module(pyd_path)hlep(mod)except Exception as e:print(f"加载模块失败: {e}")print(dir(mod))print('----------------------------------------------------')for name in dir(mod):if name.startswith("__"): continueobj = getattr(mod, name)print(f"{name} -> {type(obj)}")print('----------------------------------------------------')for name in dir(mod):if name.startswith("__"):continueobj = getattr(mod, name)if callable(obj):print(f"{name}() 可调用,类型: {type(obj)}")

看到有这些玩意儿,让他提取这些的值
import importlib.util
import inspect
import sys
import osdef load_pyd_module(pyd_path):module_name = os.path.splitext(os.path.basename(pyd_path))[0]spec = importlib.util.spec_from_file_location(module_name, pyd_path)module = importlib.util.module_from_spec(spec)spec.loader.exec_module(module)return moduledef analyze_module(module):print(f"[+] 模块名: {module.__name__}")print(f"[+] 文档字符串:\n{module.__doc__}\n")members = dir(module)print(f"[+] 模块成员列表:")for name in members:if name.startswith("__") and name.endswith("__"):continueattr = getattr(module, name)if inspect.isfunction(attr):print(f" [+] 函数: {name}")doc = inspect.getdoc(attr)if doc:print(f" - Doc: {doc}")else:print(f" - Doc: 无")elif inspect.isbuiltin(attr):print(f" [+] 内建函数: {name}")else:print(f" [+] 变量: {name} = {repr(attr)}")if __name__ == "__main__":# 替换为你的 .pyd 文件路径pyd_path = "moon.pyd"if not os.path.exists(pyd_path):print(f"[!] 找不到文件: {pyd_path}")sys.exit(1)try:mod = load_pyd_module(pyd_path)analyze_module(mod)except Exception as e:print(f"[!] 加载或分析模块失败: {e}")

再根据前面的分析,写了个解密的脚本
import moonxor_result = moon.xor_crypt(1131796,b'\x42\x6b\x87\xab\xd0\xce\xaa\x3c\x58\x76\x1b\xbb\x01\x72\x60\x6d\xd8\xab\x06\x44\x91\xa2\xa7\x6a\xf9\xa9\x3e\x1a\xe5\x6f\xa8\x42\x06\xa2\xf7')print(xor_result)
刚开始根据分析以为先传的是16进制
(b'\x42\x6b\x87\xab\xd0\xce\xaa\x3c\x58\x76\x1b\xbb\x01\x72\x60\x6d\xd8\xab\x06\x44\x91\xa2\xa7\x6a\xf9\xa9\x3e\x1a\xe5\x6f\xa8\x42\x06\xa2\xf7',1131796)
结果报错了

后面换回来就对了

得到flagflag{but_y0u_l00k3d_up_@t_th3_mOOn}
