Skip to content

Commit

Permalink
feat(daemon): Add impersonate crate, show rare-achievement-toast when…
Browse files Browse the repository at this point in the history
… starting SSH/SFTP daemon
  • Loading branch information
tuxuser committed Aug 23, 2024
1 parent 1f87726 commit e7350e4
Show file tree
Hide file tree
Showing 9 changed files with 2,213 additions and 0 deletions.
217 changes: 217 additions & 0 deletions crates/impersonate/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions crates/impersonate/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "impersonate"
version = "0.1.0"
edition = "2021"

[dependencies]
tracing = "0.1.40"
windows = { version = "0.58.0", features = [
"Win32_Security",
"Win32_System_Threading",
"Win32_System_ProcessStatus",
"Win32_System_Com",
"Win32_System_WindowsProgramming",
"Win32_System_SystemServices"
] }

[features]
default = []

155 changes: 155 additions & 0 deletions crates/impersonate/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/// Reference: https://github.com/joaovarelas/steal-token-rs/blob/main/src/main.rs
use tracing::{error, debug};
use windows::core::PSTR;
use windows::Win32::Foundation::{BOOL, FALSE, HANDLE, LUID, TRUE};
use windows::Win32::Security::{AdjustTokenPrivileges, RevertToSelf};
use windows::Win32::Security::LUID_AND_ATTRIBUTES;
use windows::Win32::Security::PRIVILEGE_SET;
use windows::Win32::Security::{
DuplicateTokenEx, LookupPrivilegeValueW, PrivilegeCheck, SecurityImpersonation,
TokenImpersonation, SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, TOKEN_ACCESS_MASK, TOKEN_ALL_ACCESS,
TOKEN_ASSIGN_PRIMARY, TOKEN_DUPLICATE, TOKEN_IMPERSONATE, TOKEN_PRIVILEGES, TOKEN_QUERY,
};
use windows::Win32::System::SystemServices::MAXIMUM_ALLOWED;
use windows::Win32::System::Threading::OpenProcess;
use windows::Win32::System::Threading::{
GetCurrentProcess, OpenProcessToken, SetThreadToken, PROCESS_QUERY_INFORMATION,
};
use windows::Win32::System::WindowsProgramming::GetUserNameA;

mod process_list;

pub struct Impersonate {
current_process: HANDLE,
original_token: HANDLE,
}

impl Impersonate {
pub fn create() -> Self {
let own = unsafe { GetCurrentProcess() };
let orig_token = Self::get_impersonation_token(own).unwrap();
Self {
current_process: own,
original_token: orig_token,
}
}

fn get_impersonation_token(process_handle: HANDLE) -> Result<HANDLE, Box<dyn std::error::Error>> {
let mut token_handle = HANDLE::default();
let mut new_token = HANDLE::default();

unsafe {
OpenProcessToken(
process_handle,
TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
&mut token_handle,
)?;

DuplicateTokenEx(
token_handle,
TOKEN_ACCESS_MASK(MAXIMUM_ALLOWED),
None,
SecurityImpersonation,
TokenImpersonation,
&mut new_token,
)?;
}

Ok(new_token)
}

pub fn get_username() -> Result<String, Box<dyn std::error::Error>> {
let mut buffer = vec![0u8; 257];
let lpbuffer: PSTR = PSTR(buffer.as_mut_ptr());
let mut pcbbuffer: u32 = buffer.len() as u32;

unsafe {
GetUserNameA(lpbuffer, &mut pcbbuffer)?;
}

let username = String::from_utf8(buffer)?.trim_end_matches("\0").to_owned();
Ok(username)
}

fn enable_debug_privilege(&mut self) -> Result<(), Box<dyn std::error::Error>> {
unsafe {
let mut luid: LUID = LUID {
LowPart: 0,
HighPart: 0,
};

LookupPrivilegeValueW(None, SE_DEBUG_NAME, &mut luid)?;
OpenProcessToken(self.current_process, TOKEN_ALL_ACCESS, &mut self.original_token)?;

let token_priv: TOKEN_PRIVILEGES = TOKEN_PRIVILEGES {
PrivilegeCount: 1,
Privileges: [LUID_AND_ATTRIBUTES {
Luid: luid,
Attributes: SE_PRIVILEGE_ENABLED,
}],
};

AdjustTokenPrivileges(self.original_token, FALSE, Some(&token_priv), 0, None, None)?;

let mut priv_set: PRIVILEGE_SET = PRIVILEGE_SET {
PrivilegeCount: 1,
Control: 1u32, // PRIVILEGE_SET_ALL_NECESSARY
Privilege: [LUID_AND_ATTRIBUTES {
Luid: luid,
Attributes: SE_PRIVILEGE_ENABLED,
}],
};

let mut priv_enabled: BOOL = BOOL(1);
PrivilegeCheck(self.original_token, &mut priv_set, &mut priv_enabled)?;

debug!("SeDebugPrivilege is: {:?}", priv_enabled);
}

Ok(())
}

pub fn do_impersonate_pid(&mut self, pid: u32) -> Result<(), Box<dyn std::error::Error>> {
unsafe {
let proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid)?;
let new_token = Impersonate::get_impersonation_token(proc_handle)?;
SetThreadToken(None, new_token)?;
}
Ok(())
}

pub fn do_impersonate_process_name(&mut self, process_name: &str) -> Result<(), Box<dyn std::error::Error>> {
self.enable_debug_privilege().or_else(|e| {
error!("Failed to enable debug privilege, err: {e:?}");
Err(e)
})?;

let mut pid = 0;
for p in process_list::get_process_list()? {
if p.name.to_lowercase() == process_name.to_lowercase() {
pid = p.id;
debug!("Found PID for {process_name} -> {pid}");
}
}

if pid == 0 {
return Err(format!("Failed to get target PID for process: {process_name:?}").into());
}


self.do_impersonate_pid(pid)
}

pub fn revert_to_self() -> Result<(), Box<dyn std::error::Error>> {
unsafe {
RevertToSelf()?;
Ok(())
}
}
}

impl Drop for Impersonate {
fn drop(&mut self) {
let _ = Self::revert_to_self();
}
}
Loading

0 comments on commit e7350e4

Please sign in to comment.