惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

博客园 - smalldust

NTT大规模网络故障 亲手焙制一个极其简单但却极其实用的Reflector插件 关于园子里讨论的软件的追求的杂谈 .Net 2.0 原汁原味读取注册表 为什么我不用IE7和FireFox 给.Net程序员的PInvoke Tips [2]: Are Strings Immutable? 除了Exception,你还能throw什么? 给.Net程序员的PInvoke Tips [1]: String is Sometimes an Integer CLR Team程序员出的难题,有兴趣的朋友不妨挑战一下 - smalldust - 博客园 Google Trends发布 也谈用反射实现Enum→String映射:一种重视性能的方法 针对个例的、社区性的维基系统设想(草稿) 数学的思考方式 VS 程序的思考方式 WinForm程序启动时不显示主窗体的实现方法 C#程序模拟鼠标操作 [Simulate Mouse Movement and Click Programmatically] 如何在C#中获取“当前目录” Windows Vista将推迟到2007年1月发布 .Net 2.0实例学习:WebBrowser页面与WinForm交互技巧 使用关键字作为自定义标识符
Reflector保护方法初探
smalldust · 2006-07-17 · via 博客园 - smalldust

Reflector作为一个如此强大的反编译工具,其本身的保护也一定很完善。曾经有高手的文章[1][2]介绍Reflector的保护方法,但是时过境迁,新版本的Reflector又采用了更为隐晦的保护措施,给想了解Reflector内部细节的人提高了门槛。

下面,就本着学习的态度,把我在分析Reflector时所看到的保护方法简单介绍一下,以当前的最新版本4.2.45.0为例。

1,混淆
混淆应该是Assembly保护的最基本措施了,混淆工具也是比比皆是。用Reflector打开Reflector自己,便可以看到除了若干接口、枚举的定义,就是8,9个名字都为“□”的类;类里面的所有成员以及Nested Class的名字也都叫“□”。这里和以前的版本是相同的,只不过是把各种标识符的名字用系统无法显示的unicode字符代替而已吧。
名字混淆时,很重要的一点就是把实现接口的方法名、Main方法名等等也要加以混淆——不要以为这些名字是不能混淆的。

此外,Reflector还对IL代码进行了简单的混淆,使得很多重要的方法用Reflector反编译成其他语言时,会显示“This item appears to be obfuscated and can not be translated.”。这种情况下为了分析代码,只能读IL;或者是用其他反编译工具分析。

2,防篡改·反Debug
为了防止篡改Assembly,Reflector中为Assembly增添StrongName,以及在程序中检测StrongName是否正常。
为了防止被动态跟踪,在Reflector当中很多地方都会用System.Diagnostics.Debugger.IsAttached检测Debugger是否存在。

3,字符串加密
通常的混淆当中,虽然可以将类和成员的名字变成“乱码”,但是源代码中的字符串(例如要显示一个消息)往往会轻易暴露一段代码的意图。假如某段代码中含有“Error: Can not open file”字样的字符串,我们很容易猜测到这里是不是在打开一个文件。Reflector当中为了防止别人轻易地看到字符串,使用了一个简单的加密函数。这样,别人在阅读源代码时,所有字符串的部分都是毫无意义的一些乱码。Reflector在使用这些字符串时,首先将他们解密,然后再使用。

4,动态加载Assembly
当我们打开Reflector.exe查看Reflector的源代码时,发现代码量很少;也就是说,真正的应用部分被隐藏起来了——隐藏到哪里了呢?前版本的Reflector据说是隐藏在Menifest Resource里面了;新版本的Reflector为了增强隐蔽性,直接把它隐藏在PE文件的.rsrc段的末尾了。为了读取这段“真身”,Reflector.exe当中专门有一个读取PE文件的类,基本逻辑就是找到.rsrc Section,加上.rsrc Section的长度(也即定位到其末尾),再读取一个Int32(“真身”的长度),然后将这段内容读取到内存当中。

这段内容是经过3DES加密的,很有趣的是,密钥是一段劝说你不要破解Reflector的文字的MD5 Hash值。

就算解密之后,这段内容仍然不是一个有效的Assembly——它到底是什么呢?仔细看看Reflector之后的举动,我们就发现,这段内容其实是一个Zip文件。Reflector把这段内容在内存中解压缩,再使用Assembly.Load(byte[])将其载入(并且载入过程全部是用反射方法,程序中根本不会直接出现Assembly.Load字样)。

因此整个过程就是,Reflector是将其主要逻辑所在的Assembly(Reflector.Application.dll)先压缩成一个Zip文件,然后用3DES算法加密,塞到.rsrc段的末尾;在执行时,进行反向操作,动态加载Assembly。

以上简单介绍了Reflector的保护方法。和传统的EXE文件的加密和保护相比,.Net Assembly的保护还显得很稚嫩,Reflector的IL虽然也经过了简单混淆,但是也没有汇编代码那样的错综复杂的、大段无用的代码,看起来仍然是比较易懂的。