让Reflector的反编译不能正常工作

用过Reflector的都知道,这是一个功能非常强大的反编译工具,几乎能够将你的.net代码完全还原,并且能够立即重新
编译运行,本文提供了一个方法让Reflector的反编译不能正常工作,据研究,目前很多代码混淆工具已经使用了该技术,
为了便于理解,我将该方法姑且叫做代码顺序扰乱技术。
下面来研究一个具体的例子:
1。StrConv.cs源代码如下:

using System;
public class StrTool
{
 
public static void Main(String[] argv){
  String s1
="\ud7d1\udec3\ue5b9\ueca6";
  
int num=0x4308d77e;
  Console.WriteLine(conv(s1,num));
 }


 
public static string conv(string str, int num)
 
{
    
char[] chArray1 = str.ToCharArray();
    
for (int num1 = 0; num1 < chArray1.Length; num1++)
    
{
    chArray1[num1] 
= (char)(chArray1[num1] - num);
    num 
+= 0x6fd;
    }

    
return new string(chArray1);
 }


}



运行csc strconv.cs编译运行,结果是SHA1,程序的功能是简单的字符串加密处理。

用Reflector打开strconv.exe文件,发现所有代码可以准确的反编译为c#。

2。用ildasm反编译,导出IL文件StrConv.il,打开找到conv方法的代码如下:
.method public hidebysig static string  conv(string str,
                                             int32 num) cil managed
{
  // 代码大小       65 (0x41)
  .maxstack  4
  .locals init (char[] V_0,
           int32 V_1,
           string V_2)
  IL_0000:  ldarg.0
  IL_0001:  callvirt   instance char[] [mscorlib]System.String::ToCharArray()
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.0
  IL_0008:  stloc.1
  IL_0009:  br.s       IL_0013
  IL_000b:  ldloc.0
  IL_000c:  ldloc.1
  IL_000d:  br         IL_0027
  IL_0012:  stloc.1
  IL_0013:  ldloc.1
  IL_0014:  ldloc.0
  IL_0015:  ldlen
  IL_0016:  conv.i4
  IL_0017:  blt.s      IL_000b
  IL_0019:  ldloc.0
  IL_001a:  newobj     instance void [mscorlib]System.String::.ctor(char[])
  IL_001f:  stloc.2
  IL_0020:  br.s       IL_003f
  IL_0022:  br         IL_003f
  IL_0027:  ldloc.0
  IL_0028:  ldloc.1
  IL_0029:  ldelem.u2
  IL_002a:  ldarg.1
  IL_002b:  sub
  IL_002c:  conv.u2
  IL_002d:  stelem.i2
  IL_002e:  ldarg.1
  IL_002f:  ldc.i4     0x6fd
  IL_0034:  add
  IL_0035:  starg.s    num
  IL_0037:  ldloc.1
  IL_0038:  ldc.i4.1
  IL_0039:  add
  IL_003a:  br         IL_0012
  IL_003f:  ldloc.2
  IL_0040:  ret
} // end of method StrTool::conv

下面将上面的代码顺序扰乱编排如下,中间夹了几个跳转指令br
.method public hidebysig static string
          conv(string str,
               int32 num) cil managed
  {
    // 代码大小       50 (0x32)
    .maxstack  4
    .locals init (char[] V_0,
             int32 V_1,
             string V_2)
    IL_0000:  ldarg.0
    IL_0001:  callvirt   instance char[] [mscorlib]System.String::ToCharArray()
    IL_0006:  stloc.0
    IL_0007:  ldc.i4.0
    IL_0008:  stloc.1
    IL_0009:  br.s       IL_0021

    IL_000b:  ldloc.0
    IL_000c:  ldloc.1
    //开始跳转
    br IL_000d
   

    IL_0020:  stloc.1
    IL_0021:  ldloc.1
    IL_0022:  ldloc.0
    IL_0023:  ldlen
    IL_0024:  conv.i4
    IL_0025:  blt.s      IL_000b

    IL_0027:  ldloc.0
    IL_0028:  newobj     instance void [mscorlib]System.String::.ctor(char[])
    IL_002d:  stloc.2
    IL_002e:  br.s       IL_0030
    br IL_0030

    //***移动过来的代码
    IL_000d:  ldloc.0
    IL_000e:  ldloc.1
    IL_000f:  ldelem.u2
    IL_0010:  ldarg.1
    IL_0011:  sub
    IL_0012:  conv.u2
    IL_0013:  stelem.i2
    IL_0014:  ldarg.1
    IL_0015:  ldc.i4     0x6fd
    IL_001a:  add
    IL_001b:  starg.s    num
    IL_001d:  ldloc.1
    IL_001e:  ldc.i4.1
    IL_001f:  add
    //***返回
    br IL_0020

    IL_0030:  ldloc.2
    IL_0031:  ret
  } // end of method StrTool::conv

修改完毕,保存。大家可以看到只是简单的将代码顺序移动了一下,没有其他任何改变。
用ilasm重新组装ilasm strconv.il成新的strconv.exe

3.重新运行结果正常。然后用Reflector打开strconv.exe文件,反编译conv方法为C#,这时就出现错误了。
System.InvalidOperationException: Invalid branching statement for condition expression with target offset 0027.
   at _127._4(Int32 )
   at _127._1(Int32 )
   at _127._1(Int32 , Int32 )
   at _127._1(IMethodDeclaration , IMethodBody )
   at _123.VisitMethodDeclaration(IMethodDeclaration value)
   at _146._1(Boolean )
不信大家可以试试!
 
本文只是简单演示了这种代码处理的方法,如果多次移动代码,那么要想还原就更加复杂了。
对于这种问题,Reflector在将来的版本看会不会解决,不过目前最新版本仍然不能处理该问题。

posted @ 2005-02-28 17:26  在路上...  阅读(6694)  评论(5编辑  收藏  举报