首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

GUI RunAs:圖形化介面以不同身分啟動程式,支援桌面選擇、SYSTEM 權限與特權管理

     編輯:關於VC++

Windows 內建 runas.exe 僅支援命令列,參數繁瑣且無法互動選擇桌面。本文實作一套 GUI RunAs 工具,提供直覺介面、桌面隔離、帳號驗證、特權啟用、SYSTEM 啟動等進階功能,適合系統管理員、開發人員與自動化部署腳本使用。

核心功能一覽

  • 圖形化參數輸入:程式路徑、參數、工作目錄、使用者/密碼、網域。
  • 目標桌面選擇:列舉 WinSta0 下所有桌面 (Default, Winlogon, ScreenSaver, Disconnect 等),雙擊選擇於隔離桌面啟動。
  • 帳號選單:讀取本機使用者清單 (NetUserEnum),雙擊填入。
  • 密碼驗證按鈕:呼叫 LogonUser 即時驗證憑證正確性。
  • 特權啟用對話框:一鍵啟用 SeIncreaseQuotaPrivilege, SeAssignPrimaryTokenPrivilege, SeChangeNotifyPrivilege, SeTcbPrivilege,註銷重登即生效。
  • SYSTEM 啟動模式:留空帳號密碼 → 開啟 System 進程 Token、調整 TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY、DuplicateTokenEx + CreateProcessAsUser。
  • 常用程式清單:內建 cmd.exe, regedit.exe, mmc.exe 等快捷選項。

關鍵技術路徑

1. 列舉桌面


std::vector EnumDesktops() {
    std::vector result;
    HWINSTA hWinSta = OpenWindowStation(L"WinSta0", FALSE, WINSTA_ENUMDESKTOPS);
    if (!hWinSta) return result;
    wchar_t name[256];
    for (DWORD i = 0; EnumDesktops(hWinSta, [](LPTSTR lpszDesktop, LPARAM lParam) {
        auto& vec = *reinterpret_cast*>(lParam);
        vec.push_back(lpszDesktop);
        return TRUE;
    }, reinterpret_cast(&result)); ++i) {}
    CloseWindowStation(hWinSta);
    return result;
}

2. 驗證帳號密碼


bool VerifyCredentials(const wchar_t* user, const wchar_t* domain, const wchar_t* pwd) {
    HANDLE hToken;
    return LogonUser(user, domain, pwd, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)
        && (CloseHandle(hToken), true);
}

3. 啟用特權 (需管理員)


bool EnablePrivilege(LPCTSTR pszPrivilege, bool bEnable = true) {
    HANDLE hToken; TOKEN_PRIVILEGES tp = {1, {{0,0, bEnable ? SE_PRIVILEGE_ENABLED : 0}}};
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return false;
    LookupPrivilegeValue(nullptr, pszPrivilege, &tp.Privileges[0].Luid);
    BOOL ok = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, nullptr, nullptr);
    CloseHandle(hToken);
    return ok && GetLastError() != ERROR_NOT_ALL_ASSIGNED;
}

4. SYSTEM 啟動核心邏輯


bool LaunchAsSystem(LPCWSTR cmdLine, LPCWSTR workDir, HWINSTA hWinSta, HDESK hDesk) {
    // 1. 找 SYSTEM 進程 (如 winlogon.exe, services.exe)
    DWORD pid = FindSystemProcess(); // ToolHelp32 遍歷
    HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
    HANDLE hSysToken; OpenProcessToken(hProc, TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_QUERY, &hSysToken);
    // 2. 複製 Token 並設為 Primary
    HANDLE hPrimary; DuplicateTokenEx(hSysToken, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenPrimary, &hPrimary);
    // 3. 設定啟動資訊
    STARTUPINFO si = {sizeof(si)}; si.lpDesktop = (LPWSTR)L"WinSta0\\Default"; // 或傳入選擇的桌面
    PROCESS_INFORMATION pi;
    // 4. CreateProcessAsUser
    BOOL ok = CreateProcessAsUser(hPrimary, nullptr, (LPWSTR)cmdLine, nullptr, nullptr, FALSE,
        CREATE_UNICODE_ENVIRONMENT, nullptr, workDir, &si, &pi);
    // 清理 handles...
    return ok;
}

UI 介面截圖

GUI RunAs 主介面

介面區塊:程式路徑/參數/目錄 → 使用者/密碼/網域 (含選單/驗證按鈕) → 桌面下拉清單 → 常用程式下拉 → 特權啟用按鈕 → 執行/取消。

部署與使用提醒

  1. 編譯需 Platform SDK (含 userenv.h, secpol.h 等)。
  2. 執行需管理員權限 (UAC 提升),否則無法啟用特權、開啟 SYSTEM Token。
  3. 啟用特權後必須註銷/重新登入 才生效 (按鈕旁有提醒)。
  4. 目標桌面若非 Default,程式將不顯示於當前使用者畫面,適合背景服務、自動化測試。
  5. 原始碼使用 LSA API (LsaAddAccountRights 等) 管理特權,比手動編輯註冊表更安全。

對比替代工具

工具介面桌面隔離SYSTEM 啟動特權管理
runas.exeCLI✗✗✗
PsExecCLI✗✓ (-s)✗
RunAsTool (第三方)GUI部分✓部分
本工具GUI✓ 完整列舉✓ Token 複製法✓ 一鍵啟用+註冊表持久化

GUI RunAs 將繁瑣的 LogonUser/CreateProcessAsUser/Token 操作封裝為直覺介面,並解決桌面隔離、SYSTEM 啟動、特權持久化等進階痛點。完整原始碼 (VS2005/VC6 雙專案、Unicode、錯誤處理、日誌) 請參考文章附件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved