Posted by huboy on 2006, 09 23, 1:07 PM. Filed in .NET(C#)
这几天,工作特别忙,没空抽出时间来写文章,粗糙之作,还请见谅。
1.名称混淆 - 反混淆
名称混淆返混淆,基本上是不太可能的事,因为以前的名称已经换掉了,也没有第二个名称备份表,所以根本无法还换。不过,可以把不可见字符转换为可见字符,长字符串换成短字符串。
有两种方法可以做处理:
1. 在MetaData中有一个区域叫做 _STRING 它存放了所有名称字符串,只要修改这里的内容,即可,此方法需要对元数据结构特别熟悉
2. 如果你对元数据不了解,没关系,你可以用ILDasm把混淆后的程序集反编译,然后一个一个的对应改过来,再用ilAsm编译,一样可以达到反混淆的作用。其实,对名于名称来说,真的没有多大用处,不用反混淆也行,免得浪费自己的时间。
2.流程混淆 - 反混淆
流程混淆,在上面已经给出例子。它才是有用的一种混淆方式。它改变流程的存放序顺,从而达到静态反编译的功能。(名称混淆还是可以反编译)不过,不管怎样,他没有办法去阻止读取IL,这就是流程混淆的天生不足。我们来看
看如何对流程反混淆吧。
还是以上面的例子进行操作。
首先特别说明一下: br.s 行号 br 行号 都是强行跳转指令,而流程混淆主要是得用这样的语句进行逻辑连接的。所以,我们就需要对照着被混淆过的代码,跟着一句一句的逻辑关系,把语句拉出来重新组合。
组合出来后,代码如下:
L_0000: newobj instance void [mscorlib]System.Random
::.ctor()
L_0005: stloc.1
L_0006: ldstr ""
L_0021: stloc.2
L_0022: ldc.i4.0
L_0023: stloc.0
L_0024: br.s L_0032
L_0026: ldloc.2
L_0027: ldarg.1
L_0028: ldloc.1
L_0029: callvirt instance float64 [mscorlib]System.Random
::NextDouble()
L_002e: ldarg.2
L_002f: conv.r8
L_000d: mul
L_000e: conv.i4
L_000f: ldelem.u2
L_0010: box char
L_0015: call string string::Concat(object, object)
L_001a: stloc.2
L_001b: ldloc.0
L_001c: ldc.i4.1
L_001d: add
L_001e: stloc.0
L_0032: ldloc.0
L_0033: ldarg.3
L_0034: ble.s L_0026
L_0036: ldloc.2
L_0037: ret
其实,反流程混淆也相当的容易,只要按照执行流程加入特定的条件即可以得到代码的序顺。
为此,我特别写了一个反流程混淆的工具(Deflow)。将上面的代码反混淆后,得到如下代码:
L_0000: newobj instance void [mscorlib]System.Random::.ctor()
L_0001: stloc.1
L_0002: ldstr ""
L_0003: stloc.2
L_0004: ldc.i4.0
L_0005: stloc.0
L_0006: br.s L_0017
L_0007: ldloc.2
L_0008: ldarg.1
L_0009: ldloc.1
L_000A: callvirt instance float64 [mscorlib]System.Random::NextDouble()
L_000B: ldarg.2
L_000C: conv.r8
L_000D: mul
L_000E: conv.i4
L_000F: ldelem.u2
L_0010: box char
L_0011: call string string::Concat(object, object)
L_0012: stloc.2
L_0013: ldloc.0
L_0014: ldc.i4.1
L_0015: add
L_0016: stloc.0
L_0017: ldloc.0
L_0018: ldarg.3
L_0019: ble.s L_0007
L_001A: ldloc.2
L_001B: re