网络安全【免费下载链接】BlackboneWindows memory hacking library项目地址https://gitcode.com/gh_mirrors/bl/Blackbone点击查看免费下载导读WOW64Ext 是运行在 x64 Windows 系统 WOW64 兼容层之下的 x8632 位程序专用辅助库它解决了 32 位进程无法直接读写、枚举原生 x64 进程内存的经典难题并额外提供X64Call()这一核心机制使 x86 代码可以间接调用 x64 版 NTDLL 中的任意函数。本篇文章以 WOW64Ext 官方文档 为骨架结合 wow64ext.h 与 wow64ext.cpp 源码及 示例程序完整讲解每个导出 API 的签名、参数语义与底层实现并展示该库如何被本项目 Blackbone 的 WOW64 子系统直接吸收利用。读完本文你将掌握从 32 位进程访问 64 位目标进程的内存、模块与线程上下文的完整方法以及 x86 模式切换至 x64 模式调用原生函数的底层原理。背景32 位进程在 64 位系统上面临的内存访问难题x64 版本 Windows 通过 WOW64Windows 32-bit on Windows 64-bit兼容层运行 x86 程序。WOW64 环境中的 32 位进程在功能上有很大限制标准 Win32 APIReadProcessMemory、VirtualAllocEx、OpenProcess等的SIZE_T指针位宽被截断为 32 位无法表示 x64 目标进程中的高地址默认情况下32 位进程的地址空间被限制在 4GB 之内无法直接寻址 64 位进程位于 4GB 之上的内存区域32 位代码无法直接调用 64 位 NTDLL 中的系统服务封装函数Nt*系列因为两者使用不同的调用约定与代码段。WOW64Ext 正是为了解决这些限制而设计的它在不依赖任何驱动的情况下让 x86 程序获得对原生 x64 进程内存、模块与线程的完整操作能力。该库在 Blackbone 中承担了关键角色——Blackbone 的NativeWow64子系统Wow64Subsystem.cpp直接编译并使用了本库的wow64ext.cpp见 CMakeLists.txt 与 BlackBone.vcxproj这正是 Blackbone 支持跨越 WOW64 屏障管理 x64 进程功能的技术基础。库概览与目录结构WOW64Ext 由作者 ReWolf 开发在仓库中位于src/3rd_party/rewolf-wow64ext/核心文件如下文件作用src/wow64ext.h公共头文件导出函数声明、PEB/TEB/TIB/LDR 等结构定义、_CONTEXT64_2定义src/wow64ext.cpp全部导出函数的实现内含 x86 内联汇编src/internal.h内部宏X64_Start()/X64_End()模式切换汇编字节码、REX_W、reg64联合体src/CMemPtr.h临时内存自动释放的 RAII 辅助WATCH宏sample/main.cpp示例程序x64 进程内存转储器 功能自测doc/wow64ext.txt完整 API 文档src/wow64ext.vcxproj32 位动态库工程配置构建工程只面向 Win32 平台wow64ext.vcxproj 仅包含Debug|Win32与Release|Win32两种配置这是因为该库的设计目标就是让 x86 进程跨越 WOW64 屏障64 位进程直接使用标准 API 即可无需此库。编译时定义WOW64EXT_EXPORTS会将导出函数标记为dllexport否则标记为dllimport见 wow64ext.h。核心机制X64Call() 与 x86/x64 模式切换函数签名与参数约定DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...);这是整个库的引擎。官方文档对其语义的定义如下func要调用的 x64 函数地址通常由GetProcAddress64()取得argC传给func的参数个数...func的其余参数所有参数都必须显式转换为DWORD64。返回值是被调用 x64 函数在RAX中的返回值以DWORD64形式返回。底层原理x86 内联汇编 远程段切换从实现上看wow64ext.cppX64Call的代码被编译为 x86 内联汇编但在运行时通过修改 CS代码段寄存器以 x64 模式执行这些字节码。关键步骤包括切换 FS 段先将 FS 段保存随后将 FS 写入 x64 选择子0x2B以正确处理 64 位环境的 FS 基址TEB64 定位依赖于此栈对齐将esp对齐到0x10边界——源码注释明确指出未对齐的栈可能导致某些 syscall 返回错误且 SSE 指令要求 16 字节对齐通过X64_Start()宏切换到 x64 代码段宏展开后是一段精心构造的字节码push cs; call $5; add dword [esp], 5; retf通过retf远返回切换 CS 到 x64 选择子0x33见 internal.h填充寄存器参数按 x64 调用约定把前 4 个参数放入rcx、rdx、r8、r9其余参数逆序压栈注意其中REX_W前缀的作用——32 位汇编器会省略这些字节但 CPU 在 x64 模式下需要它们把指令解析为 64 位操作调用目标函数并清理栈调用完毕后按参数个数恢复栈retf返回 32 位模式X64_End()恢复ss、esp与 FS 段。为了在 32 位汇编中安全地操作 64 位值internal.h 定义了reg64联合体用两个DWORD模拟一个DWORD64注释说明直接使用DWORD64会产生错误的pop word ptr[]并破坏栈。配套辅助函数DWORD64 __cdecl getNTDLL64();返回 x64 版 ntdll.dll 的基址内部缓存X64Call与内存 API 的延迟解析都依赖它。GetModuleHandle64(Lntdll.dll)是它的实现基础见 wow64ext.cpp。此外还有VOID __cdecl SetLastErrorFromX64Call(DWORD64 status);X64Call直接返回 NTSTATUS而内存类 API 需要遵循 Win32 惯例设置GetLastError()。该函数通过 x86 版RtlNtStatusToDosError与RtlSetLastWin32Error把 NTSTATUS 转成对应的 Win32 错误码见 wow64ext.cpp。模块枚举与函数解析GetModuleHandle64 与 GetProcAddress64GetModuleHandle64DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName);行为类似 x86 版GetModuleHandle但检索的是已加载 x64 库的模块链表。官方文档特别指出通常 WOW64 层下的 x86 进程只加载 4 个 x64 库——ntdll.dll、wow64.dll、wow64cpu.dll、wow64win.dll。参数lpModuleName为宽字符串模块名。其实现wow64ext.cpp展示了 WOW64Ext 结构定义的典型用法通过getTEB64()拿到当前线程的 TEB64——在 WOW64 进程中R12寄存器恒指向 TEB64因此实现只是把R12压栈再弹出从TEB64.ProcessEnvironmentBlock得到 PEB64从PEB64.Ldr得到PEB_LDR_DATA64沿InLoadOrderModuleList链表遍历LDR_DATA_TABLE_ENTRY64逐个比较BaseDllName与目标模块名命中则返回DllBase。GetProcAddress64DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, const char* funcName);行为类似 x86 版GetProcAddress内部调用x64 版LdrGetProcedureAddress()。参数hModule为 x64 模块基址funcName为函数名ANSI 字符串。解析LdrGetProcedureAddress地址的过程wow64ext.cpp体现了对 x64 内存的基础读写能力定位 ntdll64 的 PE 头 → 读取导出目录 → 用getMem64/cmpMem64将导出名称表、序号表、函数地址表批量复制到本地内存 → 线性匹配LdrGetProcedureAddress名称 → 算出其 RVA 对应的绝对地址。之后通过X64Call(_LdrGetProcedureAddress, 4, hModule, fName, 0, funcRet)完成真正的函数地址解析见 wow64ext.cpp。内存操作 API在 x64 目标进程上执行虚拟内存管理以下 6 个 API 的参数与行为都与 x86 对应版 Win32 函数同名同义区别在于地址一律使用DWORD64宽指针且内部通过X64Call调用 x64 NTDLL 中的Nt*系统服务。VirtualQueryEx64SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);hProcess进程句柄由标准 x86 版OpenProcess()获取lpAddress待查询区域的基址lpBuffer指向MEMORY_BASIC_INFORMATION64标准 SDK 头中已定义的缓冲区dwLength缓冲区大小。内部经X64Call(NtQueryVirtualMemory, 6, ...)调用 x64 版NtQueryVirtualMemory失败时通过SetLastErrorFromX64Call设置 Win32 错误码成功则返回ReturnLength见 wow64ext.cpp。VirtualAllocEx64DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);lpAddress期望的分配起始地址可传 0 让系统选择dwSize区域大小flAllocationType分配类型MEM_COMMIT、MEM_RESERVE等flProtect内存保护属性PAGE_READWRITE等。底层调用NtAllocateVirtualMemory成功时返回实际分配的地址注意NtAllocateVirtualMemory会通过指针参数回写实际地址因此传入的是tmpAddr失败返回FALSE并设置错误码见 wow64ext.cpp。VirtualFreeEx64BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType);dwFreeType释放操作类型官方文档明确给出可取MEM_RELEASE、MEM_DECOMMIT。底层调用NtFreeVirtualMemory见 wow64ext.cpp。VirtualProtectEx64BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);flNewProtect新的内存保护属性lpflOldProtect接收旧保护值的指针。底层调用NtProtectVirtualMemory见 wow64ext.cpp。ReadProcessMemory64 与 WriteProcessMemory64BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);lpBaseAddress目标内存基址64 位宽lpBuffer读/写数据的本地缓冲区nSize读/写字节数lpNumberOfBytesRead/lpNumberOfBytesWritten实际读/写字节数输出指针。两者底层分别调用 x64 版NtReadVirtualMemory与NtWriteVirtualMemory见 wow64ext.cpp。线程上下文 APIGetThreadContext64 与 SetThreadContext64BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext); BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext);hThread目标线程句柄文档中写作进程句柄为笔误实现与 Win32 语义均为线程句柄lpContext指向_CONTEXT64结构的指针GetThreadContext64依据ContextFlags字段填充结构SetThreadContext64仅写入ContextFlags指定的字段。底层分别调用 x64 版NtGetContextThread/NtSetContextThread见 wow64ext.cpp。由于 32 位 SDK 不包含 x64 上下文结构库在 wow64ext.h 中自定义了完整的_CONTEXT64_2包含 6 个参数 home 区、ContextFlags、各段寄存器、调试寄存器Dr0-Dr7、通用寄存器Rax-R15、Rip、_XSAVE_FORMAT64浮点保存区以及Xmm0-Xmm15、AVXVectorRegister[26]等。文件同时定义了一组与 WinNT.h 对应的ContextFlags常量#define CONTEXT64_CONTROL (CONTEXT_AMD64 | 0x1L) #define CONTEXT64_INTEGER (CONTEXT_AMD64 | 0x2L) #define CONTEXT64_SEGMENTS (CONTEXT_AMD64 | 0x4L) #define CONTEXT64_FLOATING_POINT (CONTEXT_AMD64 | 0x8L) #define CONTEXT64_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L) #define CONTEXT64_FULL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_FLOATING_POINT) #define CONTEXT64_ALL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_SEGMENTS | \ CONTEXT64_FLOATING_POINT | CONTEXT64_DEBUG_REGISTERS) #define CONTEXT64_XSTATE (CONTEXT_AMD64 | 0x20L)见 wow64ext.h。附赠结构定义模板化的 PEB / TEB / TIB / LDR 结构官方文档提到wow64ext.h还包含一批可能对访问 PEB、TEB、TIB 等有用的结构定义。它们全部是模板化的——以指针位宽T为模板参数DWORD得到 32 位版、DWORD64得到 64 位版模板实例化别名说明_LIST_ENTRY_TT—双向链表节点Flink/Blink_UNICODE_STRING_TT—宽字符串Length/MaximumLength/Buffer_NT_TIB_TT—线程信息块 TIB 前 7 个字段_CLIENT_ID_TT—UniqueProcess/UniqueThread_TEB_T_TTEB32/TEB64线程环境块注释说明其余部分暂未定义因为暂不需要_LDR_DATA_TABLE_ENTRY_TTLDR_DATA_TABLE_ENTRY32/LDR_DATA_TABLE_ENTRY64加载器链表条目_PEB_LDR_DATA_TTPEB_LDR_DATA32/PEB_LDR_DATA64PEB 中的加载器数据_PEB_TT,NGF,APEB32/PEB64进程环境块含BeingDebugged、NtGlobalFlag、GdiHandleBuffer等常用字段定义位于 wow64ext.h注意文件顶部使用了#pragma pack(1)单字节对齐以保证与真实内核结构布局一致。PEB32/PEB64的模板参数A表示GdiHandleBuffer数组大小32 位为 34、64 位为 30NGF用于适配NtGlobalFlag字段类型差异。实战示例官方内存转储器解读示例程序位于 sample/main.cpp它是 WOW64Ext 各 API 的综合演示运行方式为sample.exe hex_process_ID // 十六进制格式的进程 ID程序依次演示了以下能力解析 x64 模块导出GetProcAddress64(GetModuleHandle64(Lwow64cpu.dll), TurboDispatchJumpAddressStart)直接取得 WOW64 CPU 调度函数的地址枚举并转储 x64 进程内存以VirtualQueryEx64从地址 0 开始逐区域扫描跳过PAGE_NOACCESS/PAGE_GUARD区域对可读区域用ReadProcessMemory64读取并以进程ID_基址_保护属性.bin命名写入文件——这正是官方文档所说的简单内存转储器调用任意 x64 函数取得RtlComputeCrc32后执行X64Call(rtlcrc32, 3, (DWORD64)0, (DWORD64)ReWolf, (DWORD64)6)计算字符串 CRC32注意所有参数显式转为DWORD64完整的内存操作闭环AllocTest()展示了分配 → 查询 → 改保护 → 写入 → 读出比对 → 释放的完整流程其中VirtualAllocEx64(hProcess, 0x70000020000, 0x2000, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)在 4GB 以上地址分配内存之后WriteProcessMemory64/ReadProcessMemory64配合memcmp校验读写一致性最后VirtualFreeEx64(..., 0, MEM_RELEASE)释放并再查询确认状态该测试还对当前进程执行了一次验证在 WOW64 内部跨越 4GB 边界分配内存的能力读写线程上下文ctx.ContextFlags CONTEXT64_ALL; GetThreadContext64(GetCurrentThread(), ctx)后打印rsp、rip、r8、r9、r12。注释中保留了被注释掉的危险代码——把ctx.Rip 0后SetThreadContext64会直接崩溃进程从反面印证了上下文写入确实生效。在 Blackbone 中的集成NativeWow64 子系统Blackbone 将该库作为 WOW64 子系统的底层实现直接编译进项目BlackBone.vcxproj 将wow64ext.cpp编入BlackBone.vcxproj.filters 将其归入 Subsystem 分组CMake 构建同样包含该源文件见 CMakeLists.txt。集成点是 Wow64Subsystem.cpp其中NativeWow64类把 WOW64Ext 的底层原语封装成 Blackbone 风格的NTSTATUS接口VirtualAllocExT/VirtualFreeExT/VirtualQueryExT/VirtualProtectExT与 WOW64Ext 的内存 API 一一对应直接使用GetProcAddress64(getNTDLL64(), Nt*)配合X64Call实现见 Wow64Subsystem.cppReadProcessMemoryT/WriteProcessMemoryT对 4GB 以下的低地址走标准ReadProcessMemory/WriteProcessMemory快速路径目标本身也是 WOW64 进程时高地址则通过 Blackbone 动态导入的NtWow64ReadVirtualMemory64/NtWow64WriteVirtualMemory64处理见 Wow64Subsystem.cppGetThreadContextT/SetThreadContextT通过X64Call调用NtGetContextThread/NtSetContextThread读写 x64 上下文同时保留了对_CONTEXT32的重载见 Wow64Subsystem.cppgetPEB/getTEB借助NtWow64QueryInformationProcess64、NtWow64ReadVirtualMemory64读取目标的_PEB64/_TEB64其结构直接取自 WOW64Ext 的模板化定义见 Wow64Subsystem.cppCreateRemoteThreadT、QueueApcT、SetProcessInfoT同样通过X64Call调用NtCreateThreadEx、NtQueueApcThread、NtSetInformationProcess等 x64 函数见 Wow64Subsystem.cpp。由此可以推断WOW64Ext 提供的X64CallGetProcAddress64 64 位结构定义三件套是 Blackbone 实现Manage process through WOW64 barrier见 README.md这一核心特性的直接依赖。32 位 Blackbone 进程正是凭借这套机制才能对原生 x64 目标进程完成注入、Hook、远程调用等整套操作。集成到自有项目时的注意事项使用前提本库仅适用于 x86 程序且宿主系统必须是 x64 Windows。X64Call与GetModuleHandle64在非 WOW64 环境下直接返回 0见 wow64ext.cpp参数位宽所有传给X64Call的参数必须以(DWORD64)显式转换指针参数传递(DWORD64)var这是最常见的误用点栈对齐X64Call内部已处理 16 字节对齐与栈平衡调用方无需干预但被调用的 x64 函数必须遵循标准 x64 调用约定错误处理内存类 API 遵循 Win32 惯例——失败返回 0/FALSE并设置线程本地错误码可用GetLastError()获取结构布局使用PEB64、TEB64、LDR_DATA_TABLE_ENTRY64等结构时注意它们按#pragma pack(1)单字节对齐定义字段布局需与实际目标系统版本核对授权该第三方库以 LGPL-3.0 授权见 lgpl-3.0.txt作为 Blackbone 的 3rd_party 依赖随项目分发。小结WOW64Ext 以极小的代码规模解决了 32 位进程与 64 位进程之间的位宽鸿沟X64Call提供模式切换能力GetModuleHandle64/GetProcAddress64打通 x64 模块与导出解析六个内存 API 覆盖查询、分配、释放、改保护、读、写全部虚拟内存操作两个上下文 API 实现 x64 线程上下文的读写模板化结构定义则让 PEB/TEB 的访问不再依赖 64 位 SDK。在本仓库 Blackbone 中它已作为NativeWow64子系统的基石被实际编译与使用是理解跨 WOW64 进程操作技术的绝佳学习样本也是一份可直接复用的 32 位/64 位混合内存操作工具箱。赞分享网络安全【免费下载链接】BlackboneWindows memory hacking library项目地址https://gitcode.com/gh_mirrors/bl/Blackbone点击查看免费下载相关推荐Blackbone WOW64子系统跨越32位与64位进程屏障的终极指南Blackbone WOW64子系统跨越32位与64位进程屏障的终极指南 Blackbone是一款强大的Windows内存操作库而其中的WOW64子系统更是网络安全inih轻量级 C 语言 INI 解析器详解及其在 mGBA 中的集成实践inih轻量级 C 语言 INI 解析器详解及其在 mGBA 中的集成实践 导读 inihINI Not Invented Here是一个用纯 C 编写的游戏开发深入解析 Go 版 XXH3 哈希库zeebo/xxh3及其在 Cloudpods 中的 UUID 生成实践深入解析 Go 版 XXH3 哈希库zeebo/xxh3及其在 Cloudpods 中的 UUID 生成实践 XXH3 是知名非加密哈希算法 xxHash后端云原生运维虚拟化人工智能AI 应用上一篇如何快速提取微信聊天记录3步实现数据永久保存的完整指南下一篇伊斯兰星形图案二在 p5.js 中利用正弦定理精确计算 Hankin 长度的铺贴算法优化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?