久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

.NET方法注入

 Jcstone 2013-05-16

.NET方法注入

Uncategorized, by Zen.

最近幫朋友做個(gè)東西,,由于歷史原因,,有一些文件沒(méi)有代碼,,但是又需要修改,。這就需要干吃力不討好的事情了——反編譯,。Google了一圈,,發(fā)現(xiàn).NET平臺(tái)比較流行的也就是mono項(xiàng)目里的神器——Cecil了。原沒(méi)Java平臺(tái)的Javassist用起來(lái)里面爽,,這里是一個(gè)應(yīng)用,。最不爽的是Cecil官方基本沒(méi)什么文檔,只有一個(gè)非常簡(jiǎn)單的介紹和示例,。網(wǎng)上相關(guān)的文章也都是基于0.6版本的,,不幸中大幸就是官方出了文檔說(shuō)明了0.6和0.9之間的差別了。Cecil非常讓人不爽的一點(diǎn)是不能直接插入或修改C#代碼,,只能插入和修改IL代碼,,悲摧的。

reflector之前有個(gè)非常強(qiáng)悍的插件叫Reflexil,,也是基于Cecil實(shí)現(xiàn)的,,可以非常方便地刪除,重命名,,注入方法的,,可惜和新版的reflector不兼容了。再說(shuō)reflector開(kāi)始收費(fèi)了,,之前的免費(fèi)版本也不能用了。這時(shí)SharpDevelopILSpy就應(yīng)運(yùn)而生了,可惜剛出來(lái)沒(méi)多久,,相關(guān)的插件很少,。好吧,其實(shí)只有兩個(gè),,一個(gè)還不能用,,另一個(gè)也沒(méi)試。廢話不多說(shuō)了,,下面進(jìn)入正題,。


由于注入方法需要通過(guò)IL代碼來(lái)實(shí)現(xiàn)。下面這個(gè)方法可以把執(zhí)行過(guò)程打印出來(lái),,幫助進(jìn)行下面的操作,。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void PrintTypes(string fileName)
{
    var asm = AssemblyDefinition.ReadAssembly(fileName);
    foreach (TypeDefinition type in asm.MainModule.Types)
    {
        if (type.Name.Equals("<Module>"))
            continue;
        Console.WriteLine("ClassName is : {0}", type.Name);
        foreach (MethodDefinition method in type.Methods)
        {
            Console.WriteLine("{0} .maxstack {1}", method.FullName, method.Body.MaxStackSize);
            foreach (var ins in method.Body.Instructions)
            {
                Console.WriteLine("L_{0}: {1} {2}", ins.Offset.ToString("x4"),
                    ins.OpCode.Name,
                    ins.Operand is String ? String.Format("\"{0}\"", ins.Operand) : ins.Operand);
            }
        }
        Console.WriteLine("============================");
    }
}

新建一個(gè)工程,生成TestCecil.dll供測(cè)試

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
 
namespace TestCecil
{
    public class Class1
    {
        public void Test()
        {
            string t = "test_xxxx";
            t = t.Replace("_", ".");
            Console.WriteLine(t);
        }
 
        public void Test1(string content)
        {
            Console.WriteLine(content);
        }
    }
}

在已有方法中注入新的操作的過(guò)程

1
2
3
4
5
var processor = method.Body.GetILProcessor();
var newInstruction = processor.Create(OpCodes.Call, someMethodReference);
var firstInstruction = method.Body.Instructions[0];
 
processor.InsertBefore(firstInstruction, newInstruction);

具體示例,,在類TestCecil.Class1Test方法中的第一行,,打印字符I am a test message !!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main(string[] args)
{
    var asm = AssemblyDefinition.ReadAssembly("TestCecil.dll");
    var type = asm.MainModule.GetType("TestCecil.Class1");
    var method = type.Methods[0];
    var processor = method.Body.GetILProcessor();
    var ldstr = processor.Create(OpCodes.Ldstr, "I am a test message !!!");
    var call = processor.Create(OpCodes.Call,
        method.Module.Import(
            typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })));
 
    processor.InsertBefore(method.Body.Instructions[0], ldstr);
    processor.InsertAfter(method.Body.Instructions[0], call);
    asm.Write("TestCecil.patch.dll");
    PrintTypes("TestCecil.patch.dll");
}

在類TestCecil.Class1中注入Test2(string)方法

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    var asm = AssemblyDefinition.ReadAssembly("TestCecil.dll");
    var module = asm.Modules[0];
    var type = module.Types.FirstOrDefault(m => m.Name == "Class1");
    var method = new MethodDefinition("Test2", MethodAttributes.Public,module.Import(typeof(void)));
    type.Methods.Add(method);
    method.Parameters.Add(new ParameterDefinition(module.Import(typeof(string))));
    asm.Write("TestCecil.patch.dll");
    PrintTypes("TestCecil.patch.dll");
}

移除一個(gè)現(xiàn)有方法

1
2
3
4
5
6
7
8
public static void RemoveMethod(TypeDefinition self, string methodName)
{
    var method = self.Methods.FirstOrDefault(m => m.Name == methodName);
    if (method != null)
    {
        self.Methods.Remove(method);
    }
}

具體的使用方法,移除類TestCecil.Class1中的Test方法

1
2
3
4
5
6
7
8
static void Main(string[] args)
{
    var asm = AssemblyDefinition.ReadAssembly("TestCecil.dll");
    TypeDefinition type = asm.MainModule.GetType("TestCecil.Class1");
    RemoveMethod(type, "Test");
    asm.Write("TestCecil.patch.dll");
    PrintTypes("TestCecil.patch.dll");
}

這里只是一些簡(jiǎn)單的示例,,常見(jiàn)使用都包括了,。不過(guò)這種操作只能用來(lái)救急用的,偶爾干干還可以,,要是在生產(chǎn)環(huán)境中用此方法會(huì)死人的-_-||

--EOF--

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多