- docs/DLP_ENVIRONMENT_NOTES.md: 白名单矩阵/密文样本/属性不可区分等实测结论与探索过程 - README: DLP 程序化特征与 is_encrypted/写入通道实现逻辑摘要
8.0 KiB
DLP 环境特征调研与检测/写入实现逻辑
本文记录在本机(启用透明加密 DLP 的 Windows)上对 tests/DLP加密文件.pptx 与
tests/DLP解密文件.pptx 两个样本的实测结论、探索过程,以及 dlp_io 据此实现的
is_encrypted() 判定逻辑和未加密写入通道选择逻辑。所有结论都来自实测,不同 DLP
产品/策略可能不同,库的应对方式是运行时探测而非硬编码假设。
一、样本事实
两个样本文件内容相同(解密后 SHA-256 均为
968b5db1…d2947100),大小完全相同(2,466,572 字节)。加密文件在磁盘上存密文,
前 16 字节对比:
明文视图: 504b0304 0a000000 0000874e e2400000 (标准 ZIP/PPTX 头 "PK\x03\x04")
密文视图: 181b031a 1510197c 0a19 0e7c 6f726c5f (流式加密, 相同明文 0x00 在不同偏移密文不同)
特征:同尺寸、全文流式加密、无附加文件头/尾、无静态 magic 可识别。
二、文件属性层面无法区分(重要结论)
对两个样本逐项对比,全部一致:
attrib:都只有A属性(无 EFS 的 E 属性等差异)dir /r:均无附加数据流(ADS)- 文件大小、时间戳:一致
结论:无法通过任何文件元数据判断加密状态,唯一可靠的判别特征是内容。
这正是 is_encrypted() 采用内容对比的原因。
三、进程白名单模型(实测矩阵)
DLP 透明加密按「进程身份」决定是否介入读写。用「读取加密样本看到什么」实测:
| 进程 | 父进程 | 读加密样本视图 | 结论 |
|---|---|---|---|
python.exe |
任意(含非白名单 bash) | 明文 (PK 头) | 身份白名单,不继承、不降级 |
cmd.exe(type) |
任意 | 明文 | 白名单 |
powershell.exe |
任意 | 明文 | 白名单(读透明) |
certutil.exe |
bash / cmd | 密文 | 非白名单, raw 视图 |
Git Bash msys 工具(head/sha256sum/cat) |
bash | 密文 | 非白名单 |
git.exe(hash-object) |
bash | 明文 | 白名单(两样本 blob hash 相同) |
关键推论:
- helper 桥接设计成立:打包 EXE(非白名单)拉起
python.exe子进程,python 按身份 仍是白名单,读到的就是明文——这是库读取链路的根基。 cmd /c type不能当密文通道:cmd 是白名单,读到的同样是明文。社区直觉「用 cmd 读原始内容」在本 DLP 上不成立。- certutil 是本机可用的 raw 视图工具:但 DLP 拦截白名单进程直接拉起它
(python → certutil 报
WinError 786),必须经cmd /c certutil …中转。 cmd /c中文路径坑:把整条命令作为单个字符串传参会触发 cmd 的引号剥离规则, 中文文件名丢失(ERROR_FILE_NOT_FOUND);用列表参数(subprocess 自动逐个加引号) 则中文路径正常。
写入侧实测:
| 写入方 | 落盘结果(raw 视图校验) |
|---|---|
python.exe 直写(.bin / .pptx 后缀) |
明文(本机策略不加密 python 写入) |
powershell.exe(stdin 管道 → [IO.File]) |
明文 |
cmd /c more > f |
破坏二进制(0x00→CRLF、TAB→空格),不可用 |
cmd /c copy /b con f |
挂起等待控制台输入,不可用 |
certutil -decode - f |
不支持 stdin 输入,不可用 |
findstr ^ f |
raw 密文视图,但按行重新包装(0x0A→CRLF 注入),只能看头部不能还原内容 |
注意:白名单读透明 ≠ 写加密。本机 python/powershell 读透明但写入落盘明文; 「白名单进程写入会被加密」的策略在其他机器上仍可能存在——所以写入通道必须 运行时探测,不能假设。
四、探索过程(方法记录)
- 多通道哈希对比:
certutil -hashfile(非白名单视图)对两样本哈希不同 (33d3… vs 968b…),python 读取两样本哈希相同(968b…)——证明 DLP 生效、 python 白名单、certutil 非白名单,一条命令同时确认三件事。 - 头部字节对比:
head -c 64 | xxd(msys 工具,raw 视图)看到密文头,确认 同尺寸流加密、无附加头。 - 文件属性对比:
attrib/dir /r无差异——排除元数据检测路线。 - 写入通道候选实验:逐一验证 more/copy con/certutil -decode/findstr 全部
有二进制安全性或可用性问题,最终
powershell [Console]::OpenStandardInput()管道方案通过全字节(含 0x00/0x1A/0xFF)哈希校验。 - 误报纠正:
python → cmd /c type一度显示明文,先怀疑「白名单继承」, 后用bash → cmd /c type(仍是明文)和bash → python(明文)交叉验证, 确认 python/cmd 均为身份白名单而非继承。
五、is_encrypted() 判定逻辑
判据:文件已加密 ⟺ 白名单视图 ≠ 非白名单(raw)视图。
难点:当前进程自身是否白名单是未知的(Python/pyd 是白名单,打包 EXE 不是),
单次对比存在歧义。dlp_io.is_encrypted(path) 用两阶段消歧:
h_raw = certutil -hashfile(path) # 非白名单 raw 视图(经 cmd /c 中转)
h_native = hashlib(当前进程读 path)
if h_raw != h_native:
return True # 视图不一致: 文件已加密, 且当前进程是白名单
# 歧义分支: 文件未加密, 或文件已加密但当前进程是非白名单 EXE
head_helper = helper(白名单 python)读前 64 KiB
head_native = 当前进程读前 64 KiB
return head_helper != head_native
三种运行环境全部正确:
| 环境 | 加密文件 | 未加密文件 |
|---|---|---|
| Python / pyd(白名单) | 阶段一即判定 True | 阶段二两视图一致 → False |
| 打包 EXE(非白名单) | 阶段一相等(都看到密文)→ 阶段二 helper 明文头 ≠ 本地密文头 → True | 阶段二一致 → False |
代价:未加密文件需一次完整 certutil 哈希 + 一次本地完整读取 + helper 前 64 KiB 读取;大文件应缓存结果。库故意不引入「期望 magic 表」——内容对比与文件类型无关。
六、未加密写入通道选择逻辑
目标:任何环境下 dlp_io.open(path, "w"/"a"/"x") 落盘都是未加密文件。
首次写某后缀时:
1. 环境变量 DLP_IO_WRITE_CHANNEL=direct|powershell → 强制, 跳过探测
2. 直写探测: temp 目录写探针文件(同后缀, 含 0x00/0x1A/0xFF 等边界字节)
→ certutil raw 哈希 == 内容哈希 ?
- 一致 → DIRECT(EXE 环境恒真; 本机 python 也真)
- certutil 不可用 → 视为无 DLP → DIRECT
3. 否则 PowerShell 中转探测: 同 payload 经 stdin 管道由 powershell 子进程
([Console]::OpenStandardInput → [IO.File]::Open) 写盘 → 再校验 raw 哈希
- 一致 → POWERSHELL
4. 都失败 → raise DlpWriteError(绝不静默写出密文)
结果按后缀缓存(DLP 写策略常按文档类型区分)。
中转通道要点:字节只走 stdin 内存管道,不落地任何临时文件(白名单进程写的临时
文件本身可能被加密,会造成「密文套娃」);FileMode 映射 w→Create、
a→Append、x→CreateNew;x 模式在通道选择前先做本地存在性检查,保证
FileExistsError 语义与原生一致。
已知边界:探测文件写在 temp 目录,若 DLP 策略按目录区分,探针结论可能与目标
目录不符——此时用 DLP_IO_WRITE_CHANNEL 显式指定。
七、相关已知问题
- 保护区内
git push必现fatal: not a git repository(DLP 拦截 push 进程 对.git的访问模式),解法见.kimi-code/skills/git-push-dlp/(robocopy 镜像.git到 TEMP 后从 stage 目录推送)。 - 提交样本 fixture 时注意:本机
git.exe是白名单视图,commit 会把加密样本按 明文存入仓库。测试用例已按环境自适应编写(依据本机 raw 视图与本地视图是否 一致判断期望),CI(无 DLP)与 DLP 开发机都能通过。