ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

深入解析 MemorySharp 的 MarshalType:托管类型与字节数组高效转换原理

深入解析 MemorySharp 的 MarshalType:托管类型与字节数组高效转换原理 深入解析 MemorySharp 的 MarshalType托管类型与字节数组高效转换原理【免费下载链接】MemorySharpA C# based memory editing library targeting Windows applications, offering various functions to extract and inject data and codes into remote processes to allow interoperability.项目地址: https://gitcode.com/gh_mirrors/me/MemorySharpMemorySharp 是一款基于 C# 的 Windows 内存编辑库它的核心能力是在远程进程中读写数据与注入代码。而支撑这一切的数据搬运枢纽正是内部组件MarshalType。本文将从源码出发深入解析 MemorySharp 的 MarshalType 如何实现托管类型与字节数组之间的高效双向转换并揭示它背后两条截然不同的转换路径与性能优化思路帮助你真正读懂这个 C# 内存编辑库的底层读写原理。MemorySharp 是什么先认识这款 C# 内存编辑库简单来说MemorySharp 提供了一套面向对象的 API让开发者可以像操作本地对象一样读取和写入其他 Windows 进程的内存。它的典型应用场景包括游戏外挂开发、逆向工程辅助工具、自动化测试钩子等。在使用过程中你会发现一个有趣的矛盾内存读写的底层接口如 Windows APIReadProcessMemory/WriteProcessMemory只认字节数组而业务代码里却是int、float、结构体这样的托管类型。谁来负责这两者之间的翻译答案就是MarshalTypeT。MarshalType 在 MemorySharp 内存读写原理中的角色打开src/MemorySharp/MemorySharp.cs你会发现ReadT和WriteT这两个最常用的 API内部全部委托给了 MarshalType读取时先ReadBytes拿到原始字节再调用MarshalTypeT.ByteArrayToObject还原成托管对象写入时先调用MarshalTypeT.ObjectToByteArray把托管对象变成字节再调用底层WriteBytes写进远程进程。也就是说你每一次sharp.Readint()或sharp.Write()背后都在走 MarshalType 的转换管线。它同时服务于MarshalValue值封送、AssemblyTransaction汇编执行结果读取和RemoteThread线程返回值读取是整个库当之无愧的中央转换器。核心原理一ObjectToByteArray——托管对象转字节数组的快速通道ObjectToByteArray定义在src/MemorySharp/Internals/MarshalType.cs逻辑非常清晰先尝试零封送快速路径不行再走通用的非托管内存回退路径。所谓快速路径就是根据缓存的TypeCode直接命中BitConverter.GetBytes例如case TypeCode.Int32: return BitConverter.GetBytes((int)(object)obj); case TypeCode.Double: return BitConverter.GetBytes((double)(object)obj);因为BitConverter是纯内存拷贝级别的转换比 CLR 的 Marshal 封送快一个数量级所以作者在注释里特意写道Well tried to avoid marshalling as it really slows the process我们尽量避开封送因为它严重拖慢进程。几个值得注意的细节char类型使用Encoding.UTF8.GetBytes转换IntPtr按指针宽度拆成 4 或 8 字节string直接抛出InvalidCastException——字符串在 MarshalType 层被刻意拒绝因为字符串的长度不固定需要走MarshalValue专门的远程分配逻辑。核心原理二ByteArrayToObject——字节数组转托管对象的还原流程反向方法ByteArrayToObject(byte[] byteArray, int index 0)同样遵循快速路径优先原则并通过可选的index参数支持从字节流中间位置开始还原。这正是ReadT(address, count)批量读取数组时能复用同一段字节缓冲区的关键——每MarshalTypeT.Size个字节还原一个元素避免反复调用底层读取。这里还有一个非常精巧的细节IntPtr的还原会先检查字节数组的长度1、2、4、8分别补齐高位后转成ToInt32兼容了从远程进程读回不完整指针的边界情况。回退路径揭秘LocalUnmanagedMemory 的通用封送方案当类型不是基础类型比如自定义结构体时MarshalType 会启用通用方案借助src/MemorySharp/Memory/LocalUnmanagedMemory.cs完成转换在本进程用Marshal.AllocHGlobal分配一块非托管内存通过Marshal.StructureToPtr把托管对象写入这块内存再用Marshal.Copy把整块内存原样拷成字节数组返回。反向还原则是对称的先把字节数组Marshal.Copy进非托管内存再Marshal.PtrToStructure还原成托管对象。因为是using包裹的IDisposable实现内存会在使用后自动释放不会泄漏。这套通用方案保证了任意可封送结构体都能走通转换代价是性能略低——这正是快速路径存在的意义。静态度量一次初始化、处处复用的类型元数据缓存MarshalTypeT是一个泛型静态类它的静态构造函数在第一次使用时执行一次把Size、TypeCode、IsIntPtr、RealType、CanBeStoredInRegisters全部缓存下来。这意味着Marshal.SizeOf(RealType)只计算一次后续读取结构体大小时零开销bool被特殊处理为 1 字节Type.GetTypeCode拿到的是 Boolean走 1 字节而非 4 字节静态缓存让每次ReadT/WriteT都无需重复反射这是 MemorySharp 内存读写保持高性能的基础。注册表快速通道CanBeStoredInRegisters 的寄存器优化CanBeStoredInRegisters是 MarshalType 最有趣的优化开关。如果类型是IntPtr或各类整数、bool、char、单精度浮点以及 x64 下的 64 位整数它就能直接塞进 CPU 寄存器。这个判断直接影响PtrToObject的行为当类型可存入寄存器时直接把指针本身的值当作数据返回BitConverter.GetBytes(pointer.ToInt64())否则才真正去远程进程读取Size字节。这解释了为什么MarshalTypelong.PtrToObject(sharp, new IntPtr(32))能直接返回 32——它读的不是指针指向的内存而是指针数值本身。实战流程一次完整的内存读写如何运转把上面的知识点串起来一次sharp.ReadPoint(address)的完整链路是按MarshalTypePoint.Size向远程进程读取原始字节调用ByteArrayToObject因Point是结构体TypeCode.Object而非基础类型进入非托管内存回退路径Marshal.PtrToStructure还原出Point对象返回给调用方。你可以直接看test/IntegrationTests/Internals/MarshalTypeTests.cs中的ToManagedObjectPointStruct测试把结构体转成字节数组再转回结构体断言两者相等完整验证了这条往返链路的正确性。常见问题与注意事项字符串转换会抛异常MarshalTypeT.ObjectToByteArray和ByteArrayToObject遇到string都会抛InvalidCastException字符串应交给MarshalValue处理它会自动在远程进程分配长度 1字节含结束符\0并写入结构体必须可封送走回退路径的结构体需要满足[StructLayout]约束否则StructureToPtr会失败区分指针值与指针指向的值PtrToObject对寄存器型类型返回的是指针数值本身不要与ReadT(address)读取的地址处的数据混淆批量读取有额外优化MemorySharp.cs中读取T[]数组时若T是byte会直接Buffer.BlockCopy跳过逐元素转换。结语读懂 MarshalType就读懂了 MemorySharp 的数据流MarshalTypeT用不到 300 行代码把一个看似简单的类型 ↔ 字节转换做到了极致静态缓存类型元数据、BitConverter快速通道、非托管内存通用回退、寄存器级优化判断四者环环相扣。无论你是想深入理解 MemorySharp 内存读写原理还是准备二次开发这个 C# 内存编辑库源码都值得反复研读——相关实现集中在src/MemorySharp/Internals/MarshalType.cs与src/MemorySharp/Internals/MarshalValue.cs配套测试在test/IntegrationTests/Internals/目录下配合阅读效果更佳。【免费下载链接】MemorySharpA C# based memory editing library targeting Windows applications, offering various functions to extract and inject data and codes into remote processes to allow interoperability.项目地址: https://gitcode.com/gh_mirrors/me/MemorySharp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进