zoukankan      html  css  js  c++  java
  • 运用Mono.Ceci类库修改.NET程序集 走上破解软件的道路

    运用Mono.Ceci类库修改.NET程序集 走上破解软件的道路

    代码注入在C++时代很流行,主要是对现有的程序做一些修改,以达到预期的目的。一部分的破解程序,注册机也是借助于此方法,让被注入的程序绕过验证,达到破解的目录。在.NET中,借助于Mono.Cecil程序集,注入代码也相当容易。请看下面的代码,将要被注入的程序:

    using System;
    
    namespace Victim
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
                Console.ReadLine();
            }
        }
    }

    把上面的程序编译成一个程序集Victim,执行程序,它会在控制台出版Hello,world。

    下面我做一个新的程序,它修改上面的程序集,在Program类型中定义一个新的Test方法,修改Main方法调用我注入的Test方法。

    先添加对程序Mono.cecil的引用。

    using System;
    using Mono.Cecil;
    using Mono.Cecil.Cil;

    现在,开始加载程序集

    AssemblyDefinition asm= AssemblyFactory.GetAssembly("Victim.exe");

    添加返回值为void类型的Test方法

    //Declare returntype "void"
    TypeReference returntype = asm.MainModule.Import(typeof(void));
    //Define Methodsignature "private static void Test()"
    MethodDefinition testmethod = new MethodDefinition("Test",MethodAttributes.Private|MethodAttributes.Static, returntype);

    Test方法的访问级别为private,static

    给Test方法增加方法体,参考下面的代码写法

    //Push string onto the stack
    Instruction msg = testmethod.Body.CilWorker.Create(OpCodes.Ldstr, "Hello from Test()");
    //Import external method reference to Console.WriteLine()
    MethodReference writeline = asm.MainModule.Import(typeof(Console).GetMethod("WriteLine",new Type[]{typeof(string)}));

    加载常量为方法的签名,在控制台上打印出来

    这种写法,与MSIL代码一致,C#代码被翻译成MSIL,生成的代码就是这样的。

    最后生成Test方法,代码如下

    //Generate stack-push
    testmethod.Body.CilWorker.Append(msg);
    //Generate call to WriteLine()
    testmethod.Body.CilWorker.InsertAfter (msg,testmethod.Body.CilWorker.Create(OpCodes.Call,writeline));
    //Generate return
    testmethod.Body.CilWorker.Append (testmethod.Body.CilWorker.Create (OpCodes.Ret));
    asm.MainModule.Inject(testmethod, asm.MainModule.Types["Victim.Program"]);

    最后,修改程序,让它调用被注入的Test方法

      //Get Method reference with Name test,
                MethodReference testmethod_ref = null;
                foreach (MethodDefinition mdef in asm.MainModule.Types["Victim.Program"].Methods)
                {
                    if (mdef.Name == "Test")
                    {
                        testmethod_ref=asm.MainModule.Import(mdef);
                    }
    
                }
    
                //Create call to the reference
                Instruction call_test = testmethod.Body.CilWorker.Create(OpCodes.Call, testmethod_ref);
             //Insert reference
             asm.EntryPoint.Body.CilWorker.InsertBefore (asm.EntryPoint.Body.Instructions[0],call_test);

    保存程序集到磁盘文件中

    AssemblyFactory.SaveAssembly(asm, "patched.exe");
     

    现在,最初始的程序集代码看起来是这样的

    using System;
    
    namespace Victim
    {
        class Program
        {
            static void Main(string[] args)
            {
                Test();
                Console.WriteLine("Hello World!");
                Console.ReadLine();
            }
    
            private static void Test()
            {
                Console.WriteLine("Hello from Test()");
    
            }
        }
    }

    可以用Reflector来查看生成的Patched.exe,应该与这里的一致。

    如果被修改的方法,是许可验证,或是注册算法验证,这一方便可以直接把它的指令清空,另存为一个程序集文件,达到绕过验证的目的。

     
     
  • 相关阅读:
    【转】WCF入门教程六[一个简单的Demo]
    【转】WCF入门教程五[WCF的通信模式]
    【转】WCF入门教程四[WCF的配置文件]
    【转】WCF入门教程三[WCF的宿主]
    【转】WCF入门教程二[WCF应用的通信过程]
    【转】WCF入门教程一[什么是WCF]
    【转】浅谈.net remoting 与webservice
    【转】Microsoft .Net Remoting之Remoting事件处理全接触
    egret升级经验记录
    cmder小技巧
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3168624.html
Copyright © 2011-2022 走看看