[英]Start a process in a user session on Windows from an OpenSSH session
我正在嘗試使用 Win32 API 在當前登錄用戶的交互式 session 中啟動一個進程。 啟動是從遠程 SSH session 進行的,因此這應該類似於在交互式 session 從服務中啟動進程。 遠程 SSH session 使用與我嘗試在交互式 session 中啟動進程相同的用戶登錄。
我有以下設置:
我使用下面的 C# 代碼來啟動進程,在本例中是 notepad.exe。 該代碼正在打開應在用戶 session 中運行的explorer.exe
進程的令牌。 然后復制令牌並用於創建流程。
var pHandle = OpenProcess(
0x001F0FFF,
false,
explorerPID);
if (pHandle == IntPtr.Zero) { // handle win32 error }
if (!OpenProcessToken(pHandle,
TOKEN_ALL_ACCESS,
out IntPtr tHandle)) {
// handle win32 error
}
var lpT = new SECURITY_ATTRIBUTES();
if (!DuplicateTokenEx(
tHandle,
TOKEN_ALL_ACCESS,
ref lpT,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary,
out IntPtr newtHandle)) {
// handle win32 error
}
var startInfo = new STARTUPINFO();
var lpProcAttr = new SECURITY_ATTRIBUTES();
var lpThreadAttr = new SECURITY_ATTRIBUTES();
startInfo.lpDesktop = "winsta0\\default";
startInfo.cb = Marshal.SizeOf(startInfo);
if (!CreateProcessAsUser(newtHandle,
"c:\\Windows\\notepad.exe",
null,
ref lpProcAttr,
ref lpThreadAttr,
false,
0x00000020,
IntPtr.Zero,
null,
ref startInfo,
out _)) {
// handle win32 error
}
我在服務器上部署二進制文件,然后通過 SSH 我正在執行它。 問題是我得到(5) Access is denied
CreateProcessAsUser
function 上的訪問被拒絕。 有沒有人知道我在這里缺少什么,或者是否有可能實現這一點?
在一般情況下調用CreateProcessAsUser
您需要SE_ASSIGNPRIMARYTOKEN_NAME
權限。 您也可以在一些 session (如資源管理器)中搜索一些進程並使用它。 或者您可以枚舉終端會話並從 session 獲取令牌。 為此,您需要 TCB 特權。 這兩種可能都使您最初擁有調試權限。 代碼可以是下一個:
#define BEGIN_PRIVILEGES(name, n) static const union { TOKEN_PRIVILEGES name;\
struct { ULONG PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[n];} label(_) = { n, {
#define LAA(se) {{se}, SE_PRIVILEGE_ENABLED }
#define LAA_D(se) {{se} }
#define END_PRIVILEGES }};};
const SECURITY_QUALITY_OF_SERVICE sqos = {
sizeof (sqos), SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
};
const OBJECT_ATTRIBUTES oa_sqos = { sizeof(oa_sqos), 0, 0, 0, 0, const_cast<SECURITY_QUALITY_OF_SERVICE*>(&sqos) };
const TOKEN_PRIVILEGES tp_Debug = { 1, { { { SE_DEBUG_PRIVILEGE }, SE_PRIVILEGE_ENABLED } } };
BEGIN_PRIVILEGES(tp_TCB, 3)
LAA(SE_TCB_PRIVILEGE),
LAA(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE),
LAA(SE_INCREASE_QUOTA_PRIVILEGE),
END_PRIVILEGES
NTSTATUS GetToken(PVOID buf, const TOKEN_PRIVILEGES* RequiredSet)
{
NTSTATUS status;
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
HANDLE hProcess, hToken, hNewToken;
CLIENT_ID ClientId = { pspi->UniqueProcessId };
if (ClientId.UniqueProcess)
{
if (0 <= NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION,
const_cast<POBJECT_ATTRIBUTES>(&oa_sqos), &ClientId))
{
status = NtOpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken);
NtClose(hProcess);
if (0 <= status)
{
status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,
const_cast<POBJECT_ATTRIBUTES>(&oa_sqos), FALSE, TokenImpersonation, &hNewToken);
NtClose(hToken);
if (0 <= status)
{
status = NtAdjustPrivilegesToken(hNewToken, FALSE, const_cast<PTOKEN_PRIVILEGES>(RequiredSet), 0, 0, 0);
if (STATUS_SUCCESS == status)
{
status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
}
NtClose(hNewToken);
if (STATUS_SUCCESS == status)
{
return STATUS_SUCCESS;
}
}
}
}
}
} while (NextEntryOffset = pspi->NextEntryOffset);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS AdjustPrivileges(_In_ const TOKEN_PRIVILEGES* ptp)
{
NTSTATUS status;
HANDLE hToken, hNewToken;
if (0 <= (status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_DUPLICATE, &hToken)))
{
status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,
const_cast<OBJECT_ATTRIBUTES*>(&oa_sqos), FALSE, TokenImpersonation, &hNewToken);
NtClose(hToken);
if (0 <= status)
{
if (STATUS_SUCCESS == (status = NtAdjustPrivilegesToken(hNewToken, FALSE,
const_cast<PTOKEN_PRIVILEGES>(ptp), 0, 0, 0)))
{
status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
}
NtClose(hNewToken);
}
}
return status;
}
NTSTATUS ImpersonateToken(_In_ const TOKEN_PRIVILEGES* RequiredSet)
{
NTSTATUS status = AdjustPrivileges(&tp_Debug);
ULONG cb = 0x40000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PBYTE buf = new BYTE[cb += PAGE_SIZE])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
status = GetToken(buf, RequiredSet);
if (status == STATUS_INFO_LENGTH_MISMATCH)
{
status = STATUS_UNSUCCESSFUL;
}
}
delete [] buf;
}
} while(status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
void StartNotepadInSession(ULONG dwSessionId)
{
HANDLE hToken;
WCHAR sz[MAX_PATH];
if (SearchPathW(0, L"notepad.exe", 0, _countof(sz), sz, 0))
{
if (WTSQueryUserToken(dwSessionId, &hToken))
{
PVOID lpEnvironment;
if (CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE))
{
PROCESS_INFORMATION pi;
STARTUPINFOW si = { sizeof(si) };
if (CreateProcessAsUserW(hToken, sz, 0, 0, 0, 0,
CREATE_UNICODE_ENVIRONMENT, lpEnvironment, 0, &si, &pi))
{
NtClose(pi.hThread);
NtClose(pi.hProcess);
}
DestroyEnvironmentBlock(lpEnvironment);
}
NtClose(hToken);
}
}
}
void exec()
{
if (0 <= ImpersonateToken(&tp_TCB))
{
ULONG MySessionId, SessionId;
ProcessIdToSessionId(GetCurrentProcessId(), &MySessionId);
PWTS_SESSION_INFOW pSessionInfo;
ULONG Count;
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &Count))
{
DbgPrint("Sessions = %x\r\n", Count);
if (Count)
{
pSessionInfo += Count;
do
{
--pSessionInfo;
DbgPrint("SESSION_INFO<%x>: %x %S\r\n", pSessionInfo->SessionId, pSessionInfo->State, pSessionInfo->pWinStationName);
if (SessionId = pSessionInfo->SessionId)
{
switch (pSessionInfo->State)
{
case WTSDisconnected:
case WTSActive:
if (MySessionId != SessionId)
{
StartNotepadInSession(SessionId);
}
break;
}
}
} while (--Count);
}
WTSFreeMemory(pSessionInfo);
}
RevertToSelf();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.