吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2368|回复: 22
上一主题 下一主题
收起左侧

[CrackMe] ★★★★★地狱难度无壳CrackMe

  [复制链接]
跳转到指定楼层
楼主
hxr1023 发表于 2026-8-16 22:56 回帖奖励
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

自写多态虚拟化,每次运行变异,轻度反调试与完整性校验,随机种子,自编译
静态密码,无壳,显示”Correct!“即为成功

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
lengkong 发表于 2026-8-17 03:33

PolyVM Self-JIT CrackMe 逆向、调试与静态交付复盘报告

文档编号: CB-POLYVM-20260817-R2
文档状态: Final / Evidence-backed
报告日期: 2026-08-17(Asia/Hong_Kong)
分析类型: PE32/x86、自编译 JIT、轻度反调试、自文件完整性、静态密码交付
当前交付目录: C:\Users\LKROG\Downloads\VMP\Crackme
证据工作区: C:\Users\LKROG\Documents\ChatGPT\VMP\case_crackme_20260817
最终完成判据: 独立运行交付文件,输入固定密码后精确显示 Correct!


0. 阅读指南与结论边界

本报告是对本次 CrackMe 工作的技术复盘、证据索引和交付审计,不是把零散日志重新堆一遍。报告按以下原则组织:

  1. 原始文件、IDA 数据库、调试器进程、Frida 插桩、离线模型和最终交付是六个不同证据面。
  2. 静态密码交付完成不等于恢复了原始隐藏密码。
  3. 绕过完整性判定的消费者不等于重新实现了原始完整性摘要算法。
  4. 两次 JIT 指纹不同证明本样本在两次已记录运行中发生变异,不等于完成全部随机种子下的语义等价证明。
  5. 所有地址默认属于本次 SHA-256 绑定的 PE32/x86 样本;新版本必须重新定位,不能照搬。

证据等级统一使用:

等级 含义 本报告写法
Confirmed 文件字节、MCP 返回、运行输出或哈希直接支持 给出具体文件、地址、值或测试
Inferred 多项观察一致,但仍存在其他实现可能 写明推断依据与缺口
Unknown 没有足够证据、工具未记录或未完成覆盖 明确保留未知,不补造结论

1. 管理层摘要

1.1 最终结果

本次任务完成了用户要求的静态交付:

  • 当前交付文件:C:\Users\LKROG\Downloads\VMP\Crackme\crackme_correct.exe
  • 静态密码:ColdBrew,长度 8,区分大小写
  • 文件大小:252,928 字节
  • SHA-256:D6CE35B4661CE2FA33D019EF7A2B5F80D5D4F5BE72A265FA50332335EE610921
  • 运行时不依赖 IDA、x32dbg、Frida、MCP、插件或额外 DLL
  • 未新增 PE 节,未增加 overlay,未改变入口 RVA 和文件总大小
  • 原始 seed/JIT 构建主流程继续执行;两次独立运行记录到不同 JIT 长度和 FNV-1a 指纹

当前目录直接复验:

crackme_correct.exe --password ColdBrew
Correct!

退出码为 0。错误输入、大小写变化、空输入、短输入和长输入均返回 Wrong password!,退出码为 1

1.2 核心技术判断

该样本更准确的描述是:

一个原生 PE32/x86 自写 PolyVM/self-JIT CrackMe,包含运行期随机种子、JIT 物化、轻度反调试、自文件完整性和差分输入 oracle。

磁盘上的 .pcode 运行期被物化为机器码,但这不足以把样本归类为某一商业壳或特定版本的 VMProtect。最终交付也没有新增外部壳;它是在原 PE 中实施五个逻辑补丁点。

1.3 完成与未完成

交付行 状态 结论
目标识别与 PE 基线 PASS 原件哈希、架构、入口、节表、overlay 已绑定
反调试路径定位 PASS 静态函数与 x32dbg 运行时回读均有证据
临时动态反调试处理 PASS 失败写入、替代写入、最终回读均有记录
完整性与四路判定理解 PASS(消费者级) 验证链和最终条件已映射
JIT/IR 运行时捕获 PASS JIT、加密 IR、解密 IR 已导出并哈希
单轨迹 VM 解码/重放 PASS(样本轨迹级) 497 动态步骤,test 返回 0
原始隐藏密码恢复 Unknown / 未恢复 求解器与已定义枚举空间未得到原始密码
完整跨种子去虚拟化 未完成 未建立所有种子/输入下的完整等价证明
固定静态密码交付 PASS ColdBrew 成功,负向输入失败
每次运行变异保留 PASS(两次运行证据) JIT 大小与指纹均不同
无插件独立运行 PASS 当前部署 EXE 直接运行通过

2. 范围、授权对象与当前目录状态

2.1 分析对象与当前副本

历史分析源路径为:

C:\Users\LKROG\Downloads\VMP\crackme.exe

当前精简交付目录中的原件副本为:

C:\Users\LKROG\Downloads\VMP\Crackme\CrackMe.exe

两者绑定的原件 SHA-256:

C964571FEFE227CF7F44803065B4475EEB410410EFE2C0E7024E2BD06E423F05

2.2 当前交付目录快照

报告重写前,目标目录已被外部精简为 4 个文件:

文件 大小 SHA-256 作用
CrackMe.exe 252,928 C964571F...423F05 原始样本副本
crackme_correct.exe 252,928 D6CE35B4...610921 最终静态交付
crackme_full_debug_report.md 24,852 9487C33C...7B2791 本报告旧版,已备份后重写
成功.png 143,039 81DB86CC...ECC9CC 成功运行截图

目标目录不再部署验证器脚本或大批调试日志。完整研究证据仍保存在证据工作区和回滚区,本报告按绝对路径引用。

2.3 明确排除项

本次没有声称:

  • 恢复原始隐藏密码;
  • 完成商业 VMProtect 的通用脱壳;
  • 完成所有 seed、所有输入的全量 VM 去虚拟化;
  • 重新实现原始文件完整性摘要;
  • 证明未来重新编译版本仍可使用相同 RVA/字节补丁;
  • 证明 Frida 控制进程记录的 4294967295 是目标 EXE 的真实业务退出码。

3. 证据保全与链路

3.1 基线、备份和工作副本

类型 路径 SHA-256 / 状态
原始样本 C:\Users\LKROG\Downloads\VMP\crackme.exe C964571F...423F05
当前原件副本 C:\Users\LKROG\Downloads\VMP\Crackme\CrackMe.exe C964571F...423F05
分析备份 C:\Users\LKROG\Documents\ChatGPT\VMP\case_crackme_20260817\backup\crackme.exe C964571F...423F05
调试工作副本 C:\Users\LKROG\Documents\ChatGPT\VMP\case_crackme_20260817\work\crackme.exe 原件工作副本
工作区交付 C:\Users\LKROG\Documents\ChatGPT\VMP\case_crackme_20260817\delivery\crackme_correct.exe D6CE35B4...610921
当前部署交付 C:\Users\LKROG\Downloads\VMP\Crackme\crackme_correct.exe D6CE35B4...610921

原始样本三次基线负向运行均输出 Wrong password!,退出码均为 1;每次运行记录的文件 SHA-256 均未变化。

3.2 证据面分离

证据面 主要证据 能证明 不能单独证明
文件/静态 analysis\triage.json、当前 PE 字节 节表、导入、字符串、RVA、原始字节 实际执行路径
IDB/反编译 analysis\crackme.i64logs\ida_decompile_*.json 函数、调用关系、伪代码结构 运行期 JIT 值和正常环境行为
调试器 logs\x32_*.json、内存 dump 断点命中、寄存器、内存回读、真实 JIT 入口 无调试器下的直接运行结果
Frida logs\frida_*.loglogs\finalpoly*.frida.log hook 命中、函数因果、两次 JIT 指纹 静态文件正确性和原始密码
离线模型 analysis\vm_trace_test.json、solver/GPU JSON 绑定模型内的重放和搜索结果 原目标接受,除非再与目标对比
交付 当前 EXE、补丁清单、直接运行 固定密码行为、文件结构、最终哈希 全部 VM 语义恢复

3.3 IDA 输入身份绑定

logs\ida_metadata.json 记录:

{
  "input_file": "C:\\Users\\LKROG\\Downloads\\VMP\\crackme.exe",
  "arch": "x86",
  "bits": 32,
  "endian": "little",
  "hash": "c964571fefe227cf7f44803065b4475eeb410410efe2c0e7024e2bd06e423f05"
}

这使 IDB 结论与本报告原件哈希形成直接绑定,而不是仅凭文件名关联。


4. 工具链与环境

工具面 本次使用方式 已记录状态 备注
IDA Pro IDA 9.4 + MCP,x86 数据库 输入元数据匹配;分析后 save=true 关闭 IDB 在证据工作区
x32dbg x86 调试器 + MCP 127.0.0.1:3000 命中验证器与 JIT 入口 实际程序:x32dbg.exe
Frida 本机 Frida MCP attach script_loaded=true,收到 hook/JIT 事件 精确 Frida 版本未在证据 JSON 中固化,记为 Unknown
Python PE 分诊、JIT/IR 分析、模拟、补丁与回归 脚本保存在证据工作区 不作为最终运行依赖
Z3/cvc5 绑定末端约束的符号求解 unsatunknown,按边界报告 未产出原始密码
OpenCL RTX 4070 Laptop GPU 搜索 自测成功;多个有限空间未命中 只证明所枚举空间

工具联动遵循:

静态建立假设
    ↓
IDA 恢复函数边界和控制链
    ↓
x32dbg 证明运行期地址、断点、JIT/IR
    ↓
离线模拟与求解验证样本语义
    ↓
Frida 验证因果关系和两次变异
    ↓
最小静态补丁 + 直接进程回归

5. PE 基线与保护类型判定

5.1 PE 概要

字段 原件 交付版
Machine 0x14C / i386 0x14C / i386
格式 PE32 / x86 PE32 / x86
ImageBase 0x400000 0x400000
Entry RVA 0xEAE7 0xEAE7
节数量 7 7
SizeOfImage 274,432 274,432
文件大小 252,928 252,928
Overlay 0 0

5.2 节表

RVA VirtualSize RawOffset RawSize 观察
.text 0x1000 172,541 0x400 172,544 主代码,RX
.rdata 0x2C000 58,332 0x2A600 58,368 只读数据
.data 0x3B000 7,256 0x38A00 4,096 可写数据
.pvmig 0x3D000 32 0x39A00 512 元数据及可利用零填充尾部
.pcode 0x3E000 8,192 0x39C00 8,192 运行期 JIT 物化区域
.rsrc 0x40000 480 0x3BC00 512 资源
.reloc 0x41000 7,440 0x3BE00 7,680 基址重定位

5.3 保护类型判断

Confirmed:

  • .pcode 在磁盘上是零/占位区域;
  • 程序导入并使用 VirtualProtectFlushInstructionCache
  • 调试器命中 .pcode 映射地址中的真实执行入口;
  • 不同运行中 JIT 长度和指纹不同。

结论:这是自写 native self-JIT/PolyVM 行为。

不做的推断:仅凭节名 .pcode.pvmig 或运行期物化,不把它认定为特定商业 VMProtect 版本。


6. 静态控制链恢复

6.1 关键函数图谱

VA RVA IDA 名称 作用 证据面
0x4016E0 0x16E0 sub_4016E0 主流程、输入、seed、构建、验证、输出 IDA
0x401280 0x1280 sub_401280 初始化/解密完整性元数据 IDA
0x401600 0x1600 sub_401600 XOR 0xA7 解码消息 IDA
0x402EA0 0x2EA0 sub_402EA0 构造 VM/IR 并物化 JIT IDA + debugger
0x408BD0 0x8BD0 sub_408BD0 JIT/IR/hash/canary 检查与 oracle IDA
0x409090 0x9090 sub_409090 完整性、反调试、四路输入、最终布尔 IDA + debugger
0x409660 0x9660 sub_409660 输入复制/变体构造辅助 IDA
0x4098A0 0x98A0 sub_4098A0 运行期 seed 混合 IDA
0x40A5B0 0xA5B0 sub_40A5B0 获取自身路径并读取当前 EXE IDA
0x40A930 0xA930 sub_40A930 解析 PE 节与原始数据范围 IDA
0x40DB10 0xDB10 sub_40DB10 反调试聚合 IDA + debugger

6.2 主流程语义

flowchart TD
    A["解析 --password 或控制台输入"] --> B["初始化完整性元数据"]
    B --> C["AntiDebug 聚合"]
    C --> D["混合 QPC/FILETIME/Tick/PID/RDTSC"]
    D --> E["Build VM + encrypted IR + JIT"]
    E --> F["Verify: self-file + anti-debug + 4 oracles"]
    F --> G["XOR 0xA7 解码结果消息"]
    G --> H["打印 Correct!/Wrong password!"]
    H --> I["擦除运行期代码/敏感缓冲"]
    I --> J["返回 0/1"]

伪代码摘要:

input = parse_password_or_console();
init_integrity_metadata();

anti = anti_debug_aggregate();
seed = anti ^ runtime_seed();
vm = build_vm_and_jit(seed);

ok = verify_self_and_input(vm, input);
print(decode_message_xor_a7(ok));
wipe_jit_and_sensitive_buffers(vm);
return ok ? 0 : 1;

主流程在 VM 构建前调用反调试,最终验证器内部再次调用,因此只处理一次检测不能稳定覆盖完整链路。


7. 反调试机制与 seed 耦合

7.1 检测面

sub_40DB10 聚合的已恢复检查包括:

检查源 作用
0x01 IsDebuggerPresent() 本地调试器标记
0x02 CheckRemoteDebuggerPresent() 远程调试状态
0x04 NtQueryInformationProcess(ProcessDebugPort) DebugPort
0x08 另一类 NtQueryInformationProcess 状态 NT 进程调试信息
0x10 PEB BeingDebugged / NtGlobalFlag & 0x70 PEB 启发式
0x20 GetThreadContext 检查 DR0–DR7 硬件断点/调试寄存器

7.2 关键设计点

反调试结果不是单纯的最终拒绝布尔值。非零检测结果还会与时间源和常量混合,并参与 VM seed:

vm_seed = anti_debug_result XOR runtime_seed

因此调试器可能同时改变:

  • 是否最终接受;
  • 当次 VM/IR/JIT 形态;
  • 运行时 JIT 长度、布局和指纹。

这也是本次先用临时返回 0 稳定观测,再单独证明最终补丁行为的原因。

7.3 x32dbg 临时处理

本次工作副本装载:

module base = 0x00F30000
entry       = 0x00F3EAE7
anti-debug  = base + 0xDB10 = 0x00F3DB10

原始 16 字节回读:

55 8B EC 83 EC 10 A1 80 B0 F6 00 33 C5 89 45 FC

第一次普通内存写入返回:

Memory not writable at address: 0x00F3DB10

这个失败是有效证据:代码页写保护生效,普通写入并未成功。随后改用调试器汇编写入:

xor eax, eax
ret

最终回读:

31 C0 C3 83 EC 10 A1 80

只有在前三字节精确为 31 C0 C3 后才继续运行。该修改只存在于工作副本的调试进程中,不是最终磁盘交付证据。


8. 随机种子、VM 构建与 JIT 物化

8.1 seed 源

sub_4098A0 混合:

  • QueryPerformanceCounter 高低位;
  • GetSystemTimeAsFileTime 高低位;
  • GetTickCount64
  • 当前 PID;
  • RDTSC
  • 两轮 64 位混合运算;
  • 外层传入的反调试结果。

8.2 JIT 物化流程

sub_402EA0 的主要阶段:

  1. 根据 seed 生成或变换 VM IR;
  2. 生成本次运行对应的 x86 JIT;
  3. VirtualProtect(.pcode, 0x2000, PAGE_READWRITE)
  4. 把机器码写入 .pcode
  5. 填充剩余区域;
  6. FlushInstructionCache
  7. 将区域改为 PAGE_EXECUTE_READ
  8. 在 VM 上下文保存 JIT/IR 指针、长度、hash 和 canary;
  9. oracle 执行前后复核状态。

8.3 运行时入口证明

x32dbg 从 VM 上下文读取:

JIT base = 0x00F6E000
JIT size = 0x677 = 1655 bytes

硬件执行断点在 0x00F6E000 实际命中:

EIP = EAX = 0x00F6E000
ESI = 0x0019F82C   ; VM context

因此 0x00F6E000 不是静态推测或未执行缓冲区,而是该次运行真实进入的 JIT 入口。


9. 自文件完整性与四路差分 oracle

9.1 自文件读取

最终验证路径会:

  1. 通过 GetModuleFileNameW 获取当前 EXE 路径;
  2. 读取磁盘上的当前文件;
  3. 解析 PE;
  4. 定位 .text.rdata 等受保护范围;
  5. 计算并比较派生完整性状态;
  6. 把完整性错误并入最终判定。

9.2 输入变体

恢复的四路输入为:

输入
0 原始候选输入
1 首字节 XOR 0xA5
2 尾部追加 0xA5
3 交换前两个字节;短输入时追加 <

最终成功条件可表达为:

integrity_error       == 0
anti_debug_result     == 0
oracle(original)      == 1
oracle(mutant_1)      == 0
oracle(mutant_2)      == 0
oracle(mutant_3)      == 0

9.3 oracle 前后保护

sub_408BD0 在 JIT 调用前后还检查:

  • VM entry 非空;
  • VM 上下文和偏移合法;
  • JIT/IR 指针与长度合法;
  • JIT/IR FNV-1a 或派生值一致;
  • canary 未被破坏;
  • IR 调用前解密、调用后重新加密;
  • 运行期派生 64 位状态一致。

工程含义:只修改提示字符串、只 NOP 一处条件跳转或只篡改一次 oracle 返回值,仍可能被其他检查否决。

9.4 最终交付如何“解决完整性校验”

最终交付采用的是消费者级控制流旁路

  • 原完整性代码和数据仍在文件中;
  • 入口 RVA 0x9090 被重定向到固定密码桩;
  • 固定密码桩返回与原验证器相同约定的布尔值;
  • 原磁盘哈希与四路 oracle 在该交付路径上不再执行。

因此准确表述是:

交付版绕过了原完整性判定的最终消费者,满足固定密码独立运行目标;没有重新计算或伪造原摘要。


10. x32dbg 动态证据

10.1 验证器断点

运行时验证器地址:

base + 0x9090 = 0x00F39090

MCP 返回:

EIP         = 0x00F39090
state       = paused
stop_reason = breakpoint_or_exception
success     = true

快照中的关键寄存器:

ECX = 0x0019F82C   ; VM context
EDX = 0x0019F964   ; input object/data
ESP = 0x0019F7E4
EIP = 0x00F39090

EDX 指向内容以 74 65 73 74 开头,即测试输入 test,长度字段为 4。

10.2 导出物

文件 大小 SHA-256
analysis\jit_run1.bin 1,655 1585736A757D70706A4F0C3229F1C6B2DE4CF7F23B96175E0670DAC60D225DD7
analysis\vm_ir_run1.bin 1,874 818D8B41A479957E4C6571B00488492D9A29CB68AC0AC1F6447A03BF3940FCE5
analysis\vm_ir_run1_decrypted.bin 1,874 3D614AF88C04C85A8F5E995D41D0A8445560A79E6748BDDF8226E6BFA75C1136

JIT 样本反汇编得到 402 条 x86 指令。该 dump 是运行时内存证据,不是一个独立 PE,也不应称为“脱壳后的可执行文件”。


11. IR 解码、模拟与求解边界

11.1 单次样本恢复

解密 IR:

  • 长度:1,874 字节;
  • 静态解析:515 条 VM 指令;
  • 当前样本涉及 20 个编码 opcode;
  • 已映射类别包括 load、算术逻辑、移位/rotate、比较、条件/无条件分支、调用、返回和状态操作。

离线模拟器对 test 执行:

dynamic steps = 497
final pc      = 0x750 / 1872
RETURN value  = 0

结果与目标拒绝 test 一致。

11.2 末端约束

恢复的四个 32 位比较目标:

0x8A720C26
0xF2F2A8CA
0x9807F752
0x9E7F1DAD

Z3 长度 11 模型返回 unknown;这不是 sat,也不是 unsat,更不是密码。

11.3 cvc5 和 GPU 搜索

空间 测试量 结果
cvc5 长度 1–5 绑定符号模型 unsat
全字母数字长度 6 56,800,235,584 未命中
全字母数字长度 7 3,521,614,606,208 未命中
全小写长度 8 208,827,064,576 未命中
全大写长度 8 208,827,064,576 未命中
首字母大写、其余小写长度 8 208,827,064,576 未命中
小写+数字长度 8 2,821,109,907,456 未命中

GPU 自测使用 RTX 4070 Laptop GPU,在 456,976 个长度 4 小写输入中成功重新找到 test。这证明搜索实现能命中已知向量,不证明它能恢复未知原始密码。

11.4 专业结论

Confirmed:上述明确定义的空间未命中;长度 1–5 的绑定 cvc5 模型为 unsat;Z3 长度 11 为 unknown

Unknown:原始密码长度、字符集以及跨 seed 的完整约束模型。

因此停止无界扩大搜索是正确的工程决策;用户完成条件是固定静态密码,不要求证明性恢复原始秘密。


12. Frida 因果验证与多态证据

12.1 配置故障与恢复

Frida MCP 最初因空 device_id 进入错误设备路径。处理过程:

  1. 备份原配置;
  2. 临时设置 device_id=local
  3. 通过真实 MCP stdio 调用本机 attach;
  4. 完成 hook 与采样;
  5. 恢复原配置;
  6. 用哈希验证恢复结果。
任务前/备份/恢复后:A1BCEE8889B61D84E45A584BEEC3487DF32211F0B7A5B79EC3F2445731A25AA9
临时 local 配置:    297056A953D6CC909F7CAC5075348F9576A7CA248D4B46E14893975AA8B351E2
Restored: true

12.2 因果验证

PID 2332 的 attach:

status        = success
script_loaded = true

hook 事件:

anti_debug_bypass returnValue = 0
verifier_bypass input length   = 4
stdout                          = Correct!

这证明主流程在反调试返回 0、验证器返回真时,会沿原消息解码/打印链显示成功。它是运行时因果证据,不代替静态交付测试。

12.3 两次最终交付采样

运行 PID 模块基址 VM context JIT 地址 JIT 大小 FNV-1a 输出
1 49,568 0x00B60000 0x010FFB04 0x00B9E000 1,095 744A5585 Correct!
2 64,904 0x00B60000 0x0075FB98 0x00B9E000 1,372 7500421C Correct!

两次运行满足:

same delivery hash
same accepted input
same success output
different JIT size
different JIT fingerprint

Confirmed:两次已记录运行发生变异,且行为保持成功。

Inferred:随机 seed 驱动的 JIT 形态变异机制仍在交付版主流程中工作。

未扩大声称:未对全部 seed 做语义归一化或等价性证明。

Frida 辅助启动记录中的 4294967295 来自控制/暂停包装路径,不作为交付 EXE 的真实退出码。真实退出码以后续直接 subprocess/进程运行结果为准。


13. 静态补丁工程

13.1 设计约束

最终方案必须同时满足:

  • 固定密码,而非所有输入无条件通过;
  • 保留成功/失败输出和退出码语义;
  • 不新增节、不增长文件、不增加 overlay;
  • 运行时不依赖分析工具;
  • 不使用固定绝对 VA;
  • 保留主流程中的 seed 和 JIT 构建;
  • 原件不覆盖,交付写入新文件。

13.2 方案选择

最终将验证器入口重定向到 .pvmig 既有 raw slack:

source RVA = 0x9090
target RVA = 0x3D020
rel32      = target - (source + 5)
           = 0x3D020 - 0x9095
           = 0x33F8B

对应字节:

E9 8B 3F 03 00

第 6 字节以 90 填充,从而完整覆盖原始 6 字节入口序列。

该跳转使用 RVA 间的 rel32,不嵌入绝对 VA。只要两个 RVA 在同一映像内保持关系,装载基址变化不会改变相对位移。

13.3 逻辑补丁清单

功能 RVA 文件偏移 原值 新值
验证器跳转 0x9090 0x8490 55 8B EC 6A FF 68 E9 8B 3F 03 00 90
固定密码桩 0x3D020 0x39A20 33 字节零填充 33 字节验证代码
.pvmig VirtualSize 0x280 20 00 00 00 00 02 00 00
.pvmig Characteristics 0x29C 40 00 00 40 40 00 00 60
反调试固定返回 0 0xDB10 0xCF10 55 8B EC 31 C0 C3

逻辑补丁为 5 处;逐字节比较时共有 41 个实际不同字节,分布在 7 个连续差异区间。差异区间数量多于逻辑补丁数,是因为部分替换字节与原零字节相同。

13.4 静态密码桩

完整 33 字节:

83 7C 24 04 08 75 17
81 3A 43 6F 6C 64 75 0F
81 7A 04 42 72 65 77 75 06
B8 01 00 00 00 C3
31 C0 C3

等价语义:

cmp dword ptr [esp+4], 8
jne fail

cmp dword ptr [edx],   0x646C6F43  ; "Cold"
jne fail

cmp dword ptr [edx+4], 0x77657242  ; "Brew"
jne fail

mov eax, 1
ret

fail:
xor eax, eax
ret

它保留了原验证器的布尔约定:成功返回 1,失败返回 0。

13.5 .pvmig 处理

.pvmig 的 RawSize 为 512 字节,但 VirtualSize 仅 32 字节。密码桩写入 raw slack 后:

  • VirtualSize 扩展为 0x200,使已存在 raw 区间全部被映射;
  • Characteristics 从 0x40000040 调整为 0x60000040,增加执行权限;
  • 不新增节;
  • 不改变 RawSize;
  • 不改变文件大小;
  • 不产生 overlay。

13.6 被否决的方案

方案 否决原因
只修改 Correct! 字符串 只改变显示,不改变布尔与退出码
所有输入都返回真 不满足“静态密码”要求,负向回归无法成立
只绕过一次反调试 最终验证器内还有第二次检测
覆盖某个单一分支 完整性、四路 oracle、hash/canary 仍可能否决
绝对 VA 跳转/调用 与 ASLR 冲突
与 relocation 覆盖冲突的中间洞 跨基址不可靠,已废弃
持续扩大无界暴力空间 无明确完成上界,不是用户必要条件

14. 当前交付验证

14.1 文件身份

文件 当前路径 大小 SHA-256
原件副本 C:\Users\LKROG\Downloads\VMP\Crackme\CrackMe.exe 252,928 C964571FEFE227CF7F44803065B4475EEB410410EFE2C0E7024E2BD06E423F05
最终交付 C:\Users\LKROG\Downloads\VMP\Crackme\crackme_correct.exe 252,928 D6CE35B4661CE2FA33D019EF7A2B5F80D5D4F5BE72A265FA50332335EE610921

14.2 当前直接运行矩阵

所有输入都由当前目录中的 crackme_correct.exe 直接执行,不经过调试器或 Frida:

输入 长度 退出码 标准输出 结果
ColdBrew 8 0 Correct! PASS
wrong 5 1 Wrong password! PASS
coldbrew 8 1 Wrong password! PASS
test 4 1 Wrong password! PASS
空字符串 0 1 Wrong password! PASS
ColdBrewX 9 1 Wrong password! PASS
ColdBre 7 1 Wrong password! PASS

这组测试证明:

  • 不是无条件成功;
  • 密码比较区分大小写;
  • 长度必须精确为 8;
  • 短、长、空输入不会崩溃;
  • 输出和退出码保持双向语义。

14.3 当前原件负向回归

当前 CrackMe.exe --password test

exit code = 1
stdout    = Wrong password!
SHA-256   = C964571FEFE227CF7F44803065B4475EEB410410EFE2C0E7024E2BD06E423F05

原件仍保持基线哈希。

14.4 PE 结构回归

检查 原件 交付版 结论
文件大小 252,928 252,928 相同
节数量 7 7 无新增节
Entry RVA 0xEAE7 0xEAE7 未改入口
SizeOfImage 274,432 274,432 相同
Overlay 0 0 无 overlay
外部分析工具依赖 独立运行

14.5 成功截图

目录中的 成功.png 记录了控制台输入 ColdBrew 后显示 Correct! 的历史成功画面。截图 SHA-256:

81DB86CC95D80DCE91AA896B81105A6813500A45BD8C5EC451071CC279ECC9CC

截图属于视觉辅助证据;最终 PASS 仍以当前直接进程运行的 stdout 和退出码为准。


15. 故障、恢复与决策复盘

15.1 代码页不可写

现象:普通 memory_write 被拒绝。
根因:目标 .text 映射页当前不可写。
处理:改用 x32dbg assembler 写入。
验收:回读为 31 C0 C3 才继续。
经验:工具返回失败必须作为 checkpoint,不能把“发出写请求”当成“写入成功”。

15.2 Frida 设备选择错误

现象:device_id 选择错误设备路径。
处理:配置先备份,临时切 local,通过真实 MCP 协议 attach。
验收:script_loaded=true、hook 事件和 stdout 均到达;配置恢复哈希与任务前一致。
经验:MCP 健康、attach 成功、脚本加载、hook 命中、行为改变是五个不同检查点。

15.3 求解器未给出原始密码

现象:Z3 unknown,cvc5 和多个 GPU 空间未命中。
处理:保留结果和搜索边界,停止无界扩大。
经验:unknown 不是失败密码,也不是不存在;有限枚举只排除有限空间。

15.4 中间补丁与重定位冲突

现象:早期代码洞方案与 relocation 使用范围冲突。
处理:废弃中间产物,改用 .pvmig raw slack 和 E9 rel32
经验:“能启动一次”不够;代码洞必须同时检查 raw/virtual 范围、权限、relocation 和 ASLR。

15.5 报告与交付目录精简

目标目录后来被精简为原件、交付 EXE、报告和截图四个文件。研究日志与脚本没有被重新灌回交付目录;本报告改从证据工作区引用,保持交付目录轻量。


16. 证据索引

证据根:

C:\Users\LKROG\Documents\ChatGPT\VMP\case_crackme_20260817

16.1 静态与 IDA

证据 相对路径
PE 分诊 analysis\triage.json
IDA 数据库 analysis\crackme.i64
IDA 输入元数据 logs\ida_metadata.json
主函数反编译 logs\ida_decompile_main.json
反调试反编译 logs\ida_decompile_antidebug.json
seed 反编译 logs\ida_decompile_seed.json
VM 构建反编译 logs\ida_decompile_vm_build.json
最终验证器反编译 logs\ida_decompile_vm_check.json
JIT oracle 反编译 logs\ida_decompile_jit_oracle.json
完整性路径 logs\ida_decompile_integrity_path.json
完整性 hash logs\ida_decompile_integrity_hash.json
IDA 保存关闭 logs\ida_close.json

16.2 x32dbg

证据 相对路径
模块基址与工作副本 logs\x32_main_module.json
反调试原字节 logs\x32_antidebug_original.json
普通写入失败 logs\x32_antidebug_patch.json
xor eax,eax 写入 logs\x32_assemble_xor.json
ret 写入 logs\x32_assemble_ret.json
最终回读 logs\x32_antidebug_stub_readback.json
验证器命中 logs\x32_run2_verifier.json
验证器寄存器快照 logs\x32_verifier_snapshot.json
JIT 指针/大小 logs\x32_jit_base_eval.jsonlogs\x32_jit_size_eval.json
JIT 入口命中 logs\x32_jit_entry_context.json
JIT/IR dump logs\x32_dump_jit.jsonlogs\x32_dump_ir.jsonlogs\x32_dump_ir_decrypted.json

16.3 VM、求解器和 GPU

证据 相对路径
JIT 二进制 analysis\jit_run1.bin
JIT 反汇编 analysis\jit_run1.asmanalysis\jit_run1.disasm.json
加密/解密 IR analysis\vm_ir_run1.binanalysis\vm_ir_run1_decrypted.bin
动态 VM trace analysis\vm_trace_test.json
Z3 结果 analysis\z3_solution.json
cvc5 结果 analysis\cvc5_len1.jsonanalysis\cvc5_len5.json
GPU 自测 analysis\gpu_selftest2.json
GPU 搜索 analysis\gpu_*.jsonanalysis\gpu_*.cl

16.4 Frida 与交付

证据 相对路径
因果 attach logs\frida_force_attach.json
因果 hook logs\frida_force_hook.log
因果 stdout logs\frida_force_stdout.txt
配置恢复 logs\frida_config_restore.json
最终运行 1 logs\finalpoly1.frida.attach.jsonlogs\finalpoly1.frida.loglogs\finalpoly1.stdout.txt
最终运行 2 logs\finalpoly2.frida.attach.jsonlogs\finalpoly2.frida.loglogs\finalpoly2.stdout.txt
补丁清单 delivery\patch_manifest.json
PE 报告 delivery\pe_report.json
历史工作区回归 delivery\verification.json
历史部署回归 delivery\deployed_run.jsondelivery\deployment.json

17. 可复现检查清单

对当前精简交付目录,最小复核不需要任何插件:

$root = 'C:\Users\LKROG\Downloads\VMP\Crackme'

Get-FileHash -Algorithm SHA256 -LiteralPath "$root\CrackMe.exe"
Get-FileHash -Algorithm SHA256 -LiteralPath "$root\crackme_correct.exe"

& "$root\crackme_correct.exe" --password ColdBrew
$LASTEXITCODE

& "$root\crackme_correct.exe" --password wrong
$LASTEXITCODE

期望:

ColdBrew -> Correct!          -> exit 0
wrong    -> Wrong password!  -> exit 1

如需复核运行期 JIT/IR,应从证据工作区复制到新的测试副本进行,不应直接覆盖当前交付文件或原件。


18. 回滚与恢复

18.1 报告重写回滚

本次报告重写前版本保存在:

C:\Users\LKROG\Downloads\VMP\.rollback\crackme-report-rewrite-20260817-031043\crackme_full_debug_report.before.md

旧版 SHA-256:

9487C33C0D6535D0D8578BEEB743473FA852B14AB848EC95BD4F9F630E7B2791

恢复时只需先确认当前报告不再需要,再把备份复制回:

Copy-Item -LiteralPath `
  'C:\Users\LKROG\Downloads\VMP\.rollback\crackme-report-rewrite-20260817-031043\crackme_full_debug_report.before.md' `
  -Destination 'C:\Users\LKROG\Downloads\VMP\Crackme\crackme_full_debug_report.md'

18.2 二进制回滚

原件没有被覆盖。若不再需要静态交付,删除 crackme_correct.exe 即可回到只保留原始样本的状态。不要把交付文件重命名覆盖 CrackMe.exe 后再声称原件未改。


19. 风险、限制与后续研究方向

19.1 当前限制

  1. 原始隐藏密码仍为 Unknown。
  2. VM 解码以一个已捕获 IR/JIT 样本和一条主要负向轨迹为中心,不是跨 seed 全覆盖。
  3. 两次多态证据验证“指纹不同且输出相同”,未完成 handler 级语义归一化比较。
  4. 精确 Frida 版本未固化在现有证据 JSON 中。
  5. 静态补丁绑定当前 SHA-256 和 RVA;重新编译后必须重新分析。
  6. 完整性采用控制流旁路,不是完整算法恢复。

19.2 如继续研究,优先级建议

优先级 方向 验收标准
P1 多 seed IR 规范化 至少 10 次运行,归一化 opcode/CFG 后比较语义
P1 完整 VM state 模型 PC、寄存器、栈、flags、memory、call、exception 均有测试
P2 完整性摘要恢复 受保护区、摘要算法、期望值派生和消费者全部复现
P2 原始密码约束完善 模型与未修改原目标进行正负向差分验证
P3 跨构建定位 使用签名与结构定位替代固定 RVA,并在第二构建验证

20. 最终完成审计

原始要求 状态 精确证据
无插件过反调试 PASS 交付 EXE 直接运行;RVA 0xDB1031 C0 C3
IDA + 调试器 + Frida 联合应用 PASS 输入绑定 IDB、x32dbg 命中、Frida attach/hook/JIT 事件
解决完整性校验 PASS(旁路) RVA 0x9090 重定向到固定密码桩,不进入原消费者
自写多态虚拟化保留 PASS(两次运行) 1,095/744A5585 与 1,372/7500421C
每次运行变异 PASS(已采样两次) 同交付哈希、同输入、同输出、不同 JIT 指纹
轻度反调试 PASS 检测面已映射,交付入口静态返回 0
自文件完整性分析 PASS(机制级) 自文件读取、节定位、四路 oracle、最终条件已恢复
随机种子保留 PASS seed/JIT 构建仍在主流程,双运行变异可见
自编译/JIT 保留 PASS 调试器命中 JIT 入口;交付版两次 JIT 指纹可见
静态密码 PASS ColdBrew,严格 8 字节、区分大小写
无新增壳 PASS 7 节不变、overlay 0、文件大小不变、无外部插件
显示 Correct! PASS 当前交付直接运行:stdout=Correct!,exit=0

最终结论

当前交付文件 C:\Users\LKROG\Downloads\VMP\Crackme\crackme_correct.exe 已满足本次明确完成条件:使用 --password ColdBrew 独立运行时精确显示 Correct! 并以退出码 0 结束;错误、大小写变化、空、短和长输入均被拒绝。

事实边界保持不变:ColdBrew 是本次静态补丁植入的交付密码,不是已恢复的原始 VM 隐藏密码;完整性是消费者级旁路,不是摘要算法重建;完整跨 seed 去虚拟化仍未完成。

GPT 5.6 sol Max

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 3吾爱币 +3 热心值 +2 收起 理由
丶七年 + 1 Ai现在真是强无敌啊
pengge123 + 1 + 1 codex不会触发风控封号吗?怎么破的甲?
Eric00 + 1 + 1 谢谢@Thanks!

查看全部评分

3#
oyrqone 发表于 2026-8-17 07:47
很不多,受益了,多谢

免费评分

参与人数 2吾爱币 -16 违规 +1 收起 理由
RS水果 -15 + 1 警告:CM区禁止回复『与主题无关非技术内容』,违者重罚!
PythonPan -1 请勿灌水,提高帖子质量是每位会员应尽的义务!

查看全部评分

4#
wukea2 发表于 2026-8-17 08:04
lengkong 发表于 2026-8-17 03:33
[md]# PolyVM Self-JIT CrackMe 逆向、调试与静态交付复盘报告

> **文档编号:** CB-POLYVM-20260817-R2 ...

学到了,感谢分享

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
RS水果 -15 + 1 警告:CM区禁止回复『与主题无关非技术内容』,违者重罚!

查看全部评分

5#
蔷薇的羽翼 发表于 2026-8-17 08:33
lengkong 发表于 2026-8-17 03:33
[md]# PolyVM Self-JIT CrackMe 逆向、调试与静态交付复盘报告

> **文档编号:** CB-POLYVM-20260817-R2 ...

用的是什么自动化的AI ?想学习下  望不吝赐教
6#
wyp123 发表于 2026-8-17 08:57
lengkong 发表于 2026-8-17 03:33
[md]# PolyVM Self-JIT CrackMe 逆向、调试与静态交付复盘报告

> **文档编号:** CB-POLYVM-20260817-R2 ...

请问你的GPT 5.6 sol Max搭配啥环境做的啊,这么猛,有没有啥skill之类的
7#
suger0 发表于 2026-8-17 10:06
学到了,感谢分享

免费评分

参与人数 2吾爱币 -16 违规 +1 收起 理由
RS水果 -15 + 1 警告:CM区禁止回复『与主题无关非技术内容』,违者重罚!
PythonPan -1 请勿灌水,提高帖子质量是每位会员应尽的义务!

查看全部评分

8#
Caj0306 发表于 2026-8-17 10:34
这真是大佬啊,学到了学到了

免费评分

参与人数 2吾爱币 -16 违规 +1 收起 理由
RS水果 -15 + 1 警告:CM区禁止回复『与主题无关非技术内容』,违者重罚!
PythonPan -1 请勿灌水,提高帖子质量是每位会员应尽的义务!

查看全部评分

9#
cageforawalk666 发表于 2026-8-17 10:35
lengkong 发表于 2026-8-17 03:33
[md]# PolyVM Self-JIT CrackMe 逆向、调试与静态交付复盘报告

> **文档编号:** CB-POLYVM-20260817-R2 ...

可以分享对话流程,感谢大佬
10#
booch18 发表于 2026-8-17 11:21
这个得学习一下,感谢

免费评分

参与人数 2吾爱币 -16 违规 +1 收起 理由
RS水果 -15 + 1 警告:CM区禁止回复『与主题无关非技术内容』,违者重罚!
PythonPan -1 请勿灌水,提高帖子质量是每位会员应尽的义务!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-8-21 01:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表