diff --git a/Code Snippets/SubscriberBitPatch.c b/Code Snippets/SubscriberBitPatch.c index 12d8b2b..a6bb94b 100644 --- a/Code Snippets/SubscriberBitPatch.c +++ b/Code Snippets/SubscriberBitPatch.c @@ -70,7 +70,7 @@ int* findDotNETRuntimeEnableBits(HMODULE clrBase) { for (int i = 0; i < clrSize; i++) { unsigned char* addr = (unsigned char*)clrBase + i; - // matches "test cs:Microsoft_Windows_DotNETRuntimeEnableBits, 80000000h" + // matches "test cs:Microsoft_Windows_DotNETRuntimeEnableBits, 80000000h/40000000h" if (addr[0] != 0xf7 || addr[1] != 0x5) { continue; } diff --git a/Code Snippets/SubscriberBitPatch.cs b/Code Snippets/SubscriberBitPatch.cs deleted file mode 100644 index 4a6482e..0000000 --- a/Code Snippets/SubscriberBitPatch.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace SubscriberBitPatch { - internal class Program { - [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr GetProcAddress(IntPtr hModule, string procName); - - static int getClrSize(IntPtr clrBase) { - Console.WriteLine("CLR Base: " + clrBase.ToString("X")); - int peOffset = Marshal.ReadInt32(clrBase + 0x3C); - IntPtr optionalHeaderPtr = clrBase + peOffset + 0x18; - int sizeOfImage = Marshal.ReadInt32(optionalHeaderPtr + 0x38); - Console.WriteLine("CLR SizeOfImage: 0x" + sizeOfImage.ToString("X")); - - return sizeOfImage; - } - - static IntPtr GetImageBase(String dllName) { - foreach (ProcessModule module in Process.GetCurrentProcess().Modules) { - if (module.ModuleName.Equals(dllName, StringComparison.OrdinalIgnoreCase)) { - return module.BaseAddress; - } - } - return IntPtr.Zero; - } - - static IntPtr FindDotNETRuntimeEnableBits() { - IntPtr clrBase = GetImageBase("clr.dll"); - - Console.WriteLine("clr.dll located at " + clrBase.ToString("X")); - - int clrSize = getClrSize(clrBase); - IntPtr clrEnd = clrBase + clrSize; - - String[] pattern = new string[] { "f7", "05", "??", "??", "??", "??", "00", "00", "00", "80" }; - - Dictionary globalVarCount = new Dictionary(); - - for (long addr = (long)clrBase; addr < (long)(clrEnd - pattern.Length); addr++) { - for (int i = 0; i < pattern.Length; i++) { - if (pattern[i] == "??") { - continue; - } - - int b = Marshal.ReadByte((IntPtr)addr + i); - int target_b = Convert.ToInt32(pattern[i], 16); - - if (b != target_b) { - break; - } - - if (i != pattern.Length - 1) { - continue; - } - - - int globalVarOffset = Marshal.ReadInt32((IntPtr)addr + 2); - IntPtr rip = (IntPtr)(addr + pattern.Length); - IntPtr globalVarAddr = rip + globalVarOffset; - - if (globalVarCount.ContainsKey(globalVarAddr)) { - globalVarCount[globalVarAddr]++; - } else { - globalVarCount[globalVarAddr] = 1; - } - //Console.WriteLine("Signature found at: 0x" + addr.ToString("X")); - } - } - - IntPtr topAddr = IntPtr.Zero; - foreach (var item in globalVarCount) { - if (topAddr == IntPtr.Zero || item.Value > globalVarCount[topAddr]) { - topAddr = item.Key; - } - } - - return topAddr; - } - - static void TurnOffETW(IntPtr DotNETRuntimeEnableBits_addr, out int DotNETRuntimeEnableBits_val) { - DotNETRuntimeEnableBits_val = Marshal.ReadInt32(DotNETRuntimeEnableBits_addr); - Marshal.WriteInt32(DotNETRuntimeEnableBits_addr, 1); - } - - static void TurnOnETW(IntPtr DotNETRuntimeEnableBits_addr, int DotNETRuntimeEnableBits_val) { - Marshal.WriteInt32(DotNETRuntimeEnableBits_addr, DotNETRuntimeEnableBits_val); - } - - static void Main(string[] args) { - IntPtr DotNETRuntimeEnableBits_addr = FindDotNETRuntimeEnableBits(); - - int DotNETRuntimeEnableBits_val = 0; - TurnOffETW(DotNETRuntimeEnableBits_addr, out DotNETRuntimeEnableBits_val); - Console.WriteLine("DotNETRuntimeEnableBits_val: 0x" + DotNETRuntimeEnableBits_val.ToString("X")); - - // filename is the .NET assembly executable on disk to load. - String filename = "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\RegAsm.exe"; - Byte[] bytes = File.ReadAllBytes(filename); - Assembly asm = Assembly.Load(bytes); - Console.WriteLine(asm); - - // because ETW is turned back on, upon termination of the process, an AssemblyUnload event for RegAsm is logged. - TurnOnETW(DotNETRuntimeEnableBits_addr, DotNETRuntimeEnableBits_val); - Console.WriteLine("Microsoft_Windows_DotNETRuntimeEnableBits_addr: 0x" + DotNETRuntimeEnableBits_addr.ToString("X")); - } - } -} \ No newline at end of file diff --git a/inlineExecute/inlineExecute.o b/inlineExecute/inlineExecute.o index 468f3fa..6380cde 100644 Binary files a/inlineExecute/inlineExecute.o and b/inlineExecute/inlineExecute.o differ diff --git a/src/inlineExecute.c b/src/inlineExecute.c index 5601f49..1282117 100644 --- a/src/inlineExecute.c +++ b/src/inlineExecute.c @@ -539,10 +539,31 @@ int isEtwFunc(unsigned char* funcAddr, void* etwEventWrite) { return 1; } +int hasCoTemplateEventDescriptorCall(unsigned char* addr, void* etwEventWrite) { + // test cs:Microsoft_Windows_DotNETRuntimeEnableBits, 40000000h (10 bytes) + // jz short loc_* (2 bytes) + // lea rdx, DebugIPCEventEnd (7 bytes) + // call CoTemplateEventDescriptor (5 bytes) + unsigned char* callInstrAddr = addr + 10 + 2 + 7; + unsigned char* rip = addr + 10 + 2 + 7 + 5; + + if (*callInstrAddr != 0xe8) { + return 0; // not a call + } + + int offset = *(DWORD*)(callInstrAddr + 1); + unsigned char* funcAddr = rip + offset; + + return isEtwFunc(funcAddr, etwEventWrite); +} + int* findDotNETRuntimeEnableBits() { void* clrBase = getImageBase(L"clr.dll"); int clrSize = getImageSize(clrBase); + void* ntdllBase = getImageBase(L"ntdll.dll"); + void* etwEventWrite = getProcAddr(ntdllBase, "EtwEventWrite"); + // assuming a max of 20 global variables that match the pattern int MAX = 20; int* globalVars[20] = { 0 }; @@ -556,7 +577,11 @@ int* findDotNETRuntimeEnableBits() { continue; } - if (*(DWORD*)(addr + 6) != 0x80000000) { + if (*(DWORD*)(addr + 6) != 0x80000000 && *(DWORD*)(addr + 6) != 0x40000000) { + continue; + } + + if (!hasCoTemplateEventDescriptorCall(addr, etwEventWrite)) { continue; }