技术心得记录:强命名的延迟与关联在.net程序集保护中的作用及其逆向方法

简介: 技术心得记录:强命名的延迟与关联在.net程序集保护中的作用及其逆向方法

一、老调重谈强命名


强命名的定义这里就不重复了,不妨就把他看作一个文件的hash,而如果文件被修改的话,计算出的hash将与最被程序设计者给定的强命名不一致,程序将拒绝加载。这可怜的一点点安全特性被人用多种方法证实原来靠强命名保护程序集只是纸老虎。


至少有三种方法可以去除单独的可执行文件的强命名:


1、 ildasm反编译,在il源代码中删除该assembly对强命名的引用,再编译回去。在.net初期时,这种方法还是很好用


的,codeproject上也介绍过。但是现在的程序对于ildasm的anti越来越强,想完整的反编译再完整地编译回去,有时还不太容易。


2、 利用工具,原理是将CLI Header的标志置0


CLI Header的结构如下:


RVA Field Contents


0x2008 Cb(结构的大小) 0x48


0x200C MajorRuntimeVersion 2


0x200E MinorRuntimeVersion 0


0x2010 MetaData 0x2060


0x2014 Size of the Metadata 0x148 =(RVA of Import Table) ? (RVA of MetaData)


0x2018 Flags 1


0x201C EntryPointToken 0x06000001 (Method #1 in TypeDef table)


0x2020 Resources 0


0x2028 StrongNameSignature 0


0x2030 CodeManagerTable 0


0x2038 VTableFixups 0


0x2040 ExportAddressTableJumps 0


0x2048 ManagedNativeHeader 0


包括flags标志要减去COMIMAGE_FLAGS_STRONGNAMESIGNED (0x00000008) ,以及


StrongNameSignature处表示的强命名的偏移位置和大小要置0。这还没完,还要将Metadata表中AssemblyDef处的强命名


标志删除。


来看一下AssemblyDef的定义:


? HashAlgId (a 4-byte constant of type AssemblyHashAlgorithm).


? MajorVersion, MinorVersion, BuildNumber, RevisionNumber


(2-byte constants).


? Flags (a 4-byte bit mask of type AssemblyFlags).


? PublicKey (index into Blob heap).


? Name (index into String heap).


? Culture (index into String heap).


其中Flags项要减去afPublicKey = 0x0001。


3、就是利用Patch系统文件的形式。这种形式不推荐,毕竟强命名还有判别版本差异及文件完整性的作用,整个Patch了不大方便。


二、延迟强命名


现在的.net程序都被混淆过了。比如你原来写了个计算注册码的程序叫CalRegCode(),但是混淆过的程序名可能是


x0ab23ff10(),或者干脆是不可打印的ASCII字符。但如果你在程序中使用了强命名,混淆不会出错吗?这里其实就要用到延迟强命名。


在VisualStudio中,点击项目的属性的sign选项,选择延迟强命名:


如果不想在窗口中设置,可以直接在AssemblyInfo.cs中设置如下:


【assembly:AssemblyKeyFileAttribute("key.snk")】


【assembly:AssemblyDelaySignAttribute(true)】


延迟强命名就是在编译程序时设置好标志,并将存储空间留出,在编译完成后人工加上。比如,我们可以将strings流中的一些敏感名称,比如crypt()、crypcal()改为不可见:


保存后在命令行用:sn ?Ra xxxx.exe key.snk重新给文件签属强命名便OK了。


修改名称有个注意事项,如果你修改的方法名称,在别的程序集中对此方法有调用的话,必须在调用的文件中也把相应的方法改为相同的名字,应为这种调


用是按名称来的,否则会报找不到method的错误。但总的来说,如果仅仅对一个文件使用这种延迟强命名的方法,仍然是非常容易修改的。但如果一个主程序


a.exe要调用b.dll和c.dll时(甚至更多,或者b与c间存在调用),而b.dll和c.dll都被加上强命名的话,这样如果修改


b.dll(比如网络验证在b.dll中,我们要对其进行patch),整个程序则会报错。下面一节就讲讲这种整个程序中存在多个文件,且每个文件都有强


命名的情况,看看他的保护强度和破解。我暂时给它起名叫关联强命名。


三、关联强命名


我们来建一个C#工程,名叫example,其中存在两个dll(a.dll和b.dll),主程序对这两个程序分别存在调用,dll的代码只是弹出窗口显示被调用了,且每个dll都被加上强命名。并在主项目中添加对a和b的引用。


a与b中的代码如图所示。主程序中建两个button控件,分别调用这两个Class Library中的方法。


代码如下:


代码:


private void button1_Click(object sender, EventArgs e)


{


a.Class1 newa=new a.Class1();


newa.showMsg();


}


private void button2_Click(object sender, EventArgs e)


{


b.Class1 newb=new b.Class1();


newb.showMsg();


}


单击不同的button会显示不同的窗口,提示当前是哪个lib被调用。如,单击checkLib1的窗口如下:


由于a.dll与b.dll中已被加上强命名,我们试着修改一下,看看能否运行。比如将a.dll中窗口的显示字符改为“ClassLibrary A is called”(UserString的存储格式为Unicode):


00001590h: 53 68 6F 77 00 00 00 00 00 31 43 00 6C 00 61 00 ; Show.....1C.l.a.


000015a0h: 73 00 73 00 4C 00 69 00 62 00 72 00 61 00 72 00 ; s.s.L.i.b.r.a.r.


000015b0h: 79 00 20 00 41 00 20 00 69 00 73 00 20 00 63 00 ; y. .A. .i.s. .c.


000015c0h: 61 00 6C 00 6C 00 65 00 64 00 00 00 E5 79 88 40 ; a.l.l.e.d...妁?


运行后单击checkLib1,会报错无法载入a.dll:


这样看来,如果我们将关键代码分布在多个dll中,且每个dll加上强命名,并且存在一定的相互调用,就可以保护我们的程序集了。是不是这样呢?我们来看看example.exe中对a.dll的引用,看为什么它会认出我们修改了文件。


Example.exe中的AssemblyRef表中存储了关于a.dll和b.dll的信息,AssemblyRef表的结构如下:


The AssemblyRef table has the following columns:


? MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)


? Flags (a 4-byte bitmask of type AssemblyFlags; see Partition II, section 22.1.2)


? PublicKeyOrToken (index into Blob heap―the public key or token that identifies the author of this assembly)


? Name (index into String heap)


? Culture (index into String //代码效果参考:http://hnjlyzjd.com/xl/wz_24972.html

heap)

? HashValue (index into Blob heap)


其中第三项就规定了是否有PublicKeyOrToken,也就是是否有强命名。看看example.exe中的数据:


其中PublicKeyOrToken项清清楚楚地写的0x00be,这就是有强命名的标志,强命名存储在#Blog表中第0x00be项。再来看一下#Blog表,第0x00be项如下:


到这一步,我们就应该知道怎么修改了。首先,将example.exe中对a的引用表中的PublicKeyOrToken项的值改为0,然后第二步是去除a.dll中的强命名。修改完成后,我们再运行,果然,系统已经不再报错,并正确显示我们所修改的字符串了:


四、小结


到这里,强命名的几种应用形式基本介绍完。试想,如果一个有数十个文件的程序每个文件都被加个强命名,其保护强度也是很一般的。我们只须编写程序


自动去除每个文件的本身强命名定义与AssemblyRef中的强命名定义(注意,不要把系统文件包含在内),就可以很方便地进行修改。因此,用


StrongName做为程序的保护手段实在是不可取,还应另寻别路。


附件中是example.exe、a.dll和b.dll,其中a.dll已经修改过,而剩下的修改b.dll留给各位自己动手实践一下。


from :


Original article, please indicate the source:

相关文章
|
2天前
|
人工智能 前端开发 开发工具
解读.NET 技术的开发潜力
本文全面介绍了.NET技术在软件开发领域的核心优势、创新应用及面临的挑战。.NET以其统一的开发平台、强大的工具和跨平台能力,成为企业级应用、Web应用乃至游戏开发的理想选择。然而,在性能优化、容器化及AI集成等方面仍需不断突破。通过积极拥抱开源和社区驱动模式,.NET将持续推动软件开发的进步。
13 1
|
15天前
|
Ubuntu 持续交付 API
如何使用 dotnet pack 打包 .NET 跨平台程序集?
`dotnet pack` 是 .NET Core 的 NuGet 包打包工具,用于将代码打包成 NuGet 包。通过命令 `dotnet pack` 可生成 `.nupkg` 文件。使用 `--include-symbols` 和 `--include-source` 选项可分别创建包含调试符号和源文件的包。默认情况下,`dotnet pack` 会先构建项目,可通过 `--no-build` 跳过构建。此外,还可以使用 `--output` 指定输出目录、`-c` 设置配置等。示例展示了创建类库项目并打包的过程。更多详情及命令选项,请参考官方文档。
56 11
|
15天前
|
监控 网络协议 API
.NET WebSocket 技术深入解析,你学会了吗?
【9月更文挑战第4天】WebSocket 作为一种全双工协议,凭借低延迟和高性能特点,成为实时应用的首选技术。.NET 框架提供了强大的 WebSocket 支持,使实时通信变得简单。本文介绍 WebSocket 的基本概念、.NET 中的使用方法及编程模型,并探讨其在实时聊天、监控、在线游戏和协同编辑等场景的应用,同时分享最佳实践,帮助开发者构建高效实时应用。
58 12
|
9天前
|
人工智能 前端开发 Devops
.NET技术自发布以来,在软件开发领域发挥了重要作用
【9月更文挑战第12天】.NET技术自发布以来,在软件开发领域发挥了重要作用。本文分为三部分探讨其在现代开发中的应用:首先介绍.NET的核心价值,包括语言多样性、强大的开发工具支持、丰富的类库、跨平台能力和活跃的社区;接着分析其在企业级应用、Web开发、移动应用、云服务及游戏开发中的实际应用;最后讨论.NET面临的挑战与未来趋势,如性能优化、容器化、AI集成及跨平台框架竞争等。通过不断的技术创新和社区驱动,.NET将持续推动软件开发的进步。
21 4
|
14天前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
14天前
|
人工智能 开发框架 算法
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
|
14天前
|
传感器 应用服务中间件 Linux
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
|
14天前
|
自然语言处理 C# 图形学
使用dnSpyEx对.NET Core程序集进行反编译、编辑和调试
使用dnSpyEx对.NET Core程序集进行反编译、编辑和调试
|
14天前
|
人工智能 算法 C#
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
|
14天前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
21 7