获取当前用户的sid
!macro _GSID_Func_CALL
System::Call "user32::FindWindow(i0,tProgram Manager)p.r1"
System::Call user32::GetWindowThreadProcessId(pr1,*i.r2)i.r3
System::Call Kernel32::OpenProcess(i0x0400,i0,ir2)i.r4
System::Call Advapi32::OpenProcessToken(pr4,i0x0008,*i.r5)i.r9
System::Call Advapi32::GetTokenInformation(pr5,i1,*i.r0,i0,*i.r7)i.r8
System::Alloc $7
Pop $0
System::Call Advapi32::GetTokenInformation(pr5,i1,ir0,ir7,*i.r7)i.r8
System::Call *$0(i.R0)
System::Call Advapi32::LookupAccountSid(i0,iR0,t.R6,*i260,t.R7,*i260,*i .r2)
System::Free $0
System::Call *(&t${NSIS_MAX_STRLEN})i.R3
System::Call advapi32::LookupAccountName(t,tR6,iR3,*i${NSIS_MAX_STRLEN},t,*i${NSIS_MAX_STRLEN},*i)
System::Call advapi32::ConvertSidToStringSid(iR3,*t.R4)
; StrCpy $0 $R4
System::Free $R3
System::Free $R4
Push $R4
!macroend
获取当前用户的sid,python实现
import ctypes
import ctypes.wintypes
# 加载必要的 Windows API 函数
user32 = ctypes.WinDLL('user32', use_last_error=True)
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
# 定义一些常量
PROCESS_QUERY_INFORMATION = 0x0400
TOKEN_QUERY = 0x0008
NSIS_MAX_STRLEN = 1024
# 函数声明
FindWindow = user32.FindWindowW
FindWindow.restype = ctypes.wintypes.HWND
FindWindow.argtypes = [ctypes.wintypes.LPCWSTR, ctypes.wintypes.LPCWSTR]
GetWindowThreadProcessId = user32.GetWindowThreadProcessId
GetWindowThreadProcessId.restype = ctypes.wintypes.DWORD
GetWindowThreadProcessId.argtypes = [ctypes.wintypes.HWND, ctypes.POINTER(ctypes.wintypes.DWORD)]
OpenProcess = kernel32.OpenProcess
OpenProcess.restype = ctypes.wintypes.HANDLE
OpenProcess.argtypes = [ctypes.wintypes.DWORD, ctypes.wintypes.BOOL, ctypes.wintypes.DWORD]
OpenProcessToken = advapi32.OpenProcessToken
OpenProcessToken.restype = ctypes.wintypes.BOOL
OpenProcessToken.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.wintypes.HANDLE)]
GetTokenInformation = advapi32.GetTokenInformation
GetTokenInformation.restype = ctypes.wintypes.BOOL
GetTokenInformation.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.LPVOID, ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.wintypes.DWORD)]
LookupAccountSidW = advapi32.LookupAccountSidW
LookupAccountSidW.restype = ctypes.wintypes.BOOL
LookupAccountSidW.argtypes = [ctypes.wintypes.LPWSTR, ctypes.wintypes.LPVOID, ctypes.wintypes.LPWSTR, ctypes.POINTER(ctypes.wintypes.DWORD), ctypes.wintypes.LPWSTR, ctypes.POINTER(ctypes.wintypes.DWORD), ctypes.POINTER(ctypes.wintypes.DWORD)]
ConvertSidToStringSidW = advapi32.ConvertSidToStringSidW
ConvertSidToStringSidW.restype = ctypes.wintypes.BOOL
ConvertSidToStringSidW.argtypes = [ctypes.wintypes.LPVOID, ctypes.POINTER(ctypes.wintypes.LPWSTR)]
LocalFree = kernel32.LocalFree
LocalFree.restype = ctypes.wintypes.HANDLE
LocalFree.argtypes = [ctypes.wintypes.HANDLE]
def get_sid_from_process():
# 找到 "Program Manager" 窗口
hwnd = FindWindow(None, "Program Manager")
if not hwnd:
raise ctypes.WinError(ctypes.get_last_error())
# 获取窗口的进程ID
process_id = ctypes.wintypes.DWORD()
thread_id = GetWindowThreadProcessId(hwnd, ctypes.byref(process_id))
if not thread_id:
raise ctypes.WinError(ctypes.get_last_error())
# 打开进程
process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, False, process_id)
if not process_handle:
raise ctypes.WinError(ctypes.get_last_error())
# 打开进程令牌
token_handle = ctypes.wintypes.HANDLE()
if not OpenProcessToken(process_handle, TOKEN_QUERY, ctypes.byref(token_handle)):
raise ctypes.WinError(ctypes.get_last_error())
# 获取令牌信息所需的缓冲区大小
token_info_size = ctypes.wintypes.DWORD()
GetTokenInformation(token_handle, 1, None, 0, ctypes.byref(token_info_size))
# 分配缓冲区并获取令牌信息
token_info = ctypes.create_string_buffer(token_info_size.value)
if not GetTokenInformation(token_handle, 1, token_info, token_info_size.value, ctypes.byref(token_info_size)):
raise ctypes.WinError(ctypes.get_last_error())
# 获取 SID
sid = ctypes.cast(token_info, ctypes.POINTER(ctypes.wintypes.LPVOID)).contents
name_size = ctypes.wintypes.DWORD(NSIS_MAX_STRLEN)
domain_size = ctypes.wintypes.DWORD(NSIS_MAX_STRLEN)
sid_name_use = ctypes.wintypes.DWORD()
name = ctypes.create_unicode_buffer(name_size.value)
domain = ctypes.create_unicode_buffer(domain_size.value)
if not LookupAccountSidW(None, sid, name, ctypes.byref(name_size), domain, ctypes.byref(domain_size), ctypes.byref(sid_name_use)):
raise ctypes.WinError(ctypes.get_last_error())
# 将 SID 转换为字符串
sid_string = ctypes.wintypes.LPWSTR()
if not ConvertSidToStringSidW(sid, ctypes.byref(sid_string)):
raise ctypes.WinError(ctypes.get_last_error())
# 打印 SID 字符串
result = sid_string.value
LocalFree(sid_string)
return result
if __name__ == "__main__":
sid = get_sid_from_process()
print(f"当前用户的 SID: {sid}")
解释:
FindWindow:查找名为 "Program Manager" 的窗口,它通常是桌面进程。
GetWindowThreadProcessId:获取该窗口的线程和进程 ID。
OpenProcess:使用进程 ID 打开进程。
OpenProcessToken:获取该进程的访问令牌。
GetTokenInformation:获取访问令牌的用户信息,这里需要两次调用,第一次用于获取所需缓冲区大小,第二次用于实际获取数据。
LookupAccountSidW:查找与 SID 关联的账户名称和域名。
ConvertSidToStringSidW:将 SID 转换为字符串形式。
LocalFree:释放分配的内存。
这个 Python 实现与原始的 NSIS 脚本执行的步骤基本相同,能够获取当前登录用户的 SID,即使在管理员权限下运行也能正确地获取用户信息。
Rust 获取当前用户SID
use std::os::windows::ffi::OsStrExt;
use std::{ffi::OsStr, time};
use std::{ptr, thread};
use widestring::WideCStr;
use winapi::{
ctypes::c_void,
shared::{minwindef::DWORD, sddl::ConvertSidToStringSidW, winerror::ERROR_INSUFFICIENT_BUFFER},
um::{
errhandlingapi::GetLastError,
handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
processthreadsapi::{OpenProcess, OpenProcessToken},
securitybaseapi::GetTokenInformation,
winbase::LocalFree,
winnt::{HANDLE, TOKEN_QUERY, TOKEN_USER},
winuser::{FindWindowW, GetWindowThreadProcessId},
},
};
fn get_sid_from_process() -> Result<String, std::io::Error> {
unsafe {
// 查找 "Program Manager" 窗口
let window_title: Vec<u16> = OsStr::new("Program Manager")
.encode_wide()
.chain(Some(0)) // 添加 null 终止符
.collect();
let hwnd = FindWindowW(ptr::null(), window_title.as_ptr());
if hwnd.is_null() {
return Err(std::io::Error::last_os_error());
}
// 获取进程 ID
let mut process_id: DWORD = 0;
let thread_id = GetWindowThreadProcessId(hwnd, &mut process_id);
if thread_id == 0 {
return Err(std::io::Error::last_os_error());
}
// 打开进程句柄
let process_handle =
OpenProcess(winapi::um::winnt::PROCESS_QUERY_INFORMATION, 0, process_id);
if process_handle == INVALID_HANDLE_VALUE {
return Err(std::io::Error::last_os_error());
}
// 打开进程令牌
let mut token_handle: HANDLE = ptr::null_mut();
if OpenProcessToken(process_handle, TOKEN_QUERY, &mut token_handle) == 0 {
CloseHandle(process_handle);
return Err(std::io::Error::last_os_error());
}
// 获取令牌信息大小
let mut token_info_size: DWORD = 0;
let status = GetTokenInformation(
token_handle,
winapi::um::winnt::TokenUser,
ptr::null_mut(),
0,
&mut token_info_size,
);
// 检查是否为缓冲区不足错误
if status != 0 || GetLastError() != ERROR_INSUFFICIENT_BUFFER {
CloseHandle(token_handle);
CloseHandle(process_handle);
return Err(std::io::Error::last_os_error());
}
// 分配缓冲区并获取令牌信息
let mut buffer = vec![0u8; token_info_size as usize];
if GetTokenInformation(
token_handle,
winapi::um::winnt::TokenUser,
buffer.as_mut_ptr() as *mut _,
token_info_size,
&mut token_info_size,
) == 0
{
CloseHandle(token_handle);
CloseHandle(process_handle);
return Err(std::io::Error::last_os_error());
}
// 提取 SID
let token_user = &*(buffer.as_ptr() as *const TOKEN_USER);
let sid = token_user.User.Sid;
// 转换 SID 到字符串
let mut sid_string_ptr: *mut u16 = ptr::null_mut();
if ConvertSidToStringSidW(sid as *mut _, &mut sid_string_ptr) == 0 {
CloseHandle(token_handle);
CloseHandle(process_handle);
return Err(std::io::Error::last_os_error());
}
// 转换字符串并释放内存
let sid_cstr = WideCStr::from_ptr_str(sid_string_ptr);
let sid_str = sid_cstr.to_string_lossy().to_owned();
LocalFree(sid_string_ptr as *mut c_void);
// 清理资源
CloseHandle(token_handle);
CloseHandle(process_handle);
Ok(sid_str)
}
}
fn main() {
match get_sid_from_process() {
Ok(sid) => println!("当前用户的 SID: {}", sid),
Err(e) => eprintln!("错误: {}", e),
}
// let ten_millis = time::Duration::from_millis(10000);
// let now = time::Instant::now();
// thread::sleep(ten_millis);
}