技术心得记录:强命名的延迟与关联在.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:

相关文章
|
15天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
61 13
|
1月前
|
自然语言处理 物联网 图形学
.NET 技术凭借其独特的优势和特性,为开发者们提供了一种高效、可靠且富有创造力的开发体验
本文深入探讨了.NET技术的独特优势及其在多个领域的应用,包括企业级应用、Web应用、桌面应用、移动应用和游戏开发。通过强大的工具集、高效的代码管理、跨平台支持及稳定的性能,.NET为开发者提供了高效、可靠的开发体验,并面对技术更新和竞争压力,不断创新发展。
47 7
|
1月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
24 5
|
1月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
32 4
|
1月前
|
开发框架 .NET C#
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位。从企业应用到电子商务,再到移动开发,.NET 均展现出卓越性能,助力开发者提升效率与项目质量,推动行业持续发展。
29 4
|
1月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
34 3
|
1月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
24 3
|
1月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
30 3
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
48 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
75 0