首页 > 养蜂技术 > 软件开发 > 其他

养蜂技术正文

MaxtoCode对.Net程序加密的原理及解密探讨(一)

湖北天马养蜂场2010-03-16 10:59:14其他2320

这里研究的对象是MaxtoCode3.1试用版.这里只探讨程序代码的加密.

.Net程序代码的加密过程如下:

1.运行ildasm将程序集反编译成il代码文件.

2.对IL代码文件进行处理.(*)

3.运行ilasm将IL代码文件编译成程序文件.

4.直接对程序文件中的il字节码加密.(**)

粗体表示的2,4是关键步骤.

我们先来看看第四步.这一步就是加密的关键步骤,这里就是使用MaxtoCode的加密算法对程序代码进行加密。

显然,对于破解来说最直接直观的方法就是对其第四步的逆向解密。

如果从这个方向去破解解密加密过的程序,那就像MaxtoCode号称的那样MAXTOCODE的强度建立在加密算法之上。

理论上方法是可行的,但是工作量是非常大的。

那么我们还有其它的路可行呢?

现在来看看第二步MaxtoCode都做了什么。

vs2003建一个最简单的winform程序,然后用MaxtoCode加密试试。我们将第三步之后,第四步之前的exe文件拿来研究。这个时候的exe程序代码是还没有被加密的。可以reflector。

看看这个exe和我们直接的exe有什么区别:

1.增加了一个类InFaceMaxtoCode.

2.类都被增加了一个静态构造函数,在这个函数里面调用了InFaceMaxtoCode的一个静态函数Startup。

3.类的原有构造函数里面也增加了调用InFaceMaxtoCode.Startup的语句。

从这些来看,MaxtoCode的目的是要确保InFaceMaxtoCode.Startup在程序中能够最早的运行。

这个行为和win32程序加壳很像,一般壳都是加密程序代码,然后修改程序的启动入口,首先执行壳的代码,完成程序的解密,然后再执行程序。一般壳有一个特点:加密是对整个程序,启动时也是整个程序完全解密,然后再执行。(我也见到过一个很特别的壳,程序是部分解密的,软件注册算法的那一块,是执行一部分解密一部分,然后之前解密的又被垃圾信息填充了。)

对于壳只要我们找对了时间和地点,就能从内存中得到我们需要的东西。

那么MaxtoCode加密后的。Net程序呢?湖北天马养蜂场,加我们的微信一起学养蜂。

先来看看MaxtoCode的加密方式。用ildasm反编译加密后的程序,会报很多错误,这是正常的,从生产的IL文件看,各个类,函数都还在,只是函数体里面是只有ildasm的错误信息。显然是加密后的代码无法反编译。MaxtoCode对。Net程序的加密不是对程序整体的,而只是对函数体加密,程序类结构不变。有一点我们是很清楚的,加密后的程序要能够正常运行,在运行时肯定是需要解密的。而解密的关键就在InFaceMaxtoCode.Startup里面。

现在我们来看看InFaceMaxtoCode.Startup里面究竟做了什么。InFaceMaxtoCode类的代码如下:

usingSystem;
usingSystem.IO;
usingSystem.Reflection;
usingSystem.Runtime.InteropServices;
usingSystem.Text;

publicclassInFaceMaxtoCode
{
    
staticInFaceMaxtoCode()
    {
        InFaceMaxtoCode.started
=false;
    }

    [DllImport(
"MRuntime3.dll",EntryPoint="CheckRuntime",CharSet=CharSet.Unicode,SetLastError=true,ExactSpelling=true)]
    
privatestaticexternintA______();
    [DllImport(
"KERNEL32.DLL",EntryPoint="GetModuleHandleA",CharSet=CharSet.Ansi,SetLastError=true,ExactSpelling=true)]
    
privatestaticexternintB______(stringx13d52f7d8e232e61);
    
privatestaticstringByteToString(byte[]x5fc6100148519126)
    {
        
returnEncoding.ASCII.GetString(x5fc6100148519126);
    }

    [DllImport(
"MRuntime3.dll",EntryPoint="MainDLL",CharSet=CharSet.Ansi,SetLastError=true,ExactSpelling=true)]
    
privatestaticexternboolC______(intx19218ffab70283ef,intxe7ebe10fa44d8d49);
    [DllImport(
"KERNEL32.DLL",EntryPoint="SetEnvironmentVariableA",CharSet=CharSet.Ansi,SetLastError=true,ExactSpelling=true)]
    
privatestaticexternboolD______(stringx427bb0e14ed9e9b1,stringx84ee6c5b88919f4c);
    
publicstaticvoidStartup()
    {
        
if(!InFaceMaxtoCode.started)
        {
            
stringtext1="";
            
stringtext2="MRuntime3.dll";
            
if(AppDomain.CurrentDomain.RelativeSearchPath!=null)
            {
                
if(AppDomain.CurrentDomain.RelativeSearchPath.IndexOf(@":\")!=-1)
                {
                    text1
=AppDomain.CurrentDomain.RelativeSearchPath;
                }
                
else
                {
                    text1
=AppDomain.CurrentDomain.BaseDirectory+AppDomain.CurrentDomain.RelativeSearchPath;
                }
            }
            
else
            {
                text1
=AppDomain.CurrentDomain.BaseDirectory;
            }
            
stringtext3=Environment.GetEnvironmentVariable("path");
            
if(text3.IndexOf(text1)==-1)
            {
                InFaceMaxtoCode.D______(
"path",text3+";"+text1.Replace("/",@"\"));
            }
            
if(text1.Substring(text1.Length-1,1)==@"\")
            {
                text1
=text1;
            }
            
else
            {
                text1
=text1+@"\";
            }
            
if(File.Exists(text1+text2)&&!File.Exists(Path.GetTempPath()+text2))
            {
                File.Copy(text1
+text2,Path.GetTempPath()+text2);
            }
            
if(text3.IndexOf(Path.GetTempPath())==-1)
            {
                InFaceMaxtoCode.D______(
"path",text3+";"+Path.GetTempPath().Replace("/",@"\"));
            }
            
intnum1=5;
            num1
=InFaceMaxtoCode.A______();
            
if(num1==0)
            {
                
intnum2=InFaceMaxtoCode.B______(text2);
                
intnum3=InFaceMaxtoCode.B______(Assembly.GetExecutingAssembly().Location);
                InFaceMaxtoCode.started
=InFaceMaxtoCode.C______(num2,num3);
            }
            
else
            {
                
//一堆垃圾代码,报告启动错误信息的。
            }
        }
    }


    
privatestaticboolstarted;
}