首页
社区
课程
招聘
[分享]第二题:巳时·绿光幽语
发表于: 1天前 197

[分享]第二题:巳时·绿光幽语

1天前
197

写给谁: 刚接触逆向 / CTF 的同学,自己也学习一波。
阅读方式: 少黑话;出现专业词会先用大白话解释。
目标: 不依赖「死记 IDA 地址」,也能顺着思路得到 key,并理解「凭什么」。
AI: grok 4.5

若平台要求 flag{...} 格式,可提交:

程序本身只校验 6 字符 yb6tcr,是否再包一层以平台说明为准。

程序提示:有一段「被藏起来的代码」,需要你找到一个 6 字符钥匙(key) 正确还原,才会成功。

一句话:

找出加密方式 + 算出钥匙。

不是改程序、也不是攻击他人电脑,只是分析「程序如何检查答案」。

在工程根目录运行:

正常编码下大致显示:

含义:

这是 Windows 控制台编码问题,不是样本损坏。可先执行:

936 表示按简体中文(GBK)显示。

读后面步骤前,先建立这 5 个直觉。

有的 exe 是 C/C++ 直接编译;也有的是 把 Python 程序打包进 exe(方便双击运行)。本题属于后者,打包工具是 PyInstaller

生活类比:同一把钥匙拧一下变密文,再拧一下变明文。

本题用了两种 XOR:

key 为 yb6tcr 时,密文较长则钥匙循环使用:

每个位置:明文 = 密文 XOR key[对应位置]

都是「文字如何变成字节」:

本题中:

记住:同是中文,编码不同字节就不同,分析时要对上编码。

一句话: marshal 是 Python 把「代码对象、常量、字符串、元组」写成一串字节 / 再读回来的官方格式。.pyc、frozen 模块、嵌在 DLL 数据区里的大段,都可能是 marshal。

本题只需会认几个「路牌」:

例子 A:73 10 00 00 00 + 16 字节
→ 一段长度 16 的串(本题「展示密文」每块)。

例子 B:29 08 + 8 次「73 10 + 16 字节」
→ 8 元组,每个元素 16 字节 → 8 段展示密文的摆放方式。

例子 C:73 0F 00 00 00 + 15 字节
→ 长度 15 的串 → 本题「用户密文」。

不必手写完整解析器;会「读标签拆货」即可。

在 exe 的字符串中可看到类似:

这些是 PyInstaller 特征;python313 表示 Python 3.13

结论:

题目逻辑不在壳里,在壳释放出来的内容里。

初学者可先把 IDA 当「确认是 PyInstaller」的工具;解题主路径是 拆包 + 分析 DLL 数据

推荐使用 pyinstxtractor-ng(可执行文件或 Python 脚本均可)。

优点:一键拆包、兼容较好、目录干净,适合初学者。

在工程根目录(与 题目.exe 同级)执行:

成功后生成类似目录:

其中约有二十来个文件,例如:main.pycPYZ.pyzpython313.dll 等。

做题与写证据时,请只用 pyinstxtractor-ng 生成的拆包目录。
不要把运行日志、分析笔记 txt 混进搜索目录,以免「在文件中搜索」出现假命中。

相对路径示例:

反编译 / 分析 main.pyc 后,逻辑大约只有:

即:一运行就正常退出,没有输入 key、没有打印中文提示。

但实际运行 exe 时明明有提示和输入。因此:

提示与校验 不在 main 里,而在 Python 启动过程中更早执行 的地方。

Python 启动会自动导入内置模块,其中包括 os。出题人把挑战逻辑嵌进 被修改过的 python313.dll 内 frozen 的 os 数据。一旦启动并 import os,题目就先跑起来——即使 main 是空的。

易错点: 只反编译 main,会以为「题是空的」。必须结合运行现象,去找真正打印中文的位置。

本节回答三个问题:

运行时屏幕上明文出现了英文标识符:

特点:

分析顺序:

不是先验「一定在 dll」,而是用运行提示反查文件。

本题中,标识符 my_function 未加密,可直接搜到。

注意区分:

其它题可能混淆名字或全串加密;本题没有,因此「搜运行时看见的英文函数名」有效。

在干净目录 题目.exe_extracted/ 中搜索 my_function

本题实测:仅 python313.dll 命中 1 次。

这是 全目录检索 + 排除法,不是猜。

操作(Notepad++ 示例):

Notepad++ 只回答「在哪个文件」;打开后还要往下找 8 段密文与 15 字节(见下)。

python313.dll 中,my_function 约在文件偏移 0x4DACE9(十六进制编辑器 / 脚本查找可用)。

附近还能看到:printinputb_keyco_code / co_consts__code__replaceException,以及 os 模块常见名字。

拼起来的逻辑大致是:

下列 VA(虚拟地址) 针对本题该 DLL:ImageBase = 0x180000000
你本地若 ImageBase 一致,可用 G 跳转核对;不一致则以 字符串搜索 + 结构阅读 为准,不必死记地址。

不要在 .text 里找名为 my_function 的 C 函数。
本题逻辑是 marshal 嵌在 .rdata 的 Python 字节码与常量,不是原生导出函数。

此时还不知道 key

my_function 往下滚,会看到类似:

「展示密文块 0~7」是事后笔记名:结构来自 marshal 标签;内容是否为展示提示,要靠 XOR 实验与运行输出比对。

从第一段 16 字节(本题块 0 起址约 0x1804DC71C)抄出数据,试单字节 XOR。已知明文攻击后锁定钥匙为 0x55(过程见第十节):

按同样方法解全部 8 段并拼接,得到与运行窗口一致的整段提示 → 确认这就是「提示,需要.」密文。

不是 8 段展示密文里的某一段,而是 继续往下滚,过 co_code 等名字后:

二者地址、长度、密钥都不同,不要混

文件偏移与 VA(本题该 .rdata 片区粗算):

最稳妥仍是:搜字符串 → 按结构往下读,不必死记。

这是数据区中的 Python marshal 串,不是 C 函数入口。静态做题以 字符串/字节模式定位 + 算法还原 即可,不必反编译整份 CPython。

业务逻辑(Python)主要在 .rdata 的 marshal 数据.text 是解释器「厨师」。在 .rdata 看不到清晰的 xor al, 55h 很正常——算法靠 已知明文 + 与运行输出比对 断定。

算 key 只走线 B。

线 A 由程序自动解密并打印;你静态推出 0x55 是为了看懂题面从哪来;过关仍要线 B 的 yb6tcr

对应 = 等长 + 按下标对齐 + 同一种 XOR 能互变 + 与程序行为一致。

DLL 中有 8 段 × 16 字节。对每个字节:

拼起来即完整 UTF-8 提示(与运行时一致)。

注意: 0x1804DC6E9 处的明文名字 my_function 不能当这段密文;反推 0x55 用的是 块 2

展示文字用固定钥匙 0x55不是你要猜的 6 字符 key。

依据:长度正好 15;贴在 co_code / b_key / input 旁;仍在挑战植入区。不是在整个 .rdata 里随便抓 15 字节。

因此 6 字符 key 为:

输入:yb6tcr
看到 恭喜成功! 即通过。

下面不是 100% 从编译器抠出的原文件,而是根据证据还原、与真题行为一致的逻辑:

在 DLL 中约 0x1804DC7DB 附近,数据里夹着可读碎片:

于是有人问:密钥都在文件里了,为何还要输入?

一句话:

程序只认你键入的 6 字节当钥匙。
文件里能搜到 yb6tcr = 出题不严谨带来的作弊通道,不是官方玩法。

正确用法: 用第十节 XOR 推出 key 之后,再回搜印证。
错误用法: 一打开 DLL 就搜 yb6tcr 当定位手段,跳过算法。

能。关键路径:确认 PyInstaller → pyinstxtractor-ng 拆包 → 在 python313.dll 找字符串与密文 → XOR 计算。IDA 用于核对,不是唯一路径。

Python 源码编译后的字节码文件,可用工具反编译成接近源码的形式。

题藏在启动必加载的 frozen os(在 python313.dll)里,main 是掩护。

程序只认 6 字符;平台若要求 flag{...} 再包装。以平台说明为准。

使用工具:CyberChef

第十节「凭什么」。延伸:2_wp/6_零基础_如何算出key.md

不要盲扫整段 .rdata。更负责的优先级:

本题能快,是因为有运行提示 + 可搜 my_function(捷径)。通用时不要把「只搜字符串」当唯一方法。

本题够用两个路牌:73+长度 = 串;29+个数 = 元组。见概念 5。

本题 IDA 路标(VA,ImageBase 0x180000000):

这题拆开后核心只有两步:

跟着 运行 → 拆包 → 定位 → 算异或 → 验证,每一步问「凭什么」,就是完整的 CTF 逆向。

Key:yb6tcr

项目 内容
Key(6 个字符) yb6tcr
样本 工程根目录下的 题目.exe
验证方式 运行样本,输入 yb6tcr,应打印 「恭喜成功!」
用途 钥匙 作用
显示提示文字 固定值 0x55(十进制 85) 把展示密文变成你看到的中文和源码
校验你的输入 你输入的 6 字符,循环使用 把 15 字节密文变成 UTF-8「恭喜成功!」
字节 人话 后面跟什么
73s 字符串 / 字节串 4 字节长度(小端)+ 内容
29) 小元组 1 字节元素个数 + 各元素
da / z 短 ASCII 名字 名字字符(如 my_function
e3 / 63c code 对象 字段多,初学可先跳过
项目
文件名 题目.exe
大小 约 7.4 MB(偏大,像带了运行环境)
MD5 d2fc58976cac7403cee3a8b8f2560081
类型 Windows 64 位 PE
文件 是什么 对本题的意义
main.pyc 程序入口字节码 几乎是空的(烟雾弹)
PYZ.pyz 打包的标准库等 无自定义题目模块
python313.dll Python 解释器 真题数据在这里
其它 .pyd / 运行库 依赖 一般不必深挖
路径 说明
题目.exe 原始样本
题目.exe_extracted/ pyinstxtractor-ng 拆包结果(推荐)
题目.exe_extracted/python313.dll 真题所在 DLL
内容 是否加密 说明
屏幕展示的整段提示 (固定 XOR 0x55 密文在 DLL,运行时解密再打印
校验用 15 字节 (6 字符 key 循环 XOR) 验证 key
名字 my_function 否(本题) ASCII 明文,可直接搜
项目 值(本题)
模块 python313.dll
架构 64 位
ImageBase 0x180000000
阶段 可以搜 不要搜
刚定位 运行时见过的 my_function yb6tcr(key 尚未算出)
算完 key 后 可用 yb6tcr 回搜印证 把结论当定位手段提前抄
名称 作用 钥匙
展示密文块 给玩家看的提示(8×16) 固定 0x55
用户密文 校验你输入的 key(15 字节) 6 字符循环
含义 VA 如何自己定位
明文名 my_function 0x1804DC6E9 Shift+F12 搜
展示密文块 0 0x1804DC71C my_function 下方 29 08 后第一段 73 10+16B
展示密文块 2 0x1804DC746 第 3 段 16 字节(31 30 33 75...
用户密文 15 字节 0x1804DC7FF 再往下 73 0F 00 00 00 后 15 字节
ASCII yb6tcr(泄漏) 0x1804DC7DB 仅算出 key 后回搜印证
做题核心区(约) 0x1804DC6930x1804DCBCA 名字、两段密文、相关 names
打开对象 你看到什么
题目.exe PyInstaller 壳:解压、加载 DLL、跑 main
python313.dll 解释器 + 本题真正植入点(frozen os 数据)
线 做什么 与输入的 key 有关吗
A 展示提示 8 段数据 XOR 固定 0x55 → 屏幕中文提示 无关
B 检查 key 15 字节 XOR 你输入的 6 字符 →「恭喜成功!」 有关(答案在这里)
东西 作用
屏幕上的 def my_function(): print("恭喜成功!") 题面——告诉你还原后长什么样
6 字符 key 你要交的答案
位置 密文 明文 (UTF-8) XOR 字符
0 0x9f 0xe6 0x79 y
1 0xe3 0x81 0x62 b
2 0x9b 0xad 0x36 6
3 0x91 0xe5 0x74 t
4 0xf5 0x96 0x63 c
5 0xee 0x9c 0x72 r
6 0x9f 0xe6 0x79 y(开始重复)
程序运行时(设计意图) 你在二进制里搜到 yb6tcr
key 从哪来 input() 读键盘 数据布局泄漏出的 6 字符
干什么 XOR 15 字节,还原成功串 不是程序从该地址自动读密码
输错 解密失败,不进成功分支 与是否搜到无关
VA 内容
0x1804DC6E9 明文名字 my_function(路标)
0x1804DC746 展示密文块 2(用来反推 0x55
知识点 本题中的样子
PyInstaller exe 内嵌 Python;用 pyinstxtractor-ng 拆包
烟雾弹 main 为空
藏逻辑 python313.dll 内 frozen os;数据在 .rdata
业务代码形态 Python 字节码 + 常量被 marshal,不是 .text 里显眼的 C 函数
marshal 路牌 73+长度=串;29+个数=元组
线 A / 线 B 展示用 0x55;校验用 6 字符 key(算 flag 只走 B
固定 XOR 块 2 ⊕ def my_function(0x55
循环 XOR 15 字节 ⊕ UTF-8「恭喜成功!」→ yb6tcr
无明文时 动态断输出 + DLL diff,禁止盲扫整段 .rdata
验证 动态输入看到「恭喜成功!」
内容 VA
核心区 0x1804DC6930x1804DCBCA
名字 my_function 0x1804DC6E9
展示块 2 0x1804DC746
用户密文 15B 0x1804DC7FF
key 泄漏串 0x1804DC7DB(仅回搜印证)
flag{yb6tcr}
题目.exe
提示,需要还原的代码
def my_function():
    print("恭喜成功!")
请输入key还原代码(请输入6个字符)
chcp 936
题目.exe
┌─────────────────────────────┐
│  题目.exe(快递箱)           │
│  ┌───────────────────────┐  │
│  │  Python 运行环境        │  │
│  │  + 真正的 Python 逻辑   │  │
│  └───────────────────────┘  │
└─────────────────────────────┘
密文字节:  第0 第1 第2 第3 第4 第5 第6 第7 第8 ...
key 字节:   y   b   6   t   c   r   y   b   6  ...
源码 .py
  → 编译成 code 对象(字节码 + 常量表 + 名字表)
  → marshal.dumps  → 磁盘/DLL 里的 0x73 0x29 ...
  → 运行时 marshal.loads → 解释器执行
第 1 步  确认是 PyInstaller 打包的 Python
    ↓
第 2 步  用 pyinstxtractor-ng 拆包
    ↓
第 3 步  发现 main 几乎是空的(烟雾弹)
    ↓
第 4 步  在 python313.dll 中定位真题数据
    ↓
第 4.5 步(推荐)用 IDA 打开 DLL,按结构往下读
    ↓
第 5 步  两条线:展示用 0x55;校验用 6 字符 key
    ↓
第 6 步  得到 key = yb6tcr,运行验证
:: 独立 exe 工具
pyinstxtractor-ng.exe 题目.exe
题目.exe_extracted/
题目.exe_extracted/python313.dll
题目.exe_extracted/main.pyc
import sys
sys.exit(0)
1. 双击 题目.exe
2. PyInstaller 解压并启动 Python 3.13
3. 自动 import os  →  【题目逻辑在这里执行】
4. 最后才执行 main → sys.exit(0)  (几乎无作用)
my_function
运行现象 → 记下独特英文名 my_function
  → 在干净拆包目录全局搜索
  → 谁命中,谁更可疑
√ python313.dll     (匹配 1 次)  ← 唯一真源
× main.pyc
× PYZ.pyz
× 启动相关 pyc / 各 .pyd / 运行库 dll
29 08              ← 小元组,8 个成员
  73 10 00 00 00   ← 串,长 16
  [16 字节]        ← 展示密文块 0
  73 10 00 00 00
  [16 字节]        ← 展示密文块 1
  ... 共 8 次 ...
b = bytes.fromhex("b3dac5b2f1efbae9d9bcc9d5bdf3d4bd")
print(bytes(x ^ 0x55 for x in b))
73 0F 00 00 00   ← 长度 = 15
[15 字节]        ← 用户密文(本题起址约 0x1804DC7FF)
文件偏移 0x4DACE9  ≈  VA 0x1804DC6E9
VA ≈ 0x180000000 + 文件偏移 + 0x1A00
明文字节 = 密文字节 XOR 0x55
密文 = bytes.fromhex("31303375382c0a33203b36213c3a3b7d")  # 块2
明文 = b"def my_function("
print(bytes(密文[i] ^ 明文[i] for i in range(16)))
# b'UUUUUUUUUUUUUUUU' → 每一位都是 0x55

传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!

最后于 1天前 被教教我吧~编辑 ,原因: 上传附件
上传的附件:
收藏
免费 0
打赏
分享
最新回复 (1)
雪    币: 158
活跃值: (5361)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
11小时前
0
游客
登录 | 注册 方可回帖
返回