Mono Cecil十分强大,强大到可以静态注入程序集(注入后生成新的程序集)和动态注入程序集(注入后不改变目标程序集,只在运行时改变程序集行为),它甚至可以用来调试PDB MDB调试符号格式文件。

注:仔细看了下,并不支持“动态”注入,cecil只支持从硬盘加载或从内存读取一个已经被加载了的assembly,然后修改它的副本,最后另存为或者直接调用这个副本。

原程序集并不会发生任何改变,也就是说,如果你要修改一个程序集的行为,那么你必须在原软件加载它之前,修改它,并代替旧的。assembly一旦别加载,cecil是无法修改它的。

若想实现动态注入,动态修改已经被加载了的程序集功能(最典型的就是Unity的游戏,程序集的加载由mono.dll加载,我们比较难去操控它的加载),

可以参考这个教程:Dynamically replace the contents of a C# method?

或者这个开源库:Harmony

他们的原理都是,先用RuntimeHelpers预先从内存中加载原函数,以及要替换掉原函数的注入函数,然后分别获取它们的指针,即它们在内存中的位置,

然后交换它们指针,交换内存空间,即可以实现,替换已经加载了的程序集里的函数内容。

(32位跟64位需要分别处理,因为指针大小不一样,还有这个只支持X86架构,ARM需要另外处理)

       MethodInfo methodToReplace = typeof(Target).GetMethod("targetMethod"+ funcNum, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
MethodInfo methodToInject = typeof(Injection).GetMethod("injectionMethod"+ funcNum, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle); unsafe
{
if (IntPtr.Size == )
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + ;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + ;
#if DEBUG
Console.WriteLine("\nVersion x86 Debug\n"); byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar; int* injSrc = (int*)(injInst + );
int* tarSrc = (int*)(tarInst + ); *tarSrc = (((int)injInst + ) + *injSrc) - ((int)tarInst + );
#else
Console.WriteLine("\nVersion x86 Release\n");
*tar = *inj;
#endif
}
else
{ long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer()+;
long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer()+;
#if DEBUG
Console.WriteLine("\nVersion x64 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar; int* injSrc = (int*)(injInst + );
int* tarSrc = (int*)(tarInst + ); *tarSrc = (((int)injInst + ) + *injSrc) - ((int)tarInst + );
#else
Console.WriteLine("\nVersion x64 Release\n");
*tar = *inj;
#endif
}
}

参考文章:

注:Emit也能跟Mono.Cecil一样动态生成IL,但它貌似只支持PC平台:

Mono.Cecil与.NET Reflection的反射对比

Mono.Cecil的更多相关文章

  1. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  2. Mono.Cecil 初探(一):实现AOP

    序言 本篇文章介绍基于Mono.Cecil实现静态AOP的两种方式:无交互AOP和交互式AOP. 概念介绍 Mono.Cecil:一个可加载并浏览现有程序集并进行动态修改并保存的.NET框架. AOP ...

  3. 基于Mono.Cecil的静态注入

    Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...

  4. 使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络

    目录 一:普通写法 二:注入定义 三:Weave函数 四:参数构造 五:业务编写 六:注入调用 7.  怎么调用别的程序集的方法示例 8. [is declared in another module ...

  5. C# Asp.net中的AOP框架 Microsoft.CCI, Mono.Cecil, Typemock Open-AOP API, PostSharp -摘自网络 (可以利用反射 Attribute 进行面向切面编程 可以用在记录整个方法的Log方面)

    Both Microsoft.CCI and Mono.Cecil are low-level, and don't validate produced assemblies. It takes lo ...

  6. 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)

    原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...

  7. 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)

    原文 教你怎么用Mono Cecil - 动态注入 (注意代码的注释) 使用 Mono Cecil 进行反编译:using Mono.Cecil; using Mono.Cecil.Cil; //.. ...

  8. 使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试

    Unity3D 引擎在  UnityEngine 名字空间下,提供了  Profiler 类(Unity 5.6 开始似乎改变了这个名字空间),用于辅助对项目性能进行测试.以 Android 平台为例 ...

  9. 巧用Mono.Cecil反射加载类型和方法信息

    最近在做服务的细粒度治理,统一管理所有服务的方法.参数.返回值信息.方便后续的各个模块之间的对接和协作. 目前系统中所有的服务,管理到接口契约粒度,即服务接口声明和服务接口实现.要做服务的细粒度治理: ...

随机推荐

  1. uvaLive7303 Aquarium (kruskal)

    题意:给R*C的房间,每个房间被左上-右下或右上-左下的墙分割为两个小房间,将分割移除有一定花费,问使所有小房间联通需要的最小花费 把每个房间分成左右(上下?)两个点,判一判,本来就联通的加零边,一个 ...

  2. 使用ajax实现前后端是数据交互

    ajax的概念 ajax一个前后台配合的技术,它可以让javascript发送http请求,与后台通信,获取数据和信息.ajax技术的原理是实例化xmlhttp对象,使用此对象与后台通信.jquery ...

  3. POJ--2104 K-th Number (主席树模版题)

    题目链接 求区间第k大 #include<iostream> #include<cstring> #include<algorithm> #include<v ...

  4. FastDFS 文件上传工具类

    FastDFS文件上传工具类 import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; imp ...

  5. 区间最深LCA

    求编号在区间[l, r]之间的两两lca的深度最大值. 例题. 解:口胡几种做法.前两种基于莫队,第三种是启发式合并 + 扫描线,第四种是lct + 线段树. ①: 有个结论就是这个答案一定是点集中D ...

  6. 【CF1154】题解

    A 直接模拟即可. B 对数组中的值进行排序去重.发现若去重之后的数组中有大于 3 个数时无解,因为无法找到一个点到数轴上四个点的距离均相等.若去重之后的数组中只有三个值,则判断中间的值是否到两边的值 ...

  7. [ZROJ110][假如战争今天爆发]

    题面 思路 先假设我们已经知道了操作顺序,考虑如何求出时间.用f[i][j]表示前i个物品,第i个加工完了第j台机器所需要的最少的时间.转移的时候就是f[i][j] = max(f[i-1][j],f ...

  8. 【译】4. Java反射——字段

    原文地址:http://tutorials.jenkov.com/java-reflection/fields.html ======================================= ...

  9. 第十四节,TensorFlow中的反卷积,反池化操作以及gradients的使用

    反卷积是指,通过测量输出和已知输入重构未知输入的过程.在神经网络中,反卷积过程并不具备学习的能力,仅仅是用于可视化一个已经训练好的卷积神经网络,没有学习训练的过程.反卷积有着许多特别的应用,一般可以用 ...

  10. Solr7.1--- 单机Linux环境搭建

    应网友的要求,写个关于Linux单机的 首先,把MySQL驱动包和solr7.1安装包上传到服务器,我上传到了自定义的目录/mysoft 执行服务安装脚本 1. 先切换到root用户 2. 解压出脚本 ...