教你怎么用Mono Cecil - 动态注入 (注意代码的注释)
原文 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)
使用 Mono Cecil 进行反编译:using Mono.Cecil;
using Mono.Cecil.Cil; //...... AssemblyDefinition asm = AssemblyFactory.GetAssembly("MyLibrary.dll");
foreach (TypeDefinition type in asm.MainModule.Types)
{
if (type.Name == "Class1") //获取类名
{
foreach (MethodDefinition method in type.Methods) 遍历方法名称
{
Console.WriteLine(".maxstack {0}", method.Body.MaxStack);
foreach (Instruction 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);
}
}
}
}
输出: .maxstack 8
L_0000: nop
L_0001: ldstr "Hello, World!"
L_0006: call System.Void System.Console::WriteLine(System.String)
L_000b: nop
L_000c: ret nop ----> ldstr ----> call ----> nop ----> ret ----> =================》下面我们开始进行注入了 AssemblyDefinition asm = AssemblyFactory.GetAssembly("MyLibrary.dll");
foreach (TypeDefinition type in asm.MainModule.Types)
{
if (type.Name == "Class1")
{
foreach (MethodDefinition method in type.Methods)
{
if (method.Name == "Test")
{
foreach (Instruction ins in method.Body.Instructions)
{
if (ins.OpCode.Name == "ldstr" && (string)ins.Operand == "Hello, World!") //如果发现操作数为"Hello, World! ===>改为"Hello, C#!";
{
ins.Operand = "Hello, C#!";
}
}
}
}
}
} AssemblyFactory.SaveAssembly(asm, "Test.dll"); 用 Lutz Roeder's Reflector 打开 Test.dll 看看结果。
.method public hidebysig instance void Test() cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldstr "Hello, C#!"
L_0006: call void [mscorlib]System.Console::WriteLine(string)
L_000b: nop
L_000c: ret
} 达成所愿~~~~~ 完成代码修改以后,我们玩一个更难点的,注入额外的代码。(好像有点做病毒的意思,呵呵~) 任务目标是在 Console.WriteLine("Hello, World!"); 前注入 Console.WriteLine("Virus? No!");,还好这不是真的破坏性代码 AssemblyDefinition asm = AssemblyFactory.GetAssembly("MyLibrary.dll");
foreach (TypeDefinition type in asm.MainModule.Types)
{
if (type.Name == "Class1")
{
foreach (MethodDefinition method in type.Methods)
{
if (method.Name == "Test")
{
foreach (Instruction ins in method.Body.Instructions)
{
if (ins.OpCode.Name == "ldstr" && (string)ins.Operand == "Hello, World!") //关键的地方,找到目的地
{
CilWorker worker = method.Body.CilWorker; Instruction insStr = worker.Create(OpCodes.Ldstr, "Virus? NO!");
worker.InsertBefore(ins, insStr); MethodReference refernce = asm.MainModule.Import(typeof(Console).GetMethod("WriteLine",
new Type[]{typeof(string)})); Instruction insCall = worker.Create(OpCodes.Call, refernce);
worker.InsertAfter(insStr, insCall); Instruction insNop = worker.Create(OpCodes.Nop);
worker.InsertAfter(insCall, insNop); break;
}
}
}
}
}
}
用反射测试一下修改后的程序集。
AssemblyFactory.SaveAssembly(asm, "Test.dll"); Assembly testAssembly = Assembly.LoadFrom("Test.dll");
Type class1Type = testAssembly.GetType("MyLibrary.Class1");
Object o = Activator.CreateInstance(class1Type);
class1Type.InvokeMember("Test", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, o, null);4. 获取程序集信息
AssemblyDefinition asm = AssemblyFactory.GetAssembly("Learn.Library.dll"); Console.WriteLine("Kind:{0}", asm.Kind);
Console.WriteLine("Runtime:{0}", asm.Runtime);
输出:
Kind:Dll
Runtime:NET_2_0 利用 ModuleDefinition.Image 属性,我们可以获取程序集几乎全部的细节信息。包括 CLIHeader、DebugHeader、DOSHeader、FileInformation、HintNameTable、ImportAddressTable、ImportLookupTable、ImportTable、MetadataRoot、PEFileHeader、PEOptionalHeader、ResourceDirectoryRoot、Sections、TextSection 等。
教你怎么用Mono Cecil - 动态注入 (注意代码的注释)的更多相关文章
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...
- 使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络
目录 一:普通写法 二:注入定义 三:Weave函数 四:参数构造 五:业务编写 六:注入调用 7. 怎么调用别的程序集的方法示例 8. [is declared in another module ...
- 不修改源代码,动态注入Java代码的方法(转)
转自:https://blog.csdn.net/hiphoon_sun/article/details/38707927 有时,我们需要在不修改源代码的前提下往一个第三方的JAVA程序里注入自己的代 ...
- Mono.Cecil
Mono Cecil十分强大,强大到可以静态注入程序集(注入后生成新的程序集)和动态注入程序集(注入后不改变目标程序集,只在运行时改变程序集行为),它甚至可以用来调试PDB MDB调试符号格式文件. ...
- iOS中动态注入JavaScript方法。动态给html标签添加事件
项目中有这样一种需求,给html5网页中图片添加点击事件,并且弹出弹出点击的对应的图片,并且可以保持图片到本地 应对这样的需求你可能会想到很多方法来实现. 1. 最简单的方法就是在html5中添加图片 ...
- Spring Boot动态注入删除bean
Spring Boot动态注入删除bean 概述 因为如果采用配置文件或者注解,我们要加入对象的话,还要重启服务,如果我们想要避免这一情况就得采用动态处理bean,包括:动态注入,动态删除. 动态注入 ...
- spring boot 动态注入bean
方法一 SpringContextUtil public class SpringContextUtil { private static ApplicationContext application ...
- 如何向AcmeAir注入问题代码
为什么要注入问题代码? AcmeAir的常规代码是为了压测测试准备的,所以绝大部分的操作都是可以在几十毫秒中就可以正常返回的.为了向用户展示我们APM工具可以在源代码级别发现系统潜在问题,我们需要在A ...
- 基于Mono.Cecil的静态注入
Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...
随机推荐
- docker基础入门之二
一.docker文件系统: linuxFS包括boot file system 和 root file system boot file system (bootfs),包含bootloader和ke ...
- flexbox 伸缩布局盒
Flexbox(伸缩布局盒) 是 CSS3 中一个新的布局模式,为了现代网络中更为复杂的网页需求而设计. Flexbox 由 伸缩容器 和 伸缩项目 组成.通过设置元素的 display 属性为 ...
- Jquery 遍历数组之grep()方法介绍
grep()方法用于数组元素过滤筛选. grep(array,callback,boolean);方法参数介绍. array ---待处理数组 callback ---这个回调函数用来处理数组中 ...
- oracle 获取系统时间(转)
Oracle中如何获取系统当前时间 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual; ORACLE里获取一个时间的年.季. ...
- js中使用控件名和数组下标方式获取控件的值时失败
在做界面展示时涉及到表单行项目的增加和删除时,我们一帮都使用js的脚本实现表单行的增加和删除,那么在进行表单的提交的时我们会再页面上进行提交数据的初步校验,进行数据的初步校验时,就要动态获取控件的值. ...
- C# 微信公众平台开发(2)-- 微信菜单
上一篇了解微信开发者中心 URL的配置验证: 验证成功后,就可以对获取的接口权限进行操作 自定义菜单接口可实现多种类型按钮,用的比较多的是 1.click:点击推事件 用户点击click类型按钮后,微 ...
- 面试题之java 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 要求不能出现截半的情况
题目:10. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输 ...
- python 10 min系列三之小爬虫(一)
python10min系列之小爬虫 前一篇可视化大家表示有点难,写点简单的把,比如命令行里看论坛的十大,大家也可以扩展为抓博客园的首页文章 本文原创,同步发布在我的github上 据说去github右 ...
- Linux C 实现Ping功能的程序.
ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具.ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这 ...
- PowerShell Remove all user defined variable in PowerShell
When PS scripts executes, it is possibly create much user defined variables. So, sometimes these var ...