有没有办法在C#中执行一系列IL代码,比如C/C++中的shell代码?
我想创建一个方法,将其转换为IL代码,对其进行模糊处理并存储在一个字节数组中,最后要执行它来解密数组内容并执行IL代码.
例如,这是我的C#代码:
static int MyMethod(string A, int B)
{
B += 10;
if (A.Equals("A"))
B = 0;
return B;
}
Run Code Online (Sandbox Code Playgroud)
现在我将它转换为IL代码:
private static int MyMethod(string A, int B)
{
locals: int local_0,
bool local_1
/* 0000025C 00 */ nop
/* 0000025D 03 */ ldarg_1 // int B
/* 0000025E 1F 0A */ ldc_i4_s 10
/* 00000260 58 */ add
/* 00000261 10 01 */ starg_s arg_1 // int B
/* 00000263 02 */ ldarg_0 // string A
/* 00000264 72 01 00 00 70 */ ldstr "A"
/* 00000269 6F 11 00 00 0A */ callvirt System.String::Equals(string) // returns bool
/* 0000026E 16 */ ldc_i4_0
/* 0000026F FE 01 */ ceq
/* 00000271 0B */ stloc_1 // bool local_1
/* 00000272 07 */ ldloc_1 // bool local_1
/* 00000273 2D 03 */ brtrue_s loc_28
/* 00000275 16 */ ldc_i4_0
/* 00000276 10 01 */ starg_s arg_1 // int B
loc_28:
/* 00000278 03 */ ldarg_1 // int B
/* 00000279 0A */ stloc_0 // int local_0
/* 0000027A 2B 00 */ br_s loc_32
loc_32:
/* 0000027C 06 */ ldloc_0 // int local_0
/* 0000027D 2A */ ret
}
Run Code Online (Sandbox Code Playgroud)
最后这是一个字节数组:
private byte[] ilcode =
{
0x00, 0x03, 0x1F, 0x0A, 0x58, 0x10, 0x01, 0x02, 0x72, 0x01, 0x00, 0x00, 0x70, 0x6F, 0x11, 0x00, 0x0, 0x0A, 0x16,
0xFE, 0x01, 0x0B, 0x07, 0x2D, 0x03, 0x16, 0x10, 0x01, 0x03, 0x0A, 0x2B, 0x00, 0x06, 0x2A
};
Run Code Online (Sandbox Code Playgroud)
Mik*_*ray 22
您将需要使用System.Reflection.Emit命名空间中的基础结构.具体而言,你应该看看的文档对于MethodBuilder.CreateMethodBody其接受表示MSIL指令的字节的阵列.这里有一个完整的例子,但下面是它的使用的简短片段.在这里,我还将创建动态方法的委托.
我会注意到,这只是以非常有限的方式支持,在文档中提到:
目前尚未完全支持此功能.用户无法提供令牌修复和异常处理程序的位置.
问题是IL中用于引用类型,方法,字符串文字等的元数据标记在模块级别得到解决.因此,IL不是完全可移植的,因为您不能从一个模块中的方法中获取任意的原始IL,只是将其放入另一个模块中的另一个方法中.您需要在新模块中使用正确的元数据标记.但是,如果您知道您的IL不包含元数据令牌,则可以执行此操作,但这严重限制了您可以执行的操作.(HT:svick,Simon Svensson)
class Program
{
static void Main(string[] args)
{
// opcodes for pushing two arguments to the stack, adding, and returning the result.
byte[] ilcodes = { 0x02, 0x03, 0x58, 0x2A };
var method = CreateFromILBytes(ilcodes);
Console.WriteLine(method(2, 3));
}
private static Func<int, int, int> CreateFromILBytes(byte[] bytes)
{
var asmName = new AssemblyName("DynamicAssembly");
var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
var module = asmBuilder.DefineDynamicModule("DynamicModule");
var typeBuilder = module.DefineType("DynamicType");
var method = typeBuilder.DefineMethod("DynamicMethod",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int),
new[] { typeof(int), typeof(int) });
method.CreateMethodBody(bytes, bytes.Length);
var type = typeBuilder.CreateType();
return (Func<int, int, int>)type.GetMethod("DynamicMethod").CreateDelegate(typeof(Func<int, int, int>));
}
}
Run Code Online (Sandbox Code Playgroud)
注意使用该RunAndSave选项.这会将动态程序集保存到临时位置的磁盘中.可能更希望使用RunAndCollect哪个只在内存中生成程序集,并允许稍后在对它的所有引用都已死时收集它.不过,也有一些注意事项,以所谓的收藏集,详细说明在这里.
| 归档时间: |
|
| 查看次数: |
2788 次 |
| 最近记录: |