.NET/C# 二进制文件中的跟踪方法调用

逆向工程 混淆 。网 C# 仪器仪表
2021-07-06 21:24:58

我有一个严重混淆的 Windows 服务二进制文件。字段、类型和方法被重命名。虽然可以使用 dnSpy 反编译二进制文件,但静态识别重要/有趣的位置仍然非常麻烦。

是否可以动态检测二进制文件以便更深入地了解某些执行路径?我不太了解 CLR 内部原理,但我的理解是,由于 IL 指令的 JIT 编译,检测并不容易。

如果有人对跟踪二进制文件中的执行路径有任何建议,我将非常感谢您的输入。另外,如果有人以前见过类似的混淆方案,请告诉我:

在此处输入图片说明

编辑:样本可以从以下位置下载:https : //gofile.io/?c=qrNky4(非恶意;VPN 软件的一部分)

2个回答

由于 IL 指令的 JIT 编译,检测不容易实现。

嗯,事实恰恰相反。跟踪方法非常简单——如果我们想跟踪字段的使用情况就很困难。.NET 程序集包含可用于检查/修改它们的丰富类型/方法信息。还有一个很棒的库可以做到这一点以及更多 - Mono.Cecil

在这个库的帮助下,我们可以实现你想要的(要点)。

using System;
using System.IO;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;

class TraceIL
{
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("TraceIL.exe <assembly>");
            return;
        }

        string fileName = args[0];
        ModuleDefinition module = ModuleDefinition.ReadModule(fileName);
        MethodReference consoleWriteLine =
            module.ImportReference(typeof(Console).GetMethod("WriteLine", new Type[] {typeof(object)}));
        foreach (TypeDefinition type in module.Types)
        {
            foreach (var methodDefinition in type.Methods)
            {
                var ilBody = methodDefinition.Body;
                var ilProcessor = ilBody.GetILProcessor();

                var firstOp = methodDefinition.Body.Instructions.First();
                var ldstrEntering = Instruction.Create(OpCodes.Ldstr, $"--Entering {methodDefinition.Name}");
                ilProcessor.InsertBefore(firstOp, ldstrEntering);
                var call = Instruction.Create(OpCodes.Call, consoleWriteLine);
                ilProcessor.InsertBefore(firstOp, call);
                var ldstrLeaving = Instruction.Create(OpCodes.Ldstr, $"--Leaving {methodDefinition.Name}");
                var lastOp = methodDefinition.Body.Instructions.Last();
                ilProcessor.InsertBefore(lastOp, ldstrLeaving);
                ilProcessor.InsertBefore(lastOp, call);
            }
        }
        module.Write(Path.GetFileNameWithoutExtension(fileName)+".modified"+Path.GetExtension(fileName));
    }
}

只是为了解释一下发生了什么。对于我们在程序集中找到的每种类型的每个方法,我们都会得到ILProcessor允许我们修改代码的 。有了它,我们只需Console.WriteLine在第一个现有操作码之前插入一个字符串和一个调用,并在方法结束之前插入类似的代码。最后,我们将新的二进制文件保存在同名下并.modified添加。

示例运行:

λ TestApp.exe
Inside Run
Inside Inside
MoreInside
OtherProgramRun

λ TraceIL.exe TestApp.exe

λ TestApp.modified.exe
--Entering Main
--Entering .ctor
--Leaving .ctor
--Entering Run
Inside Run
--Entering Inside
Inside Inside
- -进入 MoreInside
MoreInside
--Entering .ctor
--Leaving .ctor
--Entering OtherProgramRun
OtherProgramRun
--Leaving OtherProgramRun
--Leaving MoreInside
--Leaving Inside
--Leaving Run
--Leaving Main

当然在那里你可以做一些疯狂的事情,比如添加时间戳和/或列表传递的参数等。由于你的样本被混淆了它可能从一开始就不起作用,但我想这段代码并不难根据需要修改.

您可以使用 de4dot ( https://github.com/0xd4d/de4dot ) 对二进制文件进行反混淆。dotnet 二进制文件的静态分析可以通过使用 de4dot 轻松完成,然后使用 ILSpy 创建一个 Visual Studio 项目,然后您可以在 Visual Studio 中分析源代码。您还可以使用 dnSpy,它允许您轻松调试二进制文件。

关于检测,dotnet 二进制文件仍然在运行时运行本机代码,具有所有正常的 Win32 库。您可以使用 Api Monitor ( http://www.rohitab.com/downloads ) 在运行时监控 os api 调用,这是一个很棒的工具,它通过挂钩库和解码参数来工作。

此外,您可以使用 procmon 来显示简单的信息,如文件系统操作、注册表等。

祝你好运