shellcode注入pdf,shellcode是如何生成的

首页 > 经验 > 作者:YD1662022-11-07 08:40:14

前言

用于后开发的.NET仍然存在。它已与大多数C2框架捆绑在一起,移植了通用工具,添加(然后绕过了)AMSI,并且使用很多妙招来启动非托管代码。但是,加载.NET程序集的过程似乎非常一致。

众所周知,像Cobalt Strike中 execute-assembly 这样的工具极大地提高了从内存中加载.NET程序集的可访问性,很多攻击者在Github上发布代码时都以或这或那的方式使用它。基于这种趋势,蓝队自然而然善于寻找遗留在内存中的文件。但是,作为红队,我们仍然发现,不管目标是托管还是非托管进程,在进程内启动.NET代码的方法似乎一成不变。例如,如果我们希望将代码注入到进程中,那么,即使目标已经是加载了CLR的.NET进程,我们通常采用的路径也是相同的:

shellcode注入pdf,shellcode是如何生成的(1)

这已经困扰了我好多年,所以我花了几个晚上研究可以更改签名的潜在方法。我的目标很简单,就是尝试找到一种在.NET进程中直接调用.NET方法的方法,不必费尽心思将Shellcode或rDLL注入非托管空间,而是另辟蹊径,通过CLR接口来加载. NET程序集。(作者写的这个rdll是个什么东东,老夫查了半天没查出来,见笑了……)

这篇文章将探讨实现此目标的一种潜在性,通过利用Windows公开的调试框架,我们可以看到使用调试API在目标进程中调用任意.NET代码所需要的内容。

ICorDebug简介

正如我们大多数人在Visual Studio中所见,.NET公开了强大的调试功能,使人们能够在附加的进程中执行代码:

shellcode注入pdf,shellcode是如何生成的(2)

在我脑海中已初步构建一种在.NET进程中执行特定函数的简单方法,但是,有那么一种方法可以模拟此功能,使得.NET进程中的代码可以执行而不必加载shellcode和全部.NET程序集吗?我所希望的是某种类似 DebuggerEvaluateCSharpInThisprocess 的方法,但是,并不存在。。。又但是,我们可以利用一个文档齐全(尽管非常复杂)的API,然后以编程方式来利用.NET调试的功能。

ICorDebug 是.NET调试的切入点,并提供了很多函数,使我们可以控制.NET进程。让我们从设计一个简单的调试器开始,将其附加到我们选择的进程中,从而开始探索此API。

创建一个调试器

我们要做的第一件事是新建一个ICorDebug实例。使用与当前.NET注入方法完全相同的调用,我们首先选择.NET框架的安装版本:

if ((hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&metaHost)) != S_OK) { return hr; } if ((hr = metaHost->EnumerateInstalledRuntimes(&runtime)) != S_OK) { return hr; } frameworkName = (LPWSTR)LocalAlloc(LPTR, 2048); if (frameworkName == NULL) { return E_OUTOFMEMORY; } while (runtime->Next(1, &enumRuntime, 0) == S_OK) { if (enumRuntime->QueryInterface<ICLRRuntimeInfo>(&runtimeInfo) == S_OK) { if (runtimeInfo != NULL) { runtimeInfo->GetVersionString(frameworkName, &bytes); wprintf(L"[*] Supported Framework: %s\\n", frameworkName); } } }

不同之处在于,一旦我们确定了要使用的运行时间后,就会初始化该 ICorDebug 接口实例;而不是像通常那样,从注入的DLL直接运行.NET代码,然后再请求一个 ICLRRuntimeHost 实例。此处的主要区别在于,我们把要执行的shellcode附加到另一个.NET进程,而不需要将之注入非托管空间再加载CLR那么麻烦。

我们使用以下内容来创建一个 ICorDebug 实例:

// Create our debugging interface ICorDebug *debug; ICorDebugProcess *process; if ((hr = runtimeInfo->GetInterface(CLSID_CLRDebuggingLegacy, IID_ICorDebug, (LPVOID *)&debug)) != S_OK) { return hr; } // Initialise the debugger debug->Initialize(); // Attach to an existing process by PID debug->DebugActiveProcess(1234, false, &process);

现在我们已经初始化了接口,这里暂停一下喝杯茶,然后解释一下此调试框架实际上如何与我们的目标流程交互的。首先看看对所公开的各个组件进行高层次概述:

shellcode注入pdf,shellcode是如何生成的(3)

这乍看之下可能有点抽象(我第一次使用API时,阅读了无数遍文档才看懂),但是值得一提的是,调试器API将首先响应从目标进程触发的调试事件。例如,如果引发异常,例如将新程序集加载到目标中或创建了新线程,我们将收到一个事件。并且,每次触发事件时,我们都有机会与进入“stopped”状态的目标进行交互,然后才最终恢复执行并等待其他事件。

通常,当我们与调试的.NET进程进行交互时,该进程需要处于stopped状态。如果与正在运行的进程进行交互的话,就会报错如下:

shellcode注入pdf,shellcode是如何生成的(4)

首页 1234下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.