Skip to content

Instantly share code, notes, and snippets.

@MolotovCherry
Last active March 1, 2022 14:01
Show Gist options
  • Save MolotovCherry/e3ce2adfa79055777fabb81de2e03376 to your computer and use it in GitHub Desktop.
Save MolotovCherry/e3ce2adfa79055777fabb81de2e03376 to your computer and use it in GitHub Desktop.
Rust WinAPI (windows-rs) process Privilege granter
[dependencies]
thiserror = "1.0.30"
[dependencies.windows]
version = "0.33.0"
features = [
"Win32_System_Threading",
"Win32_Foundation",
"Win32_Security",
"Win32_System_SystemServices"
]
use std::ffi::CString;
use windows::Win32::System::SystemServices::SE_DEBUG_NAME;
use windows::Win32::System::Threading::{TerminateProcess, OpenProcess, PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION, OpenProcessToken};
use windows::Win32::Foundation::{GetLastError, CloseHandle, HANDLE, LUID};
use windows::Win32::Security::{TOKEN_ADJUST_PRIVILEGES, LookupPrivilegeValueA, TOKEN_PRIVILEGES, SE_PRIVILEGE_ENABLED, AdjustTokenPrivileges, TOKEN_PRIVILEGES_ATTRIBUTES};
use windows::core::PCSTR;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ProcessError {
#[error("Process termination failed -> {process} : {pid}) -> code: {errcode}")]
TerminationFailed {
process: String,
pid: u32,
errcode: u32
},
#[error("HANDLE is NULL -> {process} : {pid}) -> code: {errcode}")]
NullHandle {
process: String,
pid: u32,
errcode: u32
},
#[error("Failed to close HANDLE -> {process} : {pid}) -> code: {errcode}")]
CloseHandleFailed {
process: String,
pid: u32,
errcode: u32
},
#[error("Failed to open process token")]
OpenProcessTokenFailed {
errcode: u32
},
#[error("Failed to lookup privilege")]
PrivilegeLookupFailed {
name: String,
errcode: u32
},
#[error("Adjust token privilege failed")]
AdjustTokenPrivilegeFailed {
name: String,
errcode: u32
}
}
fn set_privilege(name: &str, state: bool) -> Result<(), Box<dyn Error>> {
unsafe {
let handle = OpenProcess(PROCESS_QUERY_INFORMATION, false, std::process::id());
if handle.is_invalid() {
return Err(Box::new(ProcessError::NullHandle {
process: env!("CARGO_PKG_NAME").to_string(),
pid: std::process::id(),
errcode: GetLastError().0
}));
}
let mut token_handle = HANDLE(0);
let res: bool = OpenProcessToken(
handle,
TOKEN_ADJUST_PRIVILEGES,
&mut token_handle as *mut _
).into();
if !res {
return Err(Box::new(ProcessError::OpenProcessTokenFailed {
errcode: GetLastError().0
}));
}
let mut luid = LUID::default();
let privilege = CString::new(name)?;
let res: bool = LookupPrivilegeValueA(
PCSTR::default(),
PCSTR(privilege.as_ptr() as *const _),
&mut luid as *mut _
).into();
if !res {
return Err(Box::new(ProcessError::PrivilegeLookupFailed {
name: name.to_string(),
errcode: GetLastError().0
}));
}
let mut tp = TOKEN_PRIVILEGES::default();
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if state {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
} else {
tp.Privileges[0].Attributes = TOKEN_PRIVILEGES_ATTRIBUTES(0u32);
}
let res: bool = AdjustTokenPrivileges(
token_handle,
false,
&tp as *const _,
std::mem::size_of::<TOKEN_PRIVILEGES>() as u32,
std::ptr::null_mut() as *mut _,
std::ptr::null_mut() as *mut _
).into();
if !res {
return Err(Box::new(ProcessError::AdjustTokenPrivilegeFailed {
name: name.to_string(),
errcode: GetLastError().0
}));
}
let res: bool = CloseHandle(handle).into();
if !res {
return Err(Box::new(ProcessError::CloseHandleFailed {
process: env!("CARGO_PKG_NAME").to_string(),
pid: std::process::id(),
errcode: GetLastError().0
}));
}
let res: bool = CloseHandle(token_handle).into();
if !res {
return Err(Box::new(ProcessError::CloseHandleFailed {
process: env!("CARGO_PKG_NAME").to_string(),
pid: std::process::id(),
errcode: GetLastError().0
}));
}
}
Ok(())
}
fn kill_process(name: &str, pid: u32) -> Result<(), ProcessError> {
unsafe {
let handle = OpenProcess(PROCESS_TERMINATE, false, pid);
if handle.is_invalid() {
return Err(ProcessError::NullHandle {
process: name.to_string(),
pid,
errcode: GetLastError().0
});
}
let res: bool = TerminateProcess(handle, 0).into();
if !res {
return Err(ProcessError::TerminationFailed {
process: name.to_string(),
pid,
errcode: GetLastError().0
});
}
let res: bool = CloseHandle(handle).into();
if !res {
return Err(ProcessError::CloseHandleFailed {
process: name.to_string(),
pid,
errcode: GetLastError().0
});
}
}
Ok(())
}
fn main() -> Result<(), Box<dyn Error> {
// Program MUST be run as admin for this to work
// Amongst other things, this will allow the program to terminate SYSTEM processes
// For list of privileges, please see:
// https://docs.microsoft.com/en-us/windows/win32/secauthz/privilege-constants
set_privilege(SE_DEBUG_NAME, true)?;
// get the process PID you want to kill somewhere
kill_process("foobar.exe", 1234)?;
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment