【发布时间】:2016-10-05 00:58:01
【问题描述】:
我想在我的项目中使用模拟来正确地在服务中运行它。
我看到一些代码做这样的事情:
获取explorer.exe PID,然后使用该PID 获取OpenProcess 和DuplicateTokenEx
之后是代码CreateThread,然后是SetThreadToken和ResumeThread
这是代码:
HANDLE ExplorerToken(VOID)
{
PROCESSENTRY32W procEntry;
HANDLE Snap = NULL;
HANDLE Process = NULL;
HANDLE PToken = NULL;
LPCWSTR TProce = L"explorer.exe";
DWORD TargetSID = -1;
DWORD SId = -1;
DWORD TargetPID = -1;
BOOL WellDone = TRUE;
HANDLE ExplorerToken = NULL;
if(ExplorerToken != NULL)
{
return ExplorerToken;
}
SId = WTSGetActiveConsoleSessionId();
procEntry.dwSize = sizeof(PROCESSENTRY32W);
Snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!Process32FirstW(Snap, &procEntry))
{
WellDone = FALSE;
}
do
{
if (lstrcmpiW(procEntry.szExeFile, TProce) == 0)
{
if (ProcessIdToSessionId(procEntry.th32ProcessID, &TargetSID) && TargetSID == SId)
{
TargetPID = procEntry.th32ProcessID;
break;
}
}
} while (Process32NextW(Snap, &procEntry));
if(TargetPID == -1)
{
WellDone = FALSE;
}
Process = OpenProcess(MAXIMUM_ALLOWED, FALSE, TargetPID);
if(!OpenProcessToken(Process, MAXIMUM_ALLOWED, &PToken))
{
WellDone = FALSE;
}
if(!DuplicateTokenEx(PToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &ExplorerToken))
{
WellDone = FALSE;
}
if(WellDone == FALSE)
{
return NULL;
}
else
{
return ExplorerToken;
}
}
VOID CcCryptUnprotectData(LPVOID data)
{
PCUD_PARAMS pCudParams;
pCudParams = (PCUD_PARAMS)data;
pCudParams->bRetVal = pCudParams->fp_CryptUnprotectData(
pCudParams->pDataIn,
pCudParams->ppszDataDescr,
pCudParams->pOptionalEntropy,
pCudParams->pvReserved,
pCudParams->pPromptStruct,
pCudParams->dwFlags,
pCudParams->pDataOut);
}
BOOL _CryptUnprotectData(__in DATA_BLOB *pDataIn, __out_opt LPWSTR *ppszDataDescr, __in_opt DATA_BLOB *pOptionalEntropy,
__in PVOID pvReserved, __in_opt CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, __in DWORD dwFlags, __out DATA_BLOB *pDataOut )
{
HANDLE ThreadHandle;
CUD_PARAMS cudParams;
DWORD ThreadIdArray = 0;
HMODULE hmCrypt32 = NULL;
HANDLE ExplorerToken;
cudParams.pDataIn = pDataIn;
cudParams.ppszDataDescr = ppszDataDescr;
cudParams.pOptionalEntropy = pOptionalEntropy;
cudParams.pvReserved = pvReserved;
cudParams.pPromptStruct = pPromptStruct;
cudParams.dwFlags = dwFlags;
cudParams.pDataOut = pDataOut;
cudParams.bRetVal = FALSE;
if(MyCryptUnprotectData_OutlookPassword == NULL)
{
if(hmCrypt32 == NULL)
{
hmCrypt32 = LoadLibraryW(L"Crypt32.dll");
}
MyCryptUnprotectData_OutlookPassword = (BOOL (WINAPI* )(DATA_BLOB *pDataIn, LPWSTR *ppszDataDescr, DATA_BLOB *pOptionalEntropy, PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, DWORD dwFlags, DATA_BLOB *pDataOut))GetProcAddress(hmCrypt32, "CryptUnprotectData");
}
cudParams.fp_CryptUnprotectData = MyCryptUnprotectData_OutlookPassword;
ExplorerToken = ExplorerToken();
if(ExplorerToken == NULL)
{
return FALSE;
}
ThreadHandle = CreateThread(NULL,
0, // use default stack size
(LPTHREAD_START_ROUTINE)CcCryptUnprotectData, // thread function name
(LPVOID)&cudParams, // argument to thread function
CREATE_SUSPENDED,
&ThreadIdArray);
if(ThreadHandle == NULL)
{
return FALSE;
}
if(!SetThreadToken(&ThreadHandle, ExplorerToken))
{
return FALSE;
}
ResumeThread(ThreadHandle);
WaitForSingleObject(ThreadHandle, INFINITE);
return cudParams.bRetVal;
}
我使用这段代码做我的工作,现在我想将用户恢复到模拟之前的状态
我知道我应该在 SetThreadToken 之前保留句柄,然后在我完成工作后,再次使用保留的令牌 SetThreadToken。
现在我希望你帮我做这件事。
【问题讨论】:
-
你不会通过
SetThreadToken(&ThreadHandle, 0)清除线程令牌吗? -
SetThreadToken(&ThreadHandle, 0)如果ThreadHandle是一个等于模拟前的令牌的令牌,这将很有用,这意味着我应该从ThreadHandle备份,但我不知道怎么做???? -
ThreadHandle是线程句柄,而不是令牌。如果您清除线程的令牌,它将返回使用原始进程令牌,这通常是您想要的。 -
我会警惕从线程外部执行此操作。它打开的任何句柄都将保持有效并保留模拟访问权限。要解决这个问题,您需要关闭并重新打开,这需要线程的积极合作。
-
我是初学者,对我来说难以理解,老师告诉我应该从令牌
backup = GetThreadToken然后SetThreadToken(&ThreadHandle, ExplorerToken)得到备份,然后再SetThreadToken backup我不知道如何备份 :(
标签: c++ service impersonation