使用場景:
病毒木馬想要實現一些關鍵的系統操作時。
比如:通過調用ExitWindows函數實現關機或重啟操作的時候就需要SE_SHUTDOWN_NAME權限
否則,會忽視操作不執行
實現原理:
獲取進程的訪問令牌,然后將訪問令牌的權限修改為指定權限。但是系統內部並不直接識別權限名稱,而是識別LUID值,所以需要根據權限名稱獲取對應的LUID值,之后傳遞給系統,實現進程訪問令牌權限的修改。
實現過程:
1.獲取指定進程的訪問令牌(需要獲取TOKEN_ADJUST_PRIVILEGES權限的令牌句柄)
2.獲取本地系統指定特權名稱的LUID值(LUID值相當於該特權的身份標號)
3.創建一個新的進程令牌特權結構體,並對其進行賦值(新特權的數量,特權對應的LUID值以及特權的屬性狀態)
4.調用 AdjustTokenPrivileges 函數對進程令牌的特權進行修改
注意點:
AdjustTokenPrivileges返回TRUE,並不代表特權設置成功,還需要使用GetLastError來判斷錯誤碼返回值。
若錯誤碼返回值為ERROR_SUCCESS,則表示所有特權設置成功;若為ERROR_NOT_ALL_ASSIGNED,
則表示並不是所有特權都設置成功
換句話說,如果在程序中只提升了一個訪問令牌特權,
且錯誤碼為ERROR_NOT_ALL_ASSIGNED,則提升失敗。如果程序運行在 Windows 7或者以上版本的操作系統,
可以嘗試以管理員身份運行程序然后再測試
代碼:
//************************************ // 函數名: CPrivilgeEscalationDlg::EnableDebugPrivilege // 返回類型: BOOL // 功能: 提升進程訪問令牌權限 // 參數1: 需要提升權限的進程句柄 // 參數2: 特權名稱 //************************************ BOOL CPrivilgeEscalationDlg::EnableDebugPrivilege(HANDLE hProcess, char* pszPrivilegesName) { HANDLE hToken = NULL; //令牌權限結構體 TOKEN_PRIVILEGES tp; //打開進程令牌並獲取進程令牌句柄 BOOL bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken); if (FALSE == bRet) { MessageBox(L"打開進程令牌失敗!"); return FALSE; } //獲取本地系統的 pszPrivilegesName 特權的LUID值 bRet = LookupPrivilegeValue(NULL, (LPCWSTR)pszPrivilegesName, &tp.Privileges[0].Luid); if (FALSE == bRet) { MessageBox(L"獲取LUID值失敗!"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } //設置提升權限信息 //設置新提權的數量 tp.PrivilegeCount = 1; //啟用該特權 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //提升進程令牌訪問權限 bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); if (FALSE == bRet) { MessageBox(L"提升進程令牌訪問權限失敗!"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } else { //根據錯誤碼判斷是否是特權都設置成功 DWORD dwRet = GetLastError(); if (ERROR_SUCCESS == dwRet) { CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return TRUE; } else if (ERROR_NOT_ALL_ASSIGNED == dwRet) { MessageBox(L"提升權限失敗!,請以管理員身份運行"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } } CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; }