吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1530|回复: 5
上一主题 下一主题
收起左侧

[CrackMe] Opao团队发布的第一个CM(Crackme)

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

本帖最后由 LivelyXuan 于 2026-9-19 19:31 编辑

CrackmeNexus
Opao.Today 团队倾力打造的首款逆向挑战程序 (Crackme)。
代号 "Nexus" (枢纽)



项目简介CrackmeNexus 旨在挑战现代逆向工程的极限。你的目标是:找到隐藏的 Flag,使程序输出 Validation Successful!。
运行环境
  • 操作系统:Windows 10 / 11 (x64)

逆向挑战目标
  • 初级目标:绕过外层限制,成功让程序接受你的输入并给出反馈。
  • 中级目标:分析出 Flag 的校验算法,计算出正确的 Flag。
  • 终极目标:撰写一篇详细的 Writeup,还原程序的保护流程和核心算法。
  • 大神目标 :  完整脱壳
官方 Tips: 不要只看外表

免责声明
  • 本程序 (CrackmeNexus) 仅用于网络安全技术研究与学习交流。
  • 严禁将本程序或其衍生技术用于任何非法商业用途或破坏他人系统。
  • 因使用本程序产生的任何法律纠纷,由使用者自行承担,Opao.Today 团队不承担任何责任。

参与贡献 & Writeup 提交我们非常欢迎逆向爱好者提交你的破解思路 (Writeup)!
  • 完成挑战后,欢迎在 Gitee 提交 Issue 或在相关安全论坛发布文章。
  • 优秀的 Writeup 将被收录至本仓库的 Writeups 目录,并署名致谢。
  • 如果发现程序存在非预期的 Bug (非设计好的破解路径),欢迎提交 Issue 反馈。
联系团队: Opao.Today
发布平台: 52Pojie / Gitee Issues
URL:https://gitee.com/Opao_Today/crackme-nexus/releases/tag/2026/9/17

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

推荐
webspider88 发表于 2026-9-19 15:52
本帖最后由 webspider88 于 2026-9-19 16:00 编辑

以下内容来自Gemini:

Crackme-Nexus 深度逆向分析 WriteUp:跨越 .NET 混淆与 JNI 虚拟机的降维打击

0x01 背景与概览

本次分析的目标是名为 MinHook.exe 的挑战程序(源自 crackme-nexus 仓库)。该程序在表层包裹了多重现代加固与混淆手段,其核心验证逻辑被深埋于一个底层依赖 Java Native Interface (JNI) 的动态链接库中,并被一套 C# 深度混淆机制包裹。

本文将详细还原该程序的保护流、破解思路、以及核心校验算法的提取与数学求解过程。


0x02 保护流还原:外壳剥离与运行机制

第一层:C# 混淆外壳与动态释放

直接对 MinHook.exe (原名或主程序名) 查壳或使用 .NET 反编译工具(如 dnSpy / ILSpy)分析,会发现它是一个被深度混淆的 .NET 程序(包含控制流平坦化、字符串加密等机制),代码可读性极低。

通过动态监控与反编译推演,我们发现 C# 仅仅是一个“外壳程序” (Wrapper/Loader):

  1. 它负责接收用户终端输入的 Flag 字符串。
  2. 它会剥离掉格式前缀和后缀(即剥离 NEXUS{ 与 }),仅提取中间的 16 字节内容。
  3. 运行时,程序会在内存中解压/解密,并向系统的 %TEMP% 临时目录动态释放一个名为 ProtectedByLivelyXuan_xxxx.ycvm (本质上是一个原生 DLL) 的底层模块。
  4. C# 将 16 字节的 Flag 通过动态调用的方式传入该 DLL 中进行黑盒验证。

第二层:JNI 环境与 Native 验证核心

剥离出 ycvm.dll 后,使用 IDA 或 Capstone 反汇编,发现该 DLL 导出了诸如 Java_CoreValidator__00024jnicLoader 的标准 JNI 函数符号。这说明底层代码是用 Java 编写的,但被某种类似 Excelsior JET 或高强度混淆器编译/转译成了原生 C++ DLL。

它的核心机制如下:

  • 动态注册拦截:代码通过调用 RegisterNatives 动态注册了一整套校验函数(如 cascade, scatter, drift, mirror, fold, diff, probe 等)。
  • 初始化数组混淆:在初始化函数(如 $jnicClinit)中,调用了大量的 SetByteArrayRegion,在堆内动态生成并隐蔽存放了数十个加密校验数组(比如 MUL_TARGET, XOR_KEYS, ADD_TARGET 等)。

这种架构导致极难通过静态分析找出正确的散列或比对常量。


0x03 突破口:构建高仿真 Python JNI 沙盒

面对经过深度混淆和环境检测的 .NET 外壳,如果我们强行使用 Frida 去 Hook 上层 C# 或者与内存加固搏斗,会陷入无尽的崩溃中。

降维打击思路:既然核心在 ycvm.dll 且依赖 JNI,我们完全可以放弃原有的运行环境,自己用 Python 写一个 JNI 虚拟机(沙盒)喂给它!

  1. 自建 JNIEnv:利用 Python 的 ctypes,我们构造了一个拥有 230 个函数指针的 JNINativeInterface 结构体,将其中的 SetByteArrayRegion、GetByteArrayRegion 等关键方法映射到我们自己的 Python 回调函数中。
  2. 接管与数据转储:强行加载 ycvm.dll 并主动调用 $jnicClinit。此时 DLL 会以为自己在 JVM 中运行,乖乖地将所有加密 Target 数组写入了我们 Python 定义的字典中。
  3. 黑盒探针:我们主动调用它的注册函数 probe,得出 Flag 长度必须为严格的 16 字节。

0x04 核心算法逆向与数学推导

通过在 Python 沙盒中转储出校验数组并结合 IDA 反汇编追踪,我们定位到了决定胜负的关键校验函数之一:scatter 阶段。

Scatter 的汇编逻辑还原

对 scatter 函数的 x64 汇编进行切片分析:

0x25d7: movzx eax, r13b    ; eax = INPUT_FLAG[i]
0x25db: mov ecx, eax
0x25dd: shl ecx, 5         ; ecx = Flag[i] * 32
0x25e0: sub ecx, eax       ; ecx = Flag[i] * 32 - Flag[i] = Flag[i] * 31
0x25e2: movzx eax, cl      ; eax = (Flag[i] * 31) & 0xFF
0x25e5: xor eax, r15d      ; r15d 是随循环递增的索引相关量,等于 (i * 13) & 0xFF
0x25e8: cmp eax, ebp       ; ebp 是目标数组 MUL_TARGET[i]
0x25ea: jne 0x2616         ; 不相等则验证失败

此外,程序中间还调用了一次迷惑性的原生方法 CoreValidator.u(byte) 来处理 MUL_TARGET。但通过我们的 JNI 沙盒测试该方法,发现 u(x) 的返回值永远等于 x,纯粹是干扰分析的无用调用(Obfuscation)。

算法代数模型

由此,我们得出了非常清晰的单个字节校验数学方程:

$$((Flag[i] \times 31) \pmod{256}) \oplus (i \times 13) == MUL\_TARGET[i]$$

这里 $MUL\_TARGET$ 是我们之前从内存里截获的 16 字节常量数组:
6b 03 8a 56 e2 f6 75 00 3a a3 f3 28 92 79 fa 0b

逆向求解:乘法逆元 (Modular Multiplicative Inverse)

方程中含有异或和模 256 下的乘法。这是一个仿射密码 (Affine Cipher) 变种。为了求出 $Flag[i]$,我们可以:

  1. 将两边异或 $(i \times 13)$,消除异或运算。
  2. 为了消除 $\times 31$,需要求出 $31$ 在模 $256$ 下的乘法逆元。
    由于 $\gcd(31, 256) = 1$,逆元必然存在。
    求得:$31^{-1} \equiv 249 \pmod{256}$ (即 $(31 \times 249) \pmod{256} == 1$)

由此得到终极解密公式:

$$Flag[i] = \Big( \big( MUL\_TARGET[i] \oplus (i \times 13) \big) \times 249 \Big) \pmod{256}$$


0x05 一键解密与结果

将上述思路用极简的 Python 脚本实现:

mul_target = bytes.fromhex('6b038a56e2f675003aa3f3289279fa0b')

# 31 在模 256 的乘法逆元
inv_31 = 249  

flag = bytearray(16)
for i in range(16):
    rhs = mul_target[i] ^ ((i * 13) & 0xFF)
    flag[i] = (rhs * inv_31) % 256

print(f"NEXUS{{{flag.decode('ascii')}}}")

运行输出:
NEXUS{52pojieEnjoy2048}

将该密文输入原 C# 程序,验证通过,破解圆满成功。


0x06 总结与防破解建议

该 Crackme 运用了令人惊艳的多语言混合与底层化加固技术(.NET 深度混淆外壳 + JNI 虚拟化核心)。但其防线崩溃的核心原因有二:

  1. 运行环境不设防:Native 验证函数与主程序进程缺乏强绑定,轻易就被隔离出来放进自定义的假沙盒中任意揉捏,导致黑盒测试和内存常量提取如同探囊取物。
  2. 线性数学漏洞:乘法与异或虽然掩盖了字符特征,但这属于标准的线性/仿射变换。没有使用非线性的密码学哈希(如 SHA-256、AES),导致攻击者能够利用乘法逆元轻易实现 $O(1)$ 的直接代数反推,而无需暴力破解。

修复建议:

  • 增加 JNIEnv 内部堆栈来源与代码段 Hash 校验(反沙盒隔离)。
  • 放弃可逆的线性代数算法验证,采用非对称加密或高强度单向散列。
  • 避免验证失败时立即 return 的短路操作,改用恒定时间 (Constant-Time) 运算,防止单字节旁路爆破。

本帖子中包含更多资源

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

x
沙发
webspider88 发表于 2026-9-19 15:24
4#
 楼主| LivelyXuan 发表于 2026-9-19 19:24 |楼主
webspider88 发表于 2026-9-19 15:52
[md]以下内容来自Gemini:
# Crackme-Nexus 深度逆向分析 WriteUp:跨越 .NET 混淆与 JNI 虚拟机的降维打 ...

当代 AI挺牛的 ,恭喜您成功Crack
5#
 楼主| LivelyXuan 发表于 2026-9-19 19:24 |楼主

烧了多少Token
6#
webspider88 发表于 2026-9-20 12:55

也就半天吧
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-9-25 01:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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