Reflector: Get the secret inside .NET assemblies.

Reflector: Get the secret inside .NET assemblies.

Reflector: Get the secret inside .NET assemblies.

 

Writen by Allen Lee

用.NET编程的朋友应该都知道ILDASM的大名吧,这里为大家介绍另一个名为Reflector的好东东。为了了解Reflector,我特意写了一个代码片断(这里只给出用C#写的Main方法的代码):

 

None.gif static   void  Main( string [] args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    List
<string> strList = new List<string>();
InBlock.gif
InBlock.gif    
if (args.Length != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
foreach (string arg in args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
switch (arg)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
case "IL":
InBlock.gif                    Console.WriteLine(
"IL");
InBlock.gif                    strList.Add(
"IL");
InBlock.gif                    
break;
InBlock.gif                
case "C#":
InBlock.gif                    Console.WriteLine(
"C#");
InBlock.gif                    strList.Add(
"C#");
InBlock.gif                    
break;
InBlock.gif                
case "VB.NET":
InBlock.gif                    Console.WriteLine(
"VB.NET");
InBlock.gif                    strList.Add(
"VB.NET");
InBlock.gif                    
break;
InBlock.gif                
case "Delphi":
InBlock.gif                    Console.WriteLine(
"Delphi");
InBlock.gif                    strList.Add(
"Delphi");
InBlock.gif                    
break;
InBlock.gif                
default:
InBlock.gif                    Console.WriteLine(
"Invalid Option");
InBlock.gif                    
break;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"No command line args!");
InBlock.gif        Console.WriteLine(
"Press any key to end.");
InBlock.gif        Console.ReadLine();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
foreach (string str in strList)
InBlock.gif        Console.WriteLine(str);
ExpandedBlockEnd.gif}

 

将上面的代码进行编译,并命名为ReflectorLab.exe。然后我们运行Reflector,一开始它的界面是:

o_Reflector.JPG

接着,我们打开菜单:File|Open,找到并选择刚刚编译的程序集,该程序集将会被加入到程序集列表,打开ReflectorLab的树,找到Main(string[]):Void这个方法,右击并选择Disassembler,将会得到下图的反编译代码:

o_Disassembler.JPG

现在截取反编译后的Main方法完整代码如下:

 

None.gif private   static   void  Main( string [] args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    List.Enumerator
<string> enumerator1;
InBlock.gif    List
<string> list1 = new List<string>();
InBlock.gif    
bool flag1 = args.Length == 0;
InBlock.gif    
if (flag1)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"No command line args!");
InBlock.gif        Console.WriteLine(
"Press any key to end.");
InBlock.gif        Console.ReadLine();
InBlock.gif        
goto Label_010F;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
string[] textArray1 = args;
InBlock.gif    
int num1 = 0;
InBlock.gif    
goto Label_00E0;
InBlock.gifLabel_00CC:
InBlock.gif    Console.WriteLine(
"Invalid Option");
InBlock.gifLabel_00D9:
InBlock.gif    num1
++;
InBlock.gifLabel_00E0:
InBlock.gif    flag1 
= num1 < textArray1.Length;
InBlock.gif    
if (flag1)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
string text3 = textArray1[num1];
InBlock.gif        
if (text3 == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
goto Label_00CC;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
if (text3 != "IL")
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (text3 == "C#")
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(
"C#");
InBlock.gif                list1.Add(
"C#");
InBlock.gif                
goto Label_00D9;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (text3 == "VB.NET")
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(
"VB.NET");
InBlock.gif                list1.Add(
"VB.NET");
InBlock.gif                
goto Label_00D9;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (text3 == "Delphi")
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(
"Delphi");
InBlock.gif                list1.Add(
"Delphi");
InBlock.gif                
goto Label_00D9;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
goto Label_00CC;
ExpandedSubBlockEnd.gif        }

InBlock.gif        Console.WriteLine(
"IL");
InBlock.gif        list1.Add(
"IL");
InBlock.gif        
goto Label_00D9;
ExpandedSubBlockEnd.gif    }

InBlock.gifLabel_010F:
InBlock.gif    enumerator1 
= list1.GetEnumerator();
InBlock.gif    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
goto Label_0128;
InBlock.gif    Label_0119:
InBlock.gif        Console.WriteLine(enumerator1.Current);
InBlock.gif    Label_0128:
InBlock.gif        flag1 
= enumerator1.MoveNext();
InBlock.gif        
if (flag1)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
goto Label_0119;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        enumerator1.Dispose();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 

反编译的代码在功能效果上与原代码是相同的,但是个人认为反编译的代码的风格却不怎么棒,尤其是充满goto语句,乍一看我真的晕了过去。代码把原来的switch条件块换成if条件块,将foreach循环块换成while循环块。我猜这是由于它是从IL那里翻译出来的,而IL就是一门基于堆栈的语言,在IL里面没有流程控制语句,全部使用goto + Label模拟,于是得到这样的结果。

除此之外,我还发现一些很特别的东西,请留意这一句:text3 = string.IsInterned(text3); 它其实反映了.NET的字符串处理方式是使用了一种叫做字符串驻留(String Interning)的技术,该技术是为了减轻字符串的操作为系统带来的性能损失(详细请参见《Microsoft .NET框架程序设计(修订版)》的262页)。另外我们看到原代码最后的foreach被翻译成一个try...finally块,在try里面实现foreach的功能,然后再finally里面自动为每一个enumerator试着调用IDisposable接口来释放资源,真是想得周到相信对应的IL也会有同样的“设施”,如果你懂IL的话,而你又肯定在这里不需要这样一个finally的话,那么你可以手动优化一下了,呵呵。

翻译后的代码是有点复杂和混乱,不过,你可以从中窥探.NET的(部分)运行机制(而这种窥探原本是应该使用IL的),并了解到简单的C#代码背后,编译器在默默地为我们作了不少的工作!最后,我们还会惊喜地发现,Reflector不但支持反汇编成C#,还支持IL、VB.NET、Delphi,这下子爽了,我们可以比较并学习这些语言,以前我们用ILDASM来反汇编C#写的程序来学习IL,现在我们可以用Reflector反汇编C#写的程序来学习VB.NET和Delphi啦!当然,由于篇幅的问题,我不可以再往里面灌水(依次加入IL、VB.NET、Delphi反编译的代码)。

另外,你会发现这些源代码的某些地方,通常是类型名称或者方法名称又或者属性会是一个连接,按下去看看有什么事发生!是不是连接到该东西(类型或者方法或者属性)的.NET基类库的反编译代码上了?

最后,在文章的结束,我还有一个惊喜给你,就是Reflector本身是一个.NET程序,这意味着它还可以反汇编它自己,不信的话你可以试试看!

噢,补充一点,当你运行Reflector后,它会在它所在的文件夹会生成一个叫Reflector.cfg的文件,这个不是XML文件,是一种INI格式的配置文件,请留意该文件的[AssemblyLoader]区段,有什么发现了没有?好了,这次的介绍就到此为止,希望你发现更多的东西来跟我分享!

 

posted on 2004-10-23 15:12 Allen Lee 阅读(472) 评论(7)  编辑 收藏

评论

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-23 15:19

Good.   

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-23 15:38

强!好东西!   

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-23 15:55

下载了一个看了一下,强得离谱,把我的一些小程序几乎一字不拉的(除了一些变量名)反编译出来了   

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-23 16:30

Disassemble Reflector is impossible mission. It's assembly is confused out of our imaginewhat_smile.gif.

  

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-23 16:53

To birdshome:

或者你不相信它本身能被反编译,更令我惊讶的是,它能够在自身运行的时候对自身进行反编译!我特意抓了一幅图展示一下:

o_ReflectItself.JPG

其中,Application class就是程序的主class,被展开的Reflector根节点就是程序本身。Amazing! 如果阁下对于Reflector的能力还有任何疑问的话,何不亲自下在一个鉴证鉴证?

  

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-25 08:40

现在已经发展到4.1.11.0以上了,作者每改善一个很小的点,就会增加一个第三版本号。他很在意用户的反馈,如果你觉得翻译的不对可以写信提出。我已经写了3次以上的信了,现在反编译VB中TryCast语法,When语法和有Target的Attribute语法都是我写信以后立刻就得到改进的,非常棒!   

 re: Reflector: Get the secret inside .NET assemblies. 2004-10-25 08:46

To Ninputer:

Wonderful!! 我之前也试过E-Mail作者Reflector的一个小小的Bug,作者马上承诺下一个版本改进。看来Reflector的作者不但为我们贡献这么一个功能强大的好东西,还积极尽责为我们改善它,精神可嘉!另外,这篇文章的Reflector是基于最新的4.1.11.0的。如果Ninputer有兴趣的话,你也不妨为VB.NET迷们写一篇并透露你所看到的有用的细节,相信会对社区有很大的帮助。

 re: Reflector: Get the secret inside .NET assemblies.      

转载于:https://www.cnblogs.com/wenus/archive/2005/01/07/88178.html

可升级, Reflector是一款比较强大的反编译工具,相信很多朋友都用过它,但reflector本身有很多局限性,比如只能一个一个的查看方法等,但幸好reflector支持插件功能目前网上有很多reflector的插件,本人找取了两个应用范围很广,并且广受好评的插件:Reflector.FileDisassembler和Reflector.FileGenerator和Reflector进行了整合,放在了一个压缩包中,大家可以直接解压缩后就开始使用,其中FileGenerator在网上没有现成dll,本人编译后将其取出,放在了压缩包中,一直在苦苦找寻的朋友这次可以拿来直接用了:) 本压缩包中Reflector.exe已经升级为最新的5.0版本,具体的使用方法不多说了,只简单介绍一下本压缩包的使用步骤: 先下载本压缩包并解压缩,运行其中的Reflector.exe(主程序),初次运行会弹出错误提示对话框,因为引用的两个插件DLL是按照我本地实际情况配置的,所以你还需要根据你的实际情况来从新配置一下,方法很简单,我们拿引用FileGenerator.dll来做一个范例, 首先介绍一下Filegenerator,FileGenerator插件的作用是:根据dll文件,把里面的源文件导出成文件,导出来的文件除了没有注释,变量名也变了,其它的可谓是没有差别。对于一些比较好的控件,如果不是开源的,完全可以导出成文件,然后自己加上注释,少许修改,很好的利用起来。(不开源的dll,用起来也不放心啊) 具体的初始化设置方法:点击View->Add-Ins...,弹出一个窗口,然后点击Add->选择文件夹里面的:"FileGenerator.dll",点击close. 然后回到Reflector窗口,Tool->Generator File(s)... 右边就出现了插件的窗口,选中左边的dll文件,点击右边的导出文件,源代码就全部导出来了! 另一个插件Reflector.FileDisassembler.dll设置方法也和这个一样,另外再提供一些Reflector的相关插件下载,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值