蓝字 江湖评谈设为关注
前言
.NET9里面,一串十六进制的代码,如下:
0x0,0x28,0xe,0x0,0x0,0xa,0x0,0x2a
你会知道它表示的是什么吗?答案是以下C#代码,也即是启动完整代的垃圾回收。
C#代码:
GC.Collect();
十六进制在内存里面分解成二进制,传送到CPU上执行。C#源码则被Roslyn Compile成MSIL。MSIL在内存里面即是十六进制,被JIT导入之后才会进行ASM Compile。一些细节可以参考:罕见的技术:MSIL的机器码简析
解析
拆解下以上十六进制
0x0 //表示空指令
0x28 0xe 0x0 0x0 0xa //表示call指令调用Collect函数
0x0 //空指令
0x2a //返回
继续看下,假如说调用
int a=5;
int b=5;
int c = a + b;
,它的MSIL十六进制如下:
0x0,0x1b,0xa,0x1b,0xb,0x6,0x7,0x58,0xc,0x2
再看:
static void Main(string[] args)
{
Console.WriteLine("Call Main");
}
它的十六进制是:
0x0, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x0d, 0x00, 0x00, 0x0a, 0x00, 0x2a
工具
这种单个的十六进制,如果以人的思维来看,是非常晦涩的。所以它如果需要转换成完整的C#代码,可以借助一些工具来完成。你只需要输入十六进制数组,让工具给你进行解析即可。
Dnspy/ILSpy等等工具是可以反编译C#代码,但它的缺陷是对于十六进制转IL过于单薄。
所以这里可以借助非托管DaoChuRef.dll来完成。
internal class Program
{
[ ]
private extern static void dumpILRange(byte[] codeAddr, int codeSize);
static void Main(string[] args)
{
/*
例子1:
十六进制:0x0, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x0d, 0x00, 0x00, 0x0a, 0x00, 0x2a
C#代码:static void Main(string[] args){ Console.WriteLine("Call Main");}
例子2:
十六进制:0x0,0x1b,0xa,0x1b,0xb,0x6,0x7,0x58,0xc,0x2
C#代码:int a=5; int b=5; int c = a + b;
例子3:
十六进制: 0x0,0x28,0xe,0x0,0x0,0xa,0x0,0x2a
C#代码: GC.Collect();
*/
byte[] bt = { 0x0, 0x28, 0xe, 0x0, 0x0, 0xa, 0x0, 0x2a };
dumpILRange(bt, bt.Length);
Console.ReadLine();
}
}
DaoChuRef.dll可在公众号后台回复:IL获取。