考虑以下 .NET 4.5 控制台应用程序:
using System;
namespace ReversingMSIL101
{
class Program
{
static void Main(string[] args) {
if (args.Length > 0 && args[0] == "Secret")
Authenticated();
else
Anonymous();
}
private static void Authenticated() {
Console.WriteLine("Gold for the people!");
}
private static void Anonymous() {
Console.WriteLine("Give them copper ...");
}
}
}
编译并打开 Ildasm 。我们将首先加载可执行文件(文件->打开)。完成后:转储它(文件->转储)。Ildasm 用一个很好的对话框来响应,因为我们想要尽可能多的信息,检查一切!
现在让我们看看我们反汇编的 IL 指令,启动您喜欢的编辑器并打开之前生成的转储。我们对if
语句特别感兴趣,因为它控制提供的密码是否正确;请注意,您可以使用生成的注释轻松发现它。
//000009: if (args.Length > 0 && args[0] == "Secret")
IL_0001: /* 02 | */ ldarg.0
IL_0002: /* 8E | */ ldlen
IL_0003: /* 69 | */ conv.i4
IL_0004: /* 16 | */ ldc.i4.0
IL_0005: /* 31 | 12 */ ble.s IL_0019
IL_0007: /* 02 | */ ldarg.0
IL_0008: /* 16 | */ ldc.i4.0
IL_0009: /* 9A | */ ldelem.ref
IL_000a: /* 72 | (70)000001 */ ldstr "Secret" /* 70000001 */
IL_000f: /* 28 | (0A)000011 */ call bool [mscorlib/*23000001*/]System.String/*01000013*/::op_Equality(string, string) /* 0A000011 */
IL_0014: /* 16 | */ ldc.i4.0
IL_0015: /* FE01 | */ ceq
IL_0017: /* 2B | 01 */ br.s IL_001a
IL_0019: /* 17 | */ ldc.i4.1
IL_001a: /* 00 | */ nop
IL_001b: /* 0A | */ stloc.0
IL_001c: /* 06 | */ ldloc.0
IL_001d: /* 2D | 08 */ brtrue.s IL_0027
我让读者完成逆向和分析指令的任务。我们将继续看最后一个。长话短说:如果第一个参数不是字符串,"Secret"
我们将采用分支并最终在IL_0027
:
IL_0027: /* 28 | (06)000003 */ call void ReversingMSIL101.Program/*02000002*/::Anonymous() /* 06000003 */
很糟糕吧?因此,我们将简单地调整最后一条指令,此外将其替换为brfalse.s
:
IL_001d: /* 2B | 08 */ brfalse.s IL_0027
就是这样,我们完成了!保存文件并打开一个 shell,导航到包含 IL 转储和问题的文件夹,以便将转储ilasm ReversingMSIL101.il
重新组装成一个可执行文件!
现在是验证我们工作的时候了:
C:\Users\dna\Documents\Visual Studio 2012\Projects\ReversingMSIL101\ReversingMSIL101\bin\Debug>ReversingMSIL101.exe IdoNotKnow
Gold for the people!