吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1142|回复: 11
收起左侧

[UnPackMe] 用免费AI写了个简单unpackme,试一下

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

让OpenCode里的免费AI模型写的简单壳



本帖子中包含更多资源

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

x

免费评分

参与人数 1吾爱币 +1 收起 理由
wchy056 + 1 热心回复!

查看全部评分

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

killerzeno 发表于 2026-10-16 00:48
本帖最后由 killerzeno 于 2026-10-16 00:50 编辑

完整逆向:自定义运行时解密壳的模拟脱壳实录(睡觉前玩一手)

目标样本:test_packed.exe(Windows x64 GUI)
分析目标:脱壳并还原程序原始逻辑
分析方式:纯用户态静态分析 + Unicorn 引擎模拟执行,全程未运行样本、未依赖调试器
最终产物:test_packed_unpacked.exe(OEP 已还原)、一键脱壳脚本 emu_unpacker.py


0. TL;DR

  • 样本为一道 unpack-me 型练习题:壳对原程序代码节做了 RC4 加密,将原程序入口重定向到壳桩,并在运行时通过 ROR13 API hash + PEB 遍历(不使用任何导入表)完成 API 解析。
  • 壳内置多层反分析:PEB 标志检查、IsDebuggerPresent/CheckRemoteDebuggerPresent、窗口扫描(按标题/类名枚举分析工具)、注册表反调试键(NtGlobalFlag/GlobalFlag)、驱动与文件存在性探测、时间反调试等。检测命中后不报错、无窗口、静默退出(退出码 0x5100),这也是"双击无反应"假象的来源。
  • 本文使用 Unicorn 引擎伪造最小进程环境(TEB/PEB/LDR + 假 kernel32 导出表),让壳自行完成全部解密,在控制权首次移交原代码时捕获 OEP(0x14000141C,即 mainCRTStartup),随后按运行时镜像重建 PE。
  • 脱壳结论:原程序是一个极简 Win32 窗口程序——注册窗口类 winhello,在 WM_CREATE 中无条件创建文本为 hello world! 的 STATIC 子窗口并进入消息循环。全代码不存在任何密码校验逻辑(无输入控件、无字符串比较、无 ASCII 常量比对)。壳层那些看似"密码校验"的检查,全部服务于反分析。

1. 样本信息

属性 值
文件名 test_packed.exe
大小 463,360 字节 (0x71200)
MD5 59d94d802aba58fb441235b21b65b8ed
SHA256 3f1e906ebd92e82310939558700dabcfb2c8a5d566e419787fe19f9ff370df86
架构 x86-64 (PE32+),GUI 子系统
ImageBase 0x140000000(ASLR 下实际基址相同)
TimeDateStamp 0x6ACFDE92(2026-10-14 19:57:06 UTC,即打包时间)
原始入口 RVA 0x455E0(位于载荷节 .WJLIEU 内)

1.1 节表与熵

节名 VA VSize Raw 熵 属性 备注
.KRrk0s 0x1000 0x5088 0x5200 7.99 R-X 原程序代码,RC4 加密
.vD6rgs 0x7000 0x287C 0x2A00 4.47 RW- 可读数据
.aWWS4n 0xA000 0x2140 0x1000 2.11 RW- 字符串/明文数据
.fH1JqT 0xD000 0x0528 0x0600 3.83 R-- 数据
.rZT03B 0xE000 0x01BE 0x0200 3.99 R-- RVA 数组表
.WJLIEU 0xF000 0x6787A 0x67A00 7.75 RWX 壳载荷:加密 blob + 壳桩,EP 在此

静态特征非常典型:随机 6 字符节名、双高熵可执行节、EP 落在 RWX 载荷节、节内存在 VMPR 字节片段——而导入表却是完整的原程序导入(USER32/GDI32/CRT),字符串(hello world!、winhello 等)亦未加密。这种"导入表完整 + 代码高熵"的组合说明:壳不做导入隐藏,只做代码加密与执行流重定向。


2. 动态行为观察

在分析机上双击运行,现象为进程存在但无任何窗口,数秒后自行退出,退出码 0x5100。对运行中进程做只读内存扫描(ReadProcessMemory,无调试器参与)得到两个关键事实:

  1. .KRrk0s 在内存中依旧保持熵 7.96——壳采用"解密-执行"甚至"按需解密"策略,静止状态下代码不落地;
  2. 载荷节 .WJLIEU 内除 EP 附近一小段明文壳桩外,其余仍为高熵密文。

结合退出码 0x5100 恰为壳配置表中的常量(见 §4.3),可以判定:静默退出是壳反分析命中的主动行为,而非程序崩溃。这也解释了为什么传统"跑起来再 dump"的路线走不通——必须让壳在受控环境中把反分析全部"骗过",才会走完解密流程。


3. 壳桩逆向(EP 0x455E0)

3.1 主流程

壳桩本体只有约 1.4KB 明文代码,IDA 反编译后主流程清晰:

void start(...) {
    save_args_to_globals(...);
    if (!initialized) {
        sub_4589D();                                  // 解密器 #2:配置表
        sub_4569D();                                  // 解密器 #1:载荷 blob A
        sub_45A9D();                                  // 解密器 #3:载荷 blob B
        if (qword_47340 && qword_47340 < 0x400000)
            call(0x1400135E0 + qword_47340);          // 二级引擎入口(blob B 反分析)
        call(0x1400135E0);                            // RC4 解密 .KRrk0s
        initialized = 1;
    }
    call(0x140013000);                                // 壳 runtime 初始化
    call(0x140012780);                                // 移交原程序
}

3.2 三个 stage-1 解密器

三个解密器均为纯算术混淆(MBA 风格垃圾指令填充寄存器运算,不影响语义),全部以 8 字节为单位、自高地址向低地址原地解密:

例程 目标范围(RVA) 大小 轮数 核心变换(q 为 64 位字)
sub_4569D 0xF100 – 0x455E0(blob A) 222,688 B 0x6CBC (27836) q = ((q − 0x5339EEE4) ⊕ 0xFFFFFFFF9BB60C44) + 0x26EBBE33
sub_4589D 0x46998 – 0x46AE0(配置表) 320 B 0x28 (40) q ⊕= 0x7DE94A53
sub_45A9D 0x47660 – 0x76768(blob B) 192,968 B 0x5E39 (24121) q = ((q ⊕ 0xFFFFFFFFD62745A5) + 0x782276EC − 0x28E40D3) ⊕ 0x27BE95A2

此外 blob B 引擎在执行初期还会解密第四块区域(gap 区,RVA 0x46AE0–0x47660,2,944 B / 368 qword),该区在解密后包含API 指针槽位表与二级引擎跳板代码(0x475A0)。

解密后的 blob A 头部即为合法 x64 代码,第一眼可辨认出 RC4 KSA 的标志性结构(S[i]=i 填充循环 + div 取模的密钥混合循环)。

3.3 配置表(RVA 0x46998,320 字节)

解密后的配置表以 64 位字段组织,关键字段:

偏移 值 含义
+0x10 0x140076770 blob B 尾部 VA
+0x18 0x1400015CA 壳引用的内部地址
+0x20 0x5100 反分析命中后的静默退出码
+0x28 0x140000000 ImageBase
+0x30 0x469A0 配置表自引用
+0x38 0x7000 加密代码节大小
+0x48 0x199FA8158B863AFE 密钥材料
+0x50 0x100054DED158 RC4 密钥(8 字节小端:58 D1 ED 54 00 10 00 00)
+0x58 0xF000 载荷节 VA
+0x60 0x379A0 blob A 长度
+0x78 0x71200 原始文件大小(完整性自校验用)
+0x80 起 24×8 字节 高熵密钥/参数材料

3.4 RC4 解密原代码节

.KRrk0s(原程序代码,20,616 字节)由 blob A 内的 RC4 例程解密,流程被 VirtualProtect(addr, size, PAGE_EXECUTE_READWRITE, &old) 包裹:

1. key = *(qword*)(0x1400469E8)          ; 配置表 +0x50
2. RC4-KSA(S, key, 8)
3. VirtualProtect(0x140001000, 0x5088, RWX, &old)
4. RC4-PRGA ⊕ 全节(逐字节,共 20,616 次写)
5. VirtualProtect 恢复原属性

解密完成后整节熵由 7.99 降至 6.15,即为标准 MSVC 静态链接 x64 代码。


4. API 解析机制:无导入 ROR13

壳桩自身不调用任何导入函数,而是通过 PEB 定位模块、按 ROR13 名称哈希扫描导出表:

FARPROC resolve_by_hash(DWORD hash) {
    PEB    = __readgsqword(0x60);
    Ldr    = PEB->Ldr;
    for (ent = Ldr->InLoadOrderModuleList.Flink; ...; ent = ent->Flink) {
        base = ent->DllBase;
        if (fn = scan_export_ror13(base, hash))   // ror32(h,13)+c 逐字符
            return fn;
    }
    return NULL;
}

导出表扫描器(RVA 0xFE94)细节相当完整:校验 DOS/NT/PE32+ 魔数、NT+0x88 取导出目录、遍历 NumberOfNames、命中后还会调用 forwarded export 检查(按节表验证函数 RVA 落点、扫描转发字符串 xxx.yyy 的点号)。

整个壳共请求 54 个唯一 hash,覆盖三类用途:

  • 反分析:IsDebuggerPresent、CheckRemoteDebuggerPresent、OutputDebugStringA、FindWindowA/FindWindowW、GetForegroundWindow、GetWindowTextA/W、GetClassNameA、EnumWindows、PostMessageW/SendMessageW;
  • 执行环境:VirtualProtect/VirtualQuery(改代码节页属性)、LoadLibraryA、GetModuleHandleA、CreateFileA/W + ReadFile + GetFileSize + CloseHandle(文件探测)、GetSystemDirectoryA、GetModuleFileNameA;
  • 完整体的运行时支撑:ExitProcess、GetCurrentThread、GetTickCount/QueryPerformanceCounter(时间反调试)、MultiByteToWideChar 等。

5. 反分析体系

blob B(192KB)是壳的反分析引擎,解密后可见大量环境探测字符串与逻辑:

类别 手段
进程级 IsDebuggerPresent、CheckRemoteDebuggerPresent、PEB NtGlobalFlag/GlobalFlag
窗口级 EnumWindows + GetWindowTextA/W + GetClassNameA 按标题/类名扫描分析工具;FindWindowA/FindWindowW、GetForegroundWindow
注册表 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\... 下 AppInit_DLLs、NtGlobalFlag、GlobalFlag(IFEO 反调试)
文件/驱动 C:\Windows\System32\drivers\ac.sys 存在性探测、\\.\PhysicalDrive0、%SystemRoot%\system32\ntdll.dll 校验
时间 GetTickCount、QueryPerformanceCounter 差值检测单步
行为 引擎内含 SetThreadContext 等上下文操作;错误统一走 err=0x%08X 格式化后静默退出

所有检查不弹窗、不提示:命中即以配置表约定的退出码(0x5100)静默结束进程。这意味着传统"先运行再附加"的动态分析路线会全军覆没,也让静态分析者误以为存在某种"密码校验失败"路径——实际上壳内不存在任何面向用户的密码输入与比较逻辑。


6. Unicorn 模拟脱壳

6.1 思路

既然壳的所有解密都是纯计算(三个解密器 + RC4 无任何系统调用),而 API 解析依赖 PEB 遍历,最干净的方案是用 Unicorn 伪造一个最小进程环境,让壳自己把一切解出来:

  1. 按原 ImageBase(0x140000000)映射全部节;
  2. 伪造 TEB → PEB → Ldr → 单模块链(kernel32.dll),GS 段基址指向 TEB;
  3. 手工构造一个结构正确的假 kernel32:PE32+ 头、节表、导出目录(约 290 个常见导出),导出函数体为 mov rax, 槽位; jmp rax,槽位处放一条 ret;
  4. 样本自身 IAT 槽位同样指向 API 槽位区;
  5. 在 API 槽位地址挂 UC_HOOK_CODE 实现 API 语义(VirtualProtect 恒成功、HeapCreate 返回非空句柄、IsDebuggerPresent 恒 0、窗口枚举类恒"未找到"等);
  6. 挂 UC_HOOK_MEM_WRITE 监控加密节的写入量与熵变化;
  7. OEP 捕获:壳 runtime 全部位于载荷节内,一旦指令指针首次落入解密后的 .KRrk0s,即为控制权移交点——本样本首次移交地址为 0x140002CD8(__security_init_cookie,由壳 runtime 调用),据此停止模拟并 dump。

6.2 实现要点与踩坑

  • 假 kernel32 的 PE 结构必须经得起壳的解析器:壳的 forwarded-export 检查会遍历节表、用 NT+0x88 取导出目录、严格校验 SizeOfOptionalHeader(NT+0x14)。任何字段错位(例如把 SizeOfOptionalHeader 写到 NT+0x0C)都会让全部 hash 解析静默失败,表现为"解析器调用正常但结果全为 NULL"。
  • 导出目录字段顺序:NumberOfFunctions 与 AddressOfFunctions 错一位会让扫描器把函数地址表当序号表用,症状同样是"hash 匹配成功但返回 NULL"。
  • null-call 处理:未解析的 API 槽为 NULL,壳中存在 call rax(rax=0) 路径。在 Unicorn 里手动改 RIP 续跑会触发 UC_ERR_MAP,正确做法是直接映射零页并放置 xor eax,eax; ret,让空调用自然"返回 0"。
  • 堆初始化语义:CRT 的 HeapCreate 若返回 0,mainCRTStartup 会走 exit(0xff) 分支——模拟日志中令人困惑的 ExitProcess(0xff) 由此而来,属环境问题而非样本逻辑。
  • 数据节保真:重建时仅替换代码类节,数据节保留磁盘原版,IAT 维持未解析状态交给真实 loader 处理。

6.3 一键化

上述流程已封装为 emu_unpacker.py,自动完成:加密节识别(可执行 + 初始熵 > 7 且不含 EP)→ 环境伪造 → 模拟执行 → 解密监控(本样本 20,616 字节写入,熵 7.99→6.15)→ OEP 捕获 → 节回填 → 假指针槽回滚 → EP 重定向 → 校验和修正。

python emu_unpacker.py test_packed.exe -o test_packed_unpacked.exe [--oep 0x14000141C]

7. OEP 与文件重建

  • 真 OEP:0x14000141C(mainCRTStartup)。壳将 EP 改写为自身桩(0x455E0),原入口由壳 runtime 在完成解密与运行时初始化后移交。
  • 首次进入解密节的地址为 0x140002CD8(__security_init_cookie,壳 runtime 在移交前调用),脚本同时支持 --oep 手动指定最终入口。
  • 重建策略:
    • .KRrk0s 回填为解密后数据(原样,不做任何"清洗"——按窗口清洗伪指针会破坏指令流,是常见的重建事故);
    • .WJLIEU 回填为运行时镜像,并仅对壳在模拟期间写入的 API 假指针槽做定点回零(通过写钩子精确记录,避免误伤代码);
    • 数据节(.vD6rgs/.aWWS4n/.fH1JqT/.rZT03B)保留磁盘原版,IAT 交由真实 loader 重建;
    • 入口点写回 OEP,重算 CheckSum。

重建后验证:入口处为标准 mainCRTStartup(GetStartupInfoW → PE 头自检 → CRT 初始化链),.KRrk0s 内 WndProc(RVA 0x1000)、WinMain(RVA 0x1130)反汇编与动态行为完全吻合。


8. 解包结论:程序的"真实面目"

脱壳后的程序是一个教科书级的极简 Win32 窗口程序(MSVC 静态 CRT):

// WinMain (0x140001130)
RegisterClassExA(&(WNDCLASSEXA){
    .lpfnWndProc = WndProc, .lpszClassName = "winhello", ... });
CreateWindowExA(0, "winhello", "winhello", WS_OVERLAPPEDWINDOW, 居中, 0x140x0x78, ...);
ShowWindow / UpdateWindow;
while (GetMessageA(...)) { TranslateMessage; DispatchMessageA; }

// WndProc (0x140001000)
case WM_CREATE:                                   // 0x1400010C9
    CreateWindowExA(0, "STATIC", "hello world!",
                    WS_CHILD|WS_VISIBLE|SS_CENTER,
                    0, 0, 0, 0, hwnd, (HMENU)100, hInst, 0);
case WM_SIZE:                                     // 0x14000106B
    MoveWindow(GetDlgItem(hwnd, 100), ...);       // 居中重排
case WM_DESTROY:
    PostQuitMessage(0);
case WM_CTLCOLORSTATIC:
    SetBkColor(...); return GetSysColorBrush(...);

对解密后全部 20,616 字节代码做了系统排查:无输入控件(无 EDIT)、无 GetCommandLineA 参与的业务逻辑(仅 CRT 标准调用)、无任何字符串/常量比较分支(ASCII 立即数扫描零命中)。窗口与其中的 hello world! 是无条件创建的。

因此,本题的"密码"并不存在于程序逻辑中——壳层的全部"校验"(哈希解析、环境探测、窗口扫描、注册表检查、时间检测)共同构成一道反分析屏障:在含分析工具的环境里,程序连窗口都来不及创建就静默退出(0x5100),制造出"有密码校验"的错觉;而在干净环境中,它只是坦然地弹出一个写着 hello world! 的窗口。解开这道题的钥匙从来不是某个字符串,而是把壳本身拆开。


附录 A:ROR13 请求清单(54 项)

0x73E2D87E ExitProcess                0xA36DC676 IsDebuggerPresent
0x43AF7D80 CheckRemoteDebuggerPresent 0x470D22BC OutputDebugStringA
0x75DA1966 GetLastError               0xF791FB23 GetTickCount
0xEA7AF15B QueryPerformanceCounter    0x249466D5 (未命名,自定义 hash)
0xE8CDCFE4 GetCurrentThread           0x2D3FCD70 (未命名)
0xEC0E4E8E LoadLibraryA               0x6228050D (未命名)
0x673F23AF (未命名)                   0x3B1E50C8 FindWindowA
0x6215F501 GetForegroundWindow        0xA1CCB963 GetWindowTextA
0xB3C52468 GetClassNameA              0x0021E71A EnumWindows
0x51E20CE0 (未命名)                   0x84454957 (未命名)
0xB9A87739 (未命名)                   0x7AC67C03 (未命名)
0x8FDE2C7E TranslateMessage           0x690A1717 (未命名)
0x94305BE0 DestroyWindow              0xC95D4F83 ShowWindow
0xC2BFD83F UpdateWindow               0x7B66EC0D PostMessageW
0x4BE0469D PostQuitMessage            0xEB6CC40A SendMessageW
0xCBA6C0E5 (未命名)                   0x16F8BA2A (未命名)
0xD53A404E (未命名)                   0xA1CCB979 GetWindowTextW
0xEF4AC4E4 MultiByteToWideChar        0xD3324904 GetModuleHandleA
0xB10FD839 (未命名)                   0xE4E1CAD6 (未命名)
0xE3D6909C (未命名)                   0x00D83695 (未命名)
0xFEEDF510 (未命名)                   0xE935E393 (未命名)
0xDCD44C5F (未命名)                   0x159B3EA0 (未命名)
0xABF6E97A (未命名)                   0x45B06D76 GetModuleFileNameA
0x7C0017A5 CreateFileA                0x7C0017BB CreateFileW
0x10FA6516 ReadFile                   0xDF7D9BAD GetFileSize
0x0FFD97FB CloseHandle                0xB8E579C1 GetSystemDirectoryA
0x7946C61B VirtualProtect             0xA3C8C8AA VirtualQuery

("未命名"项为壳自定义的补充 hash,不在常见导出名集中;对应槽位在正常流程中未触发调用,不影响脱壳。)

附录 B:关键地址速查

地址 (RVA) 角色
0x455E0 壳桩 EP(明文)
0x4569D / 0x4589D / 0x45A9D stage-1 解密器 #1/#2/#3
0xF100 RC4 KSA(blob A 头部)
0xFE94 ROR13 导出表扫描器
0x1014C PEB 遍历 + hash 解析入口
0x101DC 完整性失败处理(擦除 + 退出)
0x134C0–0x135E0 RC4 解密调度(含 VirtualProtect 包裹)
0x475A0 / 0x48DA0 二级引擎入口 / blob B 反分析引擎
0x46998 配置表(320B)
0x141C 真 OEP:mainCRTStartup
0x1000 / 0x1130 WndProc / WinMain
0x10C9 WM_CREATE:创建 "hello world!" STATIC

附录 C:产物清单

文件 说明
test_packed_unpacked.exe 脱壳重建文件(MD5 556a332a4142322161d4e8e2f2e53e98,EP=0x141C)
emu_unpacker.py 一键模拟脱壳脚本(Unicorn + Capstone + Pefile)

分析环境:Windows x64;工具链:Unicorn Engine(CPU 模拟)、Capstone(反汇编)、Pefile(PE 解析)。


本帖子中包含更多资源

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

x

免费评分

参与人数 1热心值 +1 收起 理由
sw0rdman + 1 热心回复!

查看全部评分

gshccr 发表于 2026-10-15 12:22
baysery 发表于 2026-10-15 12:19
AI可以写注册,的确很方便,前几天用一个AI软件,直接把小日子的一个软件注册方式给扒出来了,顺带还帮写了个KEYGEN
bj6688 发表于 2026-10-15 08:49
AI 还真是厉害了,什么都会

免费评分

参与人数 1吾爱币 -20 违规 +1 收起 理由
bian96 -20 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

myloveer 发表于 2026-10-15 09:07
这个是何物?小白一个

免费评分

参与人数 1吾爱币 -20 违规 +1 收起 理由
bian96 -20 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

huiye 发表于 2026-10-15 09:37
试试看,正好接触

免费评分

参与人数 1吾爱币 -20 违规 +1 收起 理由
bian96 -20 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

lch74123 发表于 2026-10-15 10:21
现在AI还能编这种程序吗?还以为已经被禁了,看网上有视频说AI不能编写黑客类测试软件。
 楼主| sw0rdman 发表于 2026-10-15 12:17
lch74123 发表于 2026-10-15 10:21
现在AI还能编这种程序吗?还以为已经被禁了,看网上有视频说AI不能编写黑客类测试软件。

说说而已 现在s服群里都是用AI逆向客户端直接写服务端 最近一年好多老网游都复活了
SokkBudd 发表于 2026-10-15 13:18
一直以为现在AI没法做这种了
天空の星 发表于 2026-10-15 16:48
gshccr 发表于 2026-10-15 12:22
密码:ZWPWD01 对吗

没有密码才对,脱壳后运行如图

免费评分

参与人数 2吾爱币 +2 热心值 +1 收起 理由
gshccr + 1 + 1 我很赞同!
sw0rdman + 1 谢谢@Thanks!

查看全部评分

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

本版积分规则

返回列表

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

GMT+8, 2026-10-16 13:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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