提權相關函數

//提升權限
bool EnableSpecificPrivilege(LPCTSTR lpPrivilegeName)
{

	HANDLE hToken = NULL;
	TOKEN_PRIVILEGES Token_Privilege;
	BOOL bRet = TRUE;

	do 
	{
		if (0 == OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		{
			OutputDebugView(_T("OpenProcessToken Error"));
			bRet = FALSE;
			break;
		}

		if (0 == LookupPrivilegeValue(NULL, lpPrivilegeName, &Token_Privilege.Privileges[0].Luid))
		{
			OutputDebugView(_T("LookupPrivilegeValue Error"));
			bRet = FALSE;
			break;
		}

		Token_Privilege.PrivilegeCount = 1;
		Token_Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		//Token_Privilege.Privileges[0].Luid.LowPart=17;//SE_BACKUP_PRIVILEGE
		//Token_Privilege.Privileges[0].Luid.HighPart=0;


		if (0 == AdjustTokenPrivileges(hToken, FALSE, &Token_Privilege, sizeof(Token_Privilege), NULL,NULL))
		{
			OutputDebugView(_T("AdjustTokenPrivileges Error"));
			bRet = FALSE;
			break;
		}

	} while (false);

	if (NULL != hToken)
	{
		CloseHandle(hToken);
	}

	return bRet;

}

lpPrivilegeName 取值:

#define SE_CREATE_TOKEN_NAME              TEXT("SeCreateTokenPrivilege")#define SE_ASSIGNPRIMARYTOKEN_NAME        TEXT("SeAssignPrimaryTokenPrivilege")#define SE_LOCK_MEMORY_NAME               TEXT("SeLockMemoryPrivilege")#define SE_INCREASE_QUOTA_NAME            TEXT("SeIncreaseQuotaPrivilege")#define SE_UNSOLICITED_INPUT_NAME         TEXT("SeUnsolicitedInputPrivilege")#define SE_MACHINE_ACCOUNT_NAME           TEXT("SeMachineAccountPrivilege")#define SE_TCB_NAME                       TEXT("SeTcbPrivilege")#define SE_SECURITY_NAME                  TEXT("SeSecurityPrivilege")#define SE_TAKE_OWNERSHIP_NAME            TEXT("SeTakeOwnershipPrivilege")#define SE_LOAD_DRIVER_NAME               TEXT("SeLoadDriverPrivilege")#define SE_SYSTEM_PROFILE_NAME            TEXT("SeSystemProfilePrivilege")#define SE_SYSTEMTIME_NAME                TEXT("SeSystemtimePrivilege")#define SE_PROF_SINGLE_PROCESS_NAME       TEXT("SeProfileSingleProcessPrivilege")#define SE_INC_BASE_PRIORITY_NAME         TEXT("SeIncreaseBasePriorityPrivilege")#define SE_CREATE_PAGEFILE_NAME           TEXT("SeCreatePagefilePrivilege")#define SE_CREATE_PERMANENT_NAME          TEXT("SeCreatePermanentPrivilege")#define SE_BACKUP_NAME                    TEXT("SeBackupPrivilege")#define SE_RESTORE_NAME                   TEXT("SeRestorePrivilege")#define SE_SHUTDOWN_NAME                  TEXT("SeShutdownPrivilege")#define SE_DEBUG_NAME                     TEXT("SeDebugPrivilege")#define SE_AUDIT_NAME                     TEXT("SeAuditPrivilege")#define SE_SYSTEM_ENVIRONMENT_NAME        TEXT("SeSystemEnvironmentPrivilege")#define SE_CHANGE_NOTIFY_NAME             TEXT("SeChangeNotifyPrivilege")#define SE_REMOTE_SHUTDOWN_NAME           TEXT("SeRemoteShutdownPrivilege")#define SE_UNDOCK_NAME                    TEXT("SeUndockPrivilege")#define SE_SYNC_AGENT_NAME                TEXT("SeSyncAgentPrivilege")#define SE_ENABLE_DELEGATION_NAME         TEXT("SeEnableDelegationPrivilege")#define SE_MANAGE_VOLUME_NAME             TEXT("SeManageVolumePrivilege")#define SE_IMPERSONATE_NAME               TEXT("SeImpersonatePrivilege")#define SE_CREATE_GLOBAL_NAME             TEXT("SeCreateGlobalPrivilege")#define SE_TRUSTED_CREDMAN_ACCESS_NAME    TEXT("SeTrustedCredManAccessPrivilege")#define SE_RELABEL_NAME                   TEXT("SeRelabelPrivilege")#define SE_INC_WORKING_SET_NAME           TEXT("SeIncreaseWorkingSetPrivilege")#define SE_TIME_ZONE_NAME                 TEXT("SeTimeZonePrivilege")#define SE_CREATE_SYMBOLIC_LINK_NAME      TEXT("SeCreateSymbolicLinkPrivilege")

Note:訪問令牌說簡單了就是個訪問權限的數據集合,令牌中包含用戶所有的權限,校驗令牌可以識別用戶是否有權限訪問他要訪問的位置
LookupPrivilegeValue函數查看系統權限的特權值,返回信息到一個LUID結構體裏。
  BOOL LookupPrivilegeValue(LPCTSTR lpSystemName,LPCTSTR lpName,PLUID lpLuid);
  第一個參數表示所要查看的系統,本地系統直接用NULL
  第二個參數表示所要查看的特權信息的名稱,定義在winnt.h中,具體指請MSDN索引“windows nt privileges”
  第三個參數用來接收所返回的制定特權名稱的信息。
  函數調用成功後,信息存入第三個類型爲LUID的結構體中,並且函數返回非0。
  函數定義在winbase.h中,鏈接使用advapi32.lib庫。
AdjustTokenPrivileges 函數啓用或禁止 指定訪問令牌的特權。
啓用或禁用特權一個有TOKEN_ADJUST_PRIVILEGES訪問的訪問令牌.
  BOOL AdjustTokenPrivileges(
  HANDLE TokenHandle//包含特權的句柄
  BOOL DisableAllPrivileges,
  //禁用所有權限標誌
  PTOKEN_PRIVILEGES NewState,
  //新特權信息的指針(結構體)
  DWORD BufferLength//大小,以字節爲單位的PreviousState的緩存區(sizeof)
  PTOKEN_PRIVILEGES PreviousState,
  //接收被改變特權當前狀態的Buffer
  PDWORD ReturnLength//接收PreviousState緩存區要求的大小
  );
  參數
  TokenHandle
  包含要修改特權的訪問令牌的標識(句柄).這個句柄必須有TOKEN_ADJUST_PRIVILEGES訪問令牌.如果PreviousState不是NULL,這個句柄還必須有TOKEN_QUERY訪問特權.
  DisableAllPrivileges
  標誌這個函數是否禁用該令牌的所有特權.如果爲TRUE,這個函數禁用所有特權,NewState參數無效.如果爲假,以NewState參數指針的信息爲基礎來修改特權.
  NewState
  一個TOKEN_PRIVILEGES結構體的指針指定了一組特權和他們的屬性.
  如果參數DisableAllPrivileges爲FALSE,AdjustTokenPrivileges啓用或禁用這些令牌的特權.
  如果你給一個特權設置了SE_PRIVILEGE_ENABLED的屬性,這個函數將啓動特權,否則禁用特權.
  如果DisableAllPrivileges爲TRUE,這個參數無效.
  BufferLength
  標誌參數PreviousState指針以字節大小緩存區(sizeof).
  如果參數PreviousState是NULL,這個參數可以爲NULL.
  PreviousState
  這個函數填充一個TOKEN_PRIVILEGES結構體【指針】,它包括該函數修改之前任何特權狀態.這個參數可以爲NULL.
  如果指定的緩衝區太小,無法收到完整的修改權限列表,這個函數失敗並不會修改任何特權.
  這個函數設置了一個 擁有修改權限完成列表【 參數ReturnLength 】的字節數 的指針變量.[結果的Buffer]
  ReturnLength
  接收 參數PreviousState的緩存區指針的 字節大小 的 變量指針(長度指針).
  如果PreviousState爲NULL,這個參數可以爲NULL.
  返回值
  如果這個函數成功,返回非0.爲了確定這個函數是否修改了所有指定的特權,可以調用GetLastError函數,當這個函數返回下面的值之一時就代表函數成功:

提權函數之 RtlAdjustPrivilege()

RtlAdjustPrivilege() 這玩意是在 NTDLL.DLL 裏的一個不爲人知的函數,MS沒有公開,原因就是這玩意實在是太NB了,以至於不需要任何其他函數的幫助,僅憑這一個函數就可以獲得進程ACL的任意權限!下面是函數定義:NTSTATUS RtlAdjustPrivilege(         ULONG   Privilege,        BOOLEANEnable,        BOOLEANCurrentThread,        PBOOLEANEnabled)參數的含義:Privilege [In] Privilege index to change.                         // 所需要的權限名稱,可以到 MSDN 查找關於 Process Token & Privilege 內容可以查到Enable [In] If TRUE, then enable the privilege otherwise disable. // 如果爲True 就是打開相應權限,如果爲False 則是關閉相應權限CurrentThread [In] If TRUE, then enable in calling thread, otherwise process. // 如果爲True 則僅提升當前線程權限,否則提升整個進程的權限Enabled [Out] Whether privilege was previously enabled or disabled.// 輸出原來相應權限的狀態(打開 | 關閉), 注意:該參數賦予空指針會出錯,我測試過。eg:RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,1,0,NULL);比用 AdjustTokenPrivileges 來提升進程權限方便很多,所以自己整理下備忘這個函數封裝在NtDll.dll中(在所有DLL加載之前加載),被微軟嚴格保密,就是說你在MSDN上查不到關於他的任何信息。

常用:常量 SE_BACKUP_PRIVILEGE = 0x11h常量 SE_RESTORE_PRIVILEGE = 0x12h常量 SE_SHUTDOWN_PRIVILEGE = 0x13h常量 SE_DEBUG_PRIVILEGE = 0x14h

全部:

//// These must be converted to LUIDs before use.//#define SE_MIN_WELL_KNOWN_PRIVILEGE         (2L)#define SE_CREATE_TOKEN_PRIVILEGE           (2L)#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE     (3L)#define SE_LOCK_MEMORY_PRIVILEGE            (4L)#define SE_INCREASE_QUOTA_PRIVILEGE         (5L)#define SE_MACHINE_ACCOUNT_PRIVILEGE        (6L)#define SE_TCB_PRIVILEGE                    (7L)#define SE_SECURITY_PRIVILEGE               (8L)#define SE_TAKE_OWNERSHIP_PRIVILEGE         (9L)#define SE_LOAD_DRIVER_PRIVILEGE            (10L)#define SE_SYSTEM_PROFILE_PRIVILEGE         (11L)#define SE_SYSTEMTIME_PRIVILEGE             (12L)#define SE_PROF_SINGLE_PROCESS_PRIVILEGE    (13L)#define SE_INC_BASE_PRIORITY_PRIVILEGE      (14L)#define SE_CREATE_PAGEFILE_PRIVILEGE        (15L)#define SE_CREATE_PERMANENT_PRIVILEGE       (16L)#define SE_BACKUP_PRIVILEGE                 (17L)#define SE_RESTORE_PRIVILEGE                (18L)#define SE_SHUTDOWN_PRIVILEGE               (19L)#define SE_DEBUG_PRIVILEGE                  (20L)#define SE_AUDIT_PRIVILEGE                  (21L)#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE     (22L)#define SE_CHANGE_NOTIFY_PRIVILEGE          (23L)#define SE_REMOTE_SHUTDOWN_PRIVILEGE        (24L)#define SE_UNDOCK_PRIVILEGE                 (25L)#define SE_SYNC_AGENT_PRIVILEGE             (26L)#define SE_ENABLE_DELEGATION_PRIVILEGE      (27L)#define SE_MANAGE_VOLUME_PRIVILEGE          (28L)#define SE_IMPERSONATE_PRIVILEGE            (29L)#define SE_CREATE_GLOBAL_PRIVILEGE          (30L)#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L)#define SE_RELABEL_PRIVILEGE                (32L)#define SE_INC_WORKING_SET_PRIVILEGE        (33L)#define SE_TIME_ZONE_PRIVILEGE              (34L)#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE   (35L)#define SE_MAX_WELL_KNOWN_PRIVILEGE         (SE_CREATE_SYMBOLIC_LINK_PRIVILEGE)

關機代碼

#include <windows.h>const unsigned int SE_SHUTDOWN_PRIVILEGE = 0x13;int main(){HMODULE hDll = ::LoadLibrary("ntdll.dll");typedef int (* type_RtlAdjustPrivilege)(int, bool, bool, int*);typedef int (* type_ZwShutdownSystem)(int);type_RtlAdjustPrivilege RtlAdjustPrivilege = (type_RtlAdjustPrivilege)GetProcAddress(hDll, "RtlAdjustPrivilege");type_ZwShutdownSystem ZwShutdownSystem = (type_ZwShutdownSystem)GetProcAddress(hDll, "ZwShutdownSystem");int nEn = 0;int nResult = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, true, true, &nEn);if(nResult == 0x0c000007c){nResult = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, true, false, &nEn);}nResult = ZwShutdownSystem(2);FreeLibrary(hDll);return 0;} 

==============================================

以不同用戶身份運行程序

一直想方便的處理CCProxy代理的帳號管理,所以夢想做一個比較好的管理工具。但一個最麻煩的問題就是帳號的更新,CCProxy有一個網頁管理功能,可以加帳號,但加的帳號就是不可以立即更新。中午上網的時候發現CCProxy有一功能就是支持命令行的操作,如:
  CCProxy -reboot  重啓軟件
  CCProxy -reset   更新配置
  CCProxy -update  更新帳號
   
   試着改了AccInfo.ini中帳號信息,在DOS中運行CCProxy -update的確更新了賬號,所以開始用PHP做管理工具,做到調用CCProxy -update時,用了PHP中的exec(),system()等函數一直沒有效果,後又通過調用批處理文件來調用命令行參數都不行。 處理得正沒耐心的時候,一氣之下狂刷新PHP網頁,電腦卡死,用進程管理器查看時發現打開了多個CCProxy進程,認真一看,除了一個CCProxy是用戶進程外其它CCProxy全是system進程。認真一想有可能是運行用戶身份不同所產生的結果。
  Apache服務調用的外部程序以system身份運行,自己雙擊運行的程序以用戶身份運行。 如果CCProxy -update以用戶身份運行是不是就可以了呢?本人在網絡上找到了runas這個命令,的確可以指定以哪個用戶運行,但是每次都要輸密碼,沒有密碼的帳號就要加上密碼纔可以用,“/savecred”這個參數可以用,只要輸入一次密碼就可以了,但在PHP中發現要以system的身份輸入一次纔行,根本沒有機會輸入。打算用C程序來處理這個問題。可是發現用WinExec(),ShellExecute(),CreateProcess()都不好處理這個問題,好在發現了CreateProcessAsUser()這個函數。把網絡上的程序改了幾處,編譯後一試問題終於解決。
   以下爲相關代碼:
// Update.cpp : 定義控制檯應用程序的入口點。

#include "stdafx.h"  
#include <windows.h>  
#include <tlhelp32.h>  
  
BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)  
{  
    if(!lpName)  
        return FALSE;  
      
    HANDLE         hProcessSnap = NULL;   
    BOOL           bRet      = FALSE;   
    PROCESSENTRY32 pe32      = {0};   
      
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);   
    if (hProcessSnap == INVALID_HANDLE_VALUE)   
        return (FALSE);   
      
    pe32.dwSize = sizeof(PROCESSENTRY32);   
      
    if (Process32First(hProcessSnap, &pe32))   
    {    
        do   
        {  
            if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))  
            {  
                HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,  
                    FALSE,pe32.th32ProcessID);  
                bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);  
                CloseHandle (hProcessSnap);   
                return (bRet);  
            }  
        }   
        while (Process32Next(hProcessSnap, &pe32));   
        bRet = TRUE;   
    }    
    else   
        bRet = FALSE;  
      
    CloseHandle (hProcessSnap);   
    return (bRet);  
}  
  
BOOL RunProcess(LPCSTR lpImage,LPSTR lpCommandLine)  
{  
    if(!lpImage)  
        return FALSE;  
      
    HANDLE hToken;  
    if(!GetTokenByName(hToken,"EXPLORER.EXE"))  
        return FALSE;  
      
    STARTUPINFO si;  
    PROCESS_INFORMATION pi;  
      
    ZeroMemory(&si, sizeof(STARTUPINFO));  
    si.cb= sizeof(STARTUPINFO);  
    si.lpDesktop = TEXT("winsta0\\default");  
      
    BOOL bResult = CreateProcessAsUser(hToken,lpImage, lpCommandLine,NULL,NULL,  
        FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);  
    CloseHandle(hToken);  
    if(bResult)  
    {  
        OutputDebugString("CreateProcessAsUser ok!\r\n");  
        printf("CreateProcessAsUser ok!\r\n");  
    }  
    else  
    {  
        OutputDebugString("CreateProcessAsUse* **lse!\r\n");  
        printf("CreateProcessAsUse* **lse!\r\n");  
    }  
    return bResult;  
}  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
    RunProcess("CCProxy.exe"," -update");  
    return 0;  
}


=====================================================================


用CreateProcessAsUser 創建最低權限進程


我從msdn上找到的資料,你看看
高 管理權限(進程可以將文件安裝到“Program Files”文件夾,並寫入敏感註冊表區域,如 HKEY_LOCAL_MACHINE。)
中 用戶權限(進程可在用戶的“文檔”文件夾創建和修改文件,並寫入用戶指定的註冊表區域,如 HKEY_CURRENT_USER。)
低 不受信任權限(進程只能寫入低完整性位置,例如 Temporary Internet Files\Low 文件夾或 HKEY_CURRENT_USER\Software\LowRegistry key)
啓動低完整性進程
1.重複中等完整性進程的處理。  
2.使用 SetTokenInformation 將進程處理降低爲低完整性。  
3.使用 CreateProcessAsUser 創建使用低完整性處理的新進程。

uses
  windows;
   
  function ConvertStringSidToSidA(StringSid: LPCTSTR; Sid:TSIDIdentifierAuthority): BOOL; stdcall; external 'Advapi32.dll' name 'ConvertStringSidToSidA';

const
  SE_GROUP_INTEGRITY = 1; 

#include "winnt.h"   
   
BOOL b;   
HANDLE hToken;   
HANDLE hNewToken;   
PWSTR szProcessName = "LowClient"; // 例如   
PWSTR szIntegritySid = "S-1-16-4096"; // 低完整性 SID   
PSID pIntegritySid = NULL;   
TOKEN_MANDATORY_LABEL TIL = {0};   
PROCESS_INFORMATION ProcInfo = {0};   
STARTUPINFO StartupInfo = {0};   
ULONG ExitCode = 0;   
   
b = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED,   
  &hToken);   
b = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,   
  SecurityImpersonation, TokenPrimary, &hNewToken);   
b = ConvertStringSidToSid(szIntegritySid, &pIntegritySid);   
TIL.Label.Attributes = SE_GROUP_INTEGRITY;   
TIL.Label.Sid = pIntegritySid;   
   
// 設置進程完整性級別   
b = SetTokenInformation(hNewToken, TokenIntegrityLevel, &TIL,   
  sizeof(TOKEN_MANDATORY_LABEL) + RtlLengthSid(pIntegritySid));   
   
// 設置進程的 UI 權限級別   
b = SetTokenInformation(hNewToken, TokenIntegrityLevelDesktop,   
  &TIL, sizeof(TOKEN_MANDATORY_LABEL) + RtlLengthSid(pIntegritySid));   
   
// 以低完整性創建新進程   
b = CreateProcessAsUser(hNewToken, NULL, szProcessName, NULL, NULL,   
  FALSE, 0, NULL, NULL, &StartupInfo, &ProcInfo);


實際中遇到的問題描:SKype在一個本地登錄帳戶裏只能運行一個實例,我需要運行多個實例,那麼就需要以其他帳戶的身份運行skype 


有個方法: 
調用runas.exe程序。。 
只需要以runas /user:anotheruser "password" whatisgoingtorun 
運行一個新進程就解決了 
而windows默認的runas.exe是交互式輸入密碼, 看雪上有人將它改爲了參數式輸入密碼(即上面的形式) 
詳見看雪論壇 
以下是該帖子網址: 
http://www.pediy.com/bbshtml/bbs8/pediy8-45.htm


============================================================


微軟從XP/2003開始爲我們提供了一套Windows Terminal Service 的相關API,這些API都以WTS開頭(請安裝MSDN2005以查閱相關說明),要獲得活動Session也不止一個途徑,最簡單的就是直接使用  
DWORD WTSGetActiveConsoleSessionId(void);  
來獲得活動Session Id 。要在程序中使用這些API需要最新的Platform SDK(如果你正在使用Visual Studio 2005那麼它已經具備了相關頭文件和庫文件可以直接使用了),如果你在使用VC++ 6.0 你也沒有或者不打算安裝最新的SDK那麼你可以直接使用LoadLibrary() 裝載wtsapi32.dll然後使用GetProcAddress()獲得相關函數的地址以調用它們。我們獲得了活動SessionId後就可以使用  
BOOL WTSQueryUserToken(  
ULONG SessionId,  
PHANDLE phToken  
);  
來獲取當前活動Session中的用戶令牌(Token),有了這個Token我們的就可以在活動Session中創建新進程了,  
BOOL CreateProcessAsUser(  
HANDLE hToken,  
LPCTSTR lpApplicationName,  
LPTSTR lpCommandLine,  
LPSECURITY_ATTRIBUTES lpProcessAttributes,  
LPSECURITY_ATTRIBUTES lpThreadAttributes,  
BOOL bInheritHandles,  
DWORD dwCreationFlags,  
LPVOID lpEnvironment,  
LPCTSTR lpCurrentDirectory,  
LPSTARTUPINFO lpStartupInfo,  
LPPROCESS_INFORMATION lpProcessInformation  
);  
將我們獲得的Token作爲此API的第一個參數即可,你可以先嚐試一下運行一個notepad.exe看看,怎麼樣?你可以在控制檯桌面上看到新進程了。再查看一下進程列表,該進程的用戶名是當前控制檯登錄的用戶。可是這裏我們又遇到一個問題,我們需要收集當前交本機互式登錄用戶的一些信息,而有些操作需要很高的權限才能完成,而Vista下即使是Administraotrs用戶組成員默認也是以Users權限啓動進程的,所以我們創建的新進程只有Users權限,無法完成一些操作,當然我們可以使用Vista所提供的UI來詢問用戶以提升至管理員權限,可有些操作甚至是管理員Token也無法完成的,而且需要用戶確認實在在易用性上大打折扣,所以我決定在活動Session中以SYSTEM權限啓動我們的用戶交互程序。顯然 WTSQueryUserToken() 是不好用了。  
之前,我們提到過進程所屬的Session是由進程Token中的TokenSessionId來決定的,那麼我們是不是可以複製服務進程的Token然後修改其中的TokenSessionId,從而在用戶桌面上創建一個具有SYSTEM權限的新進程呢?答案是肯定的。一下是實現這個操作的代碼,爲了縮小篇幅我刪除了異常處理代碼  
HANDLEhTokenThis = NULL;  
HANDLEhTokenDup = NULL;  
HANDLEhThisProcess = GetCurrentProcess();  
OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);  
DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup); 
DWORDdwSessionId = WTSGetActiveConsoleSessionId();  
SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));  

STARTUPINFOsi;  
PROCESS_INFORMATION pi;  
ZeroMemory(&si, sizeof(STARTUPINFO));  
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));  
si.cb = sizeof(STARTUPINFO);  
si.lpDesktop = "WinSta0//Default";  

LPVOIDpEnv = NULL;  
DWORDdwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;  

CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);  

CreateProcessAsUser(  
  hTokenDup,  
  NULL,  
  (char *)"notepad",  
  NULL,  
  NULL,  
  FALSE,  
  dwCreationFlag,  
  pEnv,  
  NULL,  
  &si,  
  &pi);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章