请看如下代码:
inta = 123445;
Console.WriteLine(a);
编译(debug版,未优化),运行,输出结果为123445。
使用ILdasm来查看其IL指令。如下:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 21 (0x15)
.maxstack 1
.locals init ([0]int32 a)
IL_0000: nop
IL_0001: ldc.i4 0x1e235
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call void [mscorlib]System.Console::WriteLine(int32)
IL_000d: nop
IL_000e: call int32 [mscorlib]System.Console::Read()
IL_0013: pop
IL_0014: ret
}
可以发现,局部变量a的类型时int32。我们的目标就是将变量a的类型修改为byte,从而使最终的结果产生溢出,这样就可以改变应用程序的行为。
要想修改变量a的类型,必须知道局部变量的类型存储在什么地方。首先让我们来查看一下这个方法的元数据,如下:
Method #1 (06000001) [ENTRYPOINT]
-------------------------------------------------------
MethodName: Main (06000001)
Flags : [Private] [Static] [HideBySig][ReuseSlot] (00000091)
RVA : 0x00002050
ImplFlags : [IL][Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: SZArray String
1 Parameters
(1) ParamToken :(08000001) Name : args flags: [none] (00000000)
可以发现,main方法在RVA为2050处,由于这是一个相对虚拟地址,最好将其转换为在文件中的偏移量,转换方法如下:
第一步,查看.txt节的RVA
第二不,2050减去.txt节的RVA
第三步,用上一步的结果+.txt节在文件中的偏移量。
.txt节的信息如下图:
那么main方法在文件中的偏移量就是0x2050-0x2000+200=250。
现在转到文件偏移量为250处,来查看一下方法体。
注:我使用的是FlexHEX,他可以以16进制方式查看一个文件,他还有许多其他有用的功能,功能很强大。
注:这里的方法体(参考微软CLI metadata文档)由这几部分构成,0x3013,0x0001,0x00000015,0x11000001.0x3013含有一些标记值,这里并不关心他;0x0010是方法栈的槽的个数,这里是一个槽;0x00000015是IL指令的大小,这里是15字节;0x11000001是StandAloneSig元数据,这个值才这里的重点。
可以看到,这个方法的StandAloneSig元数据表的标记值是11000001.现在来查看一下这个元数据表,如下:
可以看到,这个局部变量的签名在#blob流中偏移为4d处。现在转到这个位置来看一下,存储的是什么:
Blob Heap: 248(0xf8) bytes
0,0 : > <
1,8 : b7 7a 5c 56 19 34 e0 89 > z\V 4 <
a,5 : 00 01 01 1d 0e > <
10,3 : 00 00 01 > <
14,3 : 20 00 01 > <
18,2 : 06 08 > <
1b,5 : 20 02 01 1c 18 > <
21,7 : 20 02 12 15 12 19 1c > <
29,5 : 20 01 01 12 15 > <
2f,4 : 20 01 01 0e > <
34,4 : 20 01 01 02 > <
39,5 : 20 01 01 11 51 > Q <
3f,4 : 20 01 01 08 > <
44,4 : 00 01 01 08 > <
49,3 : 00 00 08 > <
4d,3 : 07 01 08 > <
51,4 : 07 02 0d 08
可以看到,偏移量4d处存储的值是07 01 08。07说明这是一个局部变量,01说明有一个局部变量类型,08说明这是一个int32类型的局部变量。现在我们的目的就是将int32修改为byte,byte的编码是04,因此只需要将08修改为04就OK了。
要想修改PE文件,这里使用了FlexHEX软件。现在搜索0107,找到如下我们想要的数据:
只需要将08改成04即可,然后保存。
现在重新运行程序,就会发现,输出的不再是123445,而是53.
在破解的时候,通过修改数据类型来破坏程序的正常执行流程,是非常有意思的事情。假设,源码中有如下一行:
If(password==”sss”)
{
登录….
}
这时候你不用修改任何il指令,不用将逻辑取反,只需要修改一下数据类型,然后在输入的时候输入任意一个相反的数就可以改变程序的执行流程。许多软件都会有权限设置,这些权限有的是bool类型,有的是int类型,篡改它们来修改权限是一件很快意的事情。