以编程方式反汇编CIL

时间:2012-02-12 23:14:04

标签: c# .net f# metaprogramming

我可以将指令编译成字节码,甚至可以轻松地执行它们,但我发现提取CIL的唯一函数是GetILAsByteArray,顾名思义,它只返回字节而不是CIL指令。

那么如何以编程方式在.NET上反汇编CIL?

请注意,我不希望结果以人类可读的形式出现。我想编写元程序来操纵从其他程序生成的CIL。

4 个答案:

答案 0 :(得分:9)

Mono Cecil库 - http://www.mono-project.com/Cecil应该做你需要的,我知道它至少用于一个.Net profiler

答案 1 :(得分:8)

你可以使用GetILAsByteArray方法中的字节数组得到合理的结果,但是你需要自己编写字节的解析(如果你不想依赖第三方库)。

数组的结构是有一个或两个字节标识指令操作数后面的指令(无论是什么,4字节标记或8字节数)。

要获取代码,您可以查看OpCodes中的System.Reflection.Emit结构(MSDN)。如果枚举所有字段,则可以非常轻松地构建查找表以读取字节:

// Iterate over all byte codes to build lookup table
for fld in typeof<OpCodes>.GetFields() do
  let code = fld.GetValue(null) :?> OpCode
  printfn "%A (%d + %A)" code.Name code.Size code.OperandType

code.Value属性为您提供代码的{​​{1}}或byte值。 int16属性告诉您这是1字节还是2字节代码,code.Size属性指定代码后面的参数(字节数和含义explained on MSDN)。我不记得你究竟需要处理像引用OperandType的标记这样的东西,但我想你能够弄明白这一点!

答案 2 :(得分:5)

使用Cecil的一个有趣的替代方案是恢复AbsIL项目。塞西尔写得很好,使用得很好,但如果你用F#编写它,可能不是你如何解决问题。 Absil是一个与F#同时启动的项目,允许OCaml和F#读写IL,它自从被F#项目过后,现在只是F#编译器的后端。然而,读取和写入IL的代码仍然存在,并且理论上可以与F#编译器分离并且可以自己制作成可用的库。将Absil代码与F#编译器的其余部分分开并不是完全无足轻重的,但如果您有一些空闲时间和一定的决心,则应该可以实现。如果你真的很勇敢,你可能也想看看交叉编译到OCaml。

答案 3 :(得分:2)

我用Mono Cecil项目进行了一些IL操作。它非常简单。