diff --git a/CAPE/AmsiDumper.cpp b/CAPE/AmsiDumper.cpp index 8c202868..e9e34b98 100644 --- a/CAPE/AmsiDumper.cpp +++ b/CAPE/AmsiDumper.cpp @@ -46,6 +46,8 @@ extern "C" void ErrorOutput(_In_ LPCTSTR lpOutputString, ...); extern "C" int DumpMemoryRaw(PVOID Buffer, SIZE_T Size); extern "C" BOOL SetCapeMetaData(DWORD DumpType, DWORD TargetPid, HANDLE hTargetProcess, PVOID Address); +extern "C" __declspec(thread) BOOL t_amsi_active; + HMODULE g_currentModule; STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) @@ -75,6 +77,13 @@ T GetFixedSizeAttribute(_In_ IAmsiStream* stream, _In_ AMSI_ATTRIBUTE attribute) HRESULT AmsiDumper::Scan(_In_ IAmsiStream* stream, _Out_ AMSI_RESULT* result) { + if (t_amsi_active) + { + DebugOutput("AmsiDumper: Skipping dump because active AMSI hook is handling it.\n"); + *result = AMSI_RESULT_NOT_DETECTED; + return S_OK; + } + auto session = GetFixedSizeAttribute(stream, AMSI_ATTRIBUTE_SESSION); auto contentSize = GetFixedSizeAttribute(stream, AMSI_ATTRIBUTE_CONTENT_SIZE); auto contentAddress = GetFixedSizeAttribute(stream, AMSI_ATTRIBUTE_CONTENT_ADDRESS); diff --git a/capemon.vcxproj b/capemon.vcxproj index cc45d7a1..2f9ba1f1 100644 --- a/capemon.vcxproj +++ b/capemon.vcxproj @@ -260,6 +260,7 @@ + diff --git a/capemon.vcxproj.filters b/capemon.vcxproj.filters index 21d30e1d..88739d42 100644 --- a/capemon.vcxproj.filters +++ b/capemon.vcxproj.filters @@ -60,6 +60,9 @@ Source Files + + Source Files + Source Files diff --git a/hook_amsi.c b/hook_amsi.c new file mode 100644 index 00000000..9761fa9f --- /dev/null +++ b/hook_amsi.c @@ -0,0 +1,58 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "hooking.h" +#include "log.h" +#include "misc.h" +#include "CAPE\CAPE.h" + +#define AMSIBUFFER 0x6a +#define AMSISTREAM 0x6b + +__declspec(thread) BOOL t_amsi_active = FALSE; + +HOOKDEF(HRESULT, WINAPI, AmsiScanBuffer, + _In_ PVOID amsiContext, + _In_ PVOID buffer, + _In_ ULONG length, + _In_opt_ LPCWSTR contentName, + _In_opt_ PVOID amsiSession, + _Out_ PVOID result +) { + t_amsi_active = TRUE; + HRESULT ret = Old_AmsiScanBuffer(amsiContext, buffer, length, contentName, amsiSession, result); + t_amsi_active = FALSE; + + LOQ_hresult("amsi", "up", "ContentName", contentName, "Length", length); + + if (g_config.amsidump && buffer != NULL && length > 0) { + SetCapeMetaData(AMSIBUFFER, 0, NULL, NULL); + DumpMemoryRaw(buffer, (SIZE_T)length); + DebugOutput("AmsiScanBuffer: Actively dumped AMSI buffer of size %d at 0x%p.\n", length, buffer); + } + + return ret; +} + +HOOKDEF(HRESULT, WINAPI, AmsiScanString, + _In_ PVOID amsiContext, + _In_ LPCWSTR string, + _In_opt_ LPCWSTR contentName, + _In_opt_ PVOID amsiSession, + _Out_ PVOID result +) { + t_amsi_active = TRUE; + HRESULT ret = Old_AmsiScanString(amsiContext, string, contentName, amsiSession, result); + t_amsi_active = FALSE; + + LOQ_hresult("amsi", "uu", "ContentName", contentName, "String", string); + + if (g_config.amsidump && string != NULL) { + SIZE_T len = (wcslen(string) + 1) * sizeof(wchar_t); + SetCapeMetaData(AMSIBUFFER, 0, NULL, NULL); + DumpMemoryRaw((PVOID)string, len); + DebugOutput("AmsiScanString: Actively dumped AMSI string at 0x%p.\n", string); + } + + return ret; +} diff --git a/hooks.c b/hooks.c index 072a8065..7407f96b 100644 --- a/hooks.c +++ b/hooks.c @@ -189,6 +189,7 @@ hook_t full_hooks[] = { // Script hooks HOOK_SPECIAL(clrjit, compileMethod), + HOOK_SPECIAL(coreclr, compileMethod), HOOK_SPECIAL(urlmon, IsValidURL), HOOK_SPECIAL(jscript, COleScript_ParseScriptText), HOOK_NOTAIL(jscript, JsEval, 5), @@ -516,6 +517,8 @@ hook_t full_hooks[] = { HOOK(urlmon, URLDownloadToFileW), HOOK(urlmon, URLDownloadToCacheFileW), HOOK(urlmon, ObtainUserAgentString), + HOOK(amsi, AmsiScanBuffer), + HOOK(amsi, AmsiScanString), HOOK(wininet, InternetGetConnectedState), HOOK(wininet, InternetOpenA), HOOK(wininet, InternetOpenW), @@ -1046,6 +1049,7 @@ hook_t min_hooks[] = { HOOK(kernel32, CreateRemoteThreadEx), HOOK_SPECIAL(clrjit, compileMethod), + HOOK_SPECIAL(coreclr, compileMethod), HOOK_SPECIAL(ole32, CoCreateInstance), HOOK_SPECIAL(ole32, CoCreateInstanceEx), HOOK_SPECIAL(ole32, CoGetClassObject), @@ -1477,6 +1481,8 @@ hook_t office_hooks[] = { HOOK(urlmon, URLDownloadToFileW), HOOK(urlmon, URLDownloadToCacheFileW), HOOK(urlmon, ObtainUserAgentString), + HOOK(amsi, AmsiScanBuffer), + HOOK(amsi, AmsiScanString), HOOK(wininet, InternetGetConnectedState), HOOK(wininet, InternetOpenA), HOOK(wininet, InternetOpenW), diff --git a/hooks.h b/hooks.h index a09c440c..14d4f325 100644 --- a/hooks.h +++ b/hooks.h @@ -4005,4 +4005,24 @@ HOOKDEF(DWORD, WINAPI, MapFileAndCheckSumA, _Out_ PDWORD CheckSum ); +HOOKDEF(HRESULT, WINAPI, AmsiScanBuffer, + _In_ PVOID amsiContext, + _In_ PVOID buffer, + _In_ ULONG length, + _In_opt_ LPCWSTR contentName, + _In_opt_ PVOID amsiSession, + _Out_ PVOID result +); + +HOOKDEF(HRESULT, WINAPI, AmsiScanString, + _In_ PVOID amsiContext, + _In_ LPCWSTR string, + _In_opt_ LPCWSTR contentName, + _In_opt_ PVOID amsiSession, + _Out_ PVOID result +); + +#define New_coreclr_compileMethod New_clrjit_compileMethod +#define Old_coreclr_compileMethod Old_clrjit_compileMethod + #include "hook_vbscript.h"