.NET Reactor 4.0 - Metadata 手工修复记
来源:互联网 发布:js统计人数 编辑:程序博客网 时间:2024/05/29 15:13
.NET Reactor 4.0 (Beta) 相对于以前的版本有很大的提升,就连最常用的 "Suppress ILDASM" 都升级成 "Suppress Decompilation / Anti ILDASM"。本文就是用这个功能做案例,来锻炼自己对元数据表结构的认知。
1. 加密
找个目标程序集,用 4.0 加密,注意不要选择其他选项,仅选中 "Quick Settings" 中的 "Anti ILDASM" 即可。因为本文的目的是手工修复元数据表,而不是为了完成一个破解过程。
当我们用 .NET Reflector 或者 Mono Cecil 打开这个加密的程序都会发现出错,可见还是具有一定的防护能力的。接下来,我们就依照 .NET Reflector 给出的错误信息开始手工修复过程。
2. 修复
先准备好相应的工具软件,包括 CFF Explorer VII、ILDASM (修改版)、计算器 (16进制计算),以及一个随手记录信息的记事本。
(1) NumberOfRvaAndSizes
这个错误通常是 Optional Header 中的 NumberOfRvaAndSizes 被修改造成的,其实际值应该是 0x00000010 (16)。修改保存,刷新 Reflector,继续下一个错误信息。
(2) NumberOfStreams
这也是一个比较常见的手段,通过造成错误的 MetaData Streams 来达到干扰目的。
多了一个冒牌的 #GUlD 和 #Blop。没关系,将后面正确的 Offset 和 Size 值拷贝到山寨货的位置,同时在 Hex Editor 中跳转到到相应的 Offset 位置,修正这两个冒牌货的名字。
当然,别忘了在 MetaData Header 中将 NumberOfStreams 从 0007 改成 0005。保存后在 CFF Explorer VII 中重新打开目标文件。再次浏览 MetaData Streams 时,#Strings、#GUID、#US 和 #Blob 数据都恢复正常。
(3) Multiple Assembly Definitions
刷新 Reflector 继续下一个错误信息。
晕~~~~ 这个太变态了,居然包含多个程序集。这显然是动了 #~ Stream 了。
在 Tables 中我们果然看到了多出的这个破坏分子。怎么办呢?先复习一下 Metadata 结构知识。#~ 中前 24 bytes 存储了 Metadata Header 信息。从 0x00000018 (Offset 24) 开始存储的是 Rows 信息,也就是你在 Tables 中看到的各种类型统计数字。Rows 的长度是 4 * n。
我们数数看,一共 15 种类型,也就是说长度是 60 (0x3c),偏移位置应该是 0x00000018 ~ 0x00000053。Assembly 的索引序号是 11 (从0开始),偏移位置就是 0x00000018 + 11 * 4 = 0x00000044。在 CFF Explorer VII 中的 #~ 右侧 16 进制编辑器中将 Row 值 从 02 改成 01。
注意,事情并没有结束。在 Rows 之后,也就是 0x00000054 开始存储的是各种具体类型细节信息的 Tables,我们修改了 Row 值,也就意味着 Tables 连续读取的 Index 和 Offset 也会发生变化,因此我们需要将后续数据前移 4 byte,覆盖被剔除的那个伪造 Assembly 数据。
首先得获取伪造 Assembly 详细信息的偏移量。由于这次的偏移量计算涉及到不同具体类型信息的长度,因此我们借助 ILDASM 来获得相应数据。用 ILDASM 打开目标文件,在 View -> MetaInfo 菜单中选中 Raw:Header,Schema,Rows 和 Raw:Heaps 两项。然后 Ctrl + M 查看元数据信息。
===========================================================Metadata section: 0x424a5342, version: 1.1, extra: 0, version len: 12, version: v2.0.50727 flags: 0x00, streams: 5Stream 0: name: #~, size 1040Stream 1: name: #Strings, size 1448Stream 2: name: #GUID, size 32Stream 3: name: #US, size 216Stream 4: name: #Blob, size 444Metadata header: 2.0, heaps: 0x00, rid: 0x01, valid: 0x000003092000d557, sorted: 0x0000000000000000Strings: 1448(0x5a8), Blobs: 444(0x1bc), Guids: 32(0x20), User strings: 216(0xd8)=================================================...32(0x20): Assembly cRecs: 2(0x2), cbRec: 22(0x16), cbTable: 44(0x2c) col 0: HashAlgId oCol: 0, cbCol:4, ULONG col 1: MajorVersion oCol: 4, cbCol:2, USHORT col 2: MinorVersion oCol: 6, cbCol:2, USHORT col 3: BuildNumber oCol: 8, cbCol:2, USHORT col 4: RevisionNumber oCol: a, cbCol:2, USHORT col 5: Flags oCol: c, cbCol:4, ULONG col 6: PublicKey oCol:10, cbCol:2, blob col 7: Name oCol:12, cbCol:2, string col 8: Locale oCol:14, cbCol:2, string ------------------------------------------------- 1 == 0:00008004, 1:0001, 2:0000, 3:0000, 4:0000, 5:00000000, 6:blob#0, 7:string#1, 8:string#0 2 == 0:00008004, 1:0001, 2:0000, 3:0000, 4:0000, 5:00000000, 6:blob#0, 7:string#6, 8:string#0...
嗯,很好,有个 04 80 00 00 的标记,我们找到这个位置就行了。继续在编辑器中工作,找到第二个标记位置(0x000003AE),往后数出 22(0x16) 个字节(0x000003AE ~ 0x000003C3),这就是我们要覆盖的数据。选择 0x000003C4 开始的数据,以 Unicode 方式拷贝,并 Write 到 0x000003AE 处。
拷贝
写入
保存修改 (注意关掉 ILDASM,否则无法保存)。刷新 Reflector,可以看到该错误被修复。
(4) Multiple Module Definitions
这个错和上面的如出一辙,修复手段也一样。
先修改 Rows 值,Module 是第一项,偏移位置就是 0x00000018,将其修改为 01 即可 (先别保存,否则 ILDASM 无法打开)。
... 0(0): Module cRecs: 2(0x2), cbRec: 10(0xa), cbTable: 20(0x14) col 0: Generation oCol: 0, cbCol:2, USHORT col 1: Name oCol: 2, cbCol:2, string col 2: Mvid oCol: 4, cbCol:2, GUID col 3: EncId oCol: 6, cbCol:2, GUID col 4: EncBaseId oCol: 8, cbCol:2, GUID ------------------------------------------------- 1 == 0:0000, 1:string#2b, 2:guid#1, 3:guid#0, 4:guid#0 2 == 0:0000, 1:string#0, 2:guid#2, 3:guid#0, 4:guid#0...
记录长度为 10(0xa),那么第二条记录的偏移位置就是 0x00000054 + 0xa = 0x0000005E。数出 10 bytes (0x0000005E ~ 0x00000067),将其后的数据按照前面的手法前移覆盖(顺便说一下 CFF Exploer VII 的编辑器不太好用,可能需要多次拷贝覆盖,千万记住上次覆盖的结束位置,避免出错)。
保存修改。再次用 Reflector 刷新程序集时,我们已经可以看到其原始面目了,表明我们的修复工作顺利完成。
------- 分割线 --------------
最简单的修复手法是 ILDasm + ILAsm,不过本文的目的是为了复习元数据的相关知识,因此手工修复可以加强对相关知识的了解。同时该文章也表明很多看上去貌似高深的技术,其根本还是对基础知识的掌握,当然少不了耐心和细心。
附件是修复前的原始加密文件,大家可以据此练习本文操作过程。而有关 Metadata 结构定义可以到 ECMA C# and Common Language Infrastructure Standards 下载 MS Partition II。
点击下载原始加密文件 (重新加密的,和上面演示的数据有出入)
- .NET Reactor 4.0 - Metadata 手工修复记
- .net reactor
- .net metadata/IL/BCL
- NET Reactor 3.7.1.0
- .net reactor 学习系列
- .net reactor 学习系列(一)---.net reactor介绍
- .net reactor 学习系列(四)---.net reactor应用场景
- .net reactor 学习系列(一)---.net reactor介绍
- 手工修复受损的U盘
- 手工修复PE文件的IAT
- DBCC CHECKDB用法 手工修复数据库
- DBCC CHECKDB用法 手工修复数据库
- 实战:DBCC CHECKDB用法 手工修复数据库
- DBCC CHECKDB用法 手工修复数据库
- .NET Reactor v2.2.5.0
- .NET Reactor v2.3.0.5
- .NET Reactor v 2.9.0.5
- .NET Reactor v 3.4.8.2
- Android GSM驱动模块(rild)详细分析(三)response流程
- 关于数据库死锁的检查方法
- loadrunner tuxedo协议测试
- android:windowSoftInputMode
- 使用Ext.decode()解析JSON字符串时firebug提示extjs missing ] after element list错误
- .NET Reactor 4.0 - Metadata 手工修复记
- Android开发之dip, dp, px, sp区别
- android TextView属性大全(转)
- TextView添加分割线
- liseview分割线设置
- Android 调试工具集
- 再见了,801
- SLF4J 教程
- Android 几个Info系列类的总结