📄 createprocessasuser.cpp
字号:
// for some reason, the service process hangs around for 20 seconds
// before exiting, which causes the deletion to lag for the same amount of time.
}
SERVICE_STATUS_HANDLE g_hss;
SERVICE_STATUS g_ss;
void WINAPI Handler( DWORD )
{
SetServiceStatus( g_hss, &g_ss );
}
void WINAPI ServiceMain( DWORD argc, wchar_t* argv[] )
{
g_ss.dwCurrentState = SERVICE_RUNNING;
g_ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
g_hss = RegisterServiceCtrlHandler( L"AsPrincipal", Handler );
SetServiceStatus( g_hss, &g_ss );
bool fAsSystem = false;
bool fAsAppID = false;
bool fAsInteractive = false;
bool fEqualToInteractive = false;
if (_wcsnicmp(argv[1], L"-s",2)==0) fAsSystem = true;
HANDLE hptoken = INVALID_HANDLE_VALUE;
DWORD dwErr = 0;
LPCWSTR szwDescr = NULL;
do {
if (!fAsSystem) {
LPWSTR szcwUser = NULL;
LPWSTR szcwDomain = NULL;
LPWSTR szcwPassword = NULL;
LPWSTR szcwAppID = NULL;
WCHAR szwPassword[MAX_PATH], szwUserName[MAX_PATH], szwUserDomain[MAX_PATH];
memset(szwPassword,0,sizeof(szwPassword));
memset(szwUserName,0,sizeof(szwUserName));
memset(szwUserDomain,0,sizeof(szwUserDomain));
for (DWORD i = 1; i < argc; i++) {
if (_wcsnicmp(argv[i], L"-d",2)==0) szcwDomain = argv[i]+2;
else if (_wcsnicmp(argv[i], L"-u",2)==0) szcwUser = argv[i]+2;
else if (_wcsnicmp(argv[i], L"-p",2)==0) szcwPassword = argv[i]+2;
else if (_wcsnicmp(argv[i], L"-a",2)==0) szcwAppID = argv[i]+2;
else if (_wcsnicmp(argv[i], L"-i",2)==0) fAsInteractive = true;
if (i == 3) break;
if (szcwAppID) break;
if (fAsInteractive) break;
}
if (szcwAppID) {
fAsAppID = true;
if (FAILED(dwErr = GetRunAsPassword(szcwAppID, MAX_PATH, szwPassword, MAX_PATH, szwUserName, MAX_PATH, szwUserDomain))) {
if (E_RUN_AS_INTERACTIVE == dwErr) {
fAsAppID = false;
fAsInteractive = true;
} else {szwDescr = L"Failed to retrieve AppID data"; break;}
} else {
szcwUser = szwUserName;
szcwDomain = szwUserDomain;
szcwPassword = szwPassword;
}
}
if (!fAsInteractive && !fAsAppID) {
wcscpy(szwUserName,szcwUser);
wcscpy(szwUserDomain, szcwDomain);
wcscpy(szwPassword, szcwPassword);
}
if (fAsInteractive) {
if (FAILED(dwErr = GetInteractiveUserToken(&hptoken, MAX_PATH, szwUserName, MAX_PATH, szwUserDomain))) {
szwDescr = L"Failed to retrieve token of shell process"; break;}
} else {
if (!LogonUser(szcwUser,szcwDomain,szcwPassword,
LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hptoken)) {
dwErr = GetLastError(), szwDescr = L"LogonUser failed"; break; }
HANDLE htmp;
memset(szwPassword, 0, sizeof(szwPassword));
szcwUser = szwPassword;
szcwDomain = szwPassword + MAX_PATH/2;
if (FAILED(dwErr = GetInteractiveUserToken(&htmp, MAX_PATH/2, szcwUser, MAX_PATH/2, szcwDomain))) {
szwDescr = L"Failed to retrieve token of shell process"; break;}
CloseHandle(htmp);
fEqualToInteractive = (_wcsicmp(szcwUser, szwUserName) == 0 && _wcsicmp(szcwDomain, szwUserDomain) == 0);
}
}
wchar_t cmd[MAX_CMD_LEN];
wchar_t* dst = cmd;
wchar_t* dstEnd = cmd + sizeof cmd / sizeof *cmd;
wchar_t** it = argv + ((fAsSystem ||fAsAppID||fAsInteractive)?2:4);
wchar_t** const end = it + argc - 1;
while ( end != it )
{
// add whitespace between args
if ( dst != cmd )
*dst++ = L' ';
// watch for overflow
const int cch = lstrlen( *it );
if ( dst + cch + 2 > dstEnd )
break;
// concatenate args
lstrcpy( dst, *it );
dst += cch;
++it;
}
*dst = '\0';
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.lpDesktop = (fAsInteractive || fEqualToInteractive || fAsSystem)?NULL:
(hptoken!=INVALID_HANDLE_VALUE && (dwErr = GrantDesktopAccess(hptoken))==S_OK)?NULL:L"";
if (dwErr) szwDescr = L"GrantDesktopAccess failed";
PROCESS_INFORMATION pi;
if (INVALID_HANDLE_VALUE != hptoken) {
if (CreateProcessAsUser(hptoken, 0, cmd, 0, 0, FALSE, 0, 0, 0, &si, &pi ) ) {
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
} else dwErr = GetLastError(), szwDescr = L"CreateProcessAsUser failed";
hptoken = (CloseHandle(hptoken), INVALID_HANDLE_VALUE);
} else if ( CreateProcess( 0, cmd, 0, 0, FALSE, 0, 0, 0, &si, &pi ) ) {
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
} else dwErr = GetLastError(), szwDescr = L"CreateProcess failed";
} while(false);
if (dwErr) {
HANDLE h;
if (hptoken != INVALID_HANDLE_VALUE) hptoken = (CloseHandle(hptoken), INVALID_HANDLE_VALUE);
h = RegisterEventSource(NULL, L"AsPrincipal");
if (h != NULL) {
ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, dwErr, NULL, (szwDescr)?1:0, 0, (szwDescr)?&szwDescr:NULL,NULL);
DeregisterEventSource(h);
}
}
g_ss.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus( g_hss, &g_ss );
}
void wmain( int argc, wchar_t* argv[] )
{
if (1 < argc) {
int fCheckParams = 0;
for (int i = 1; i < argc; i++) {
if (_wcsnicmp(argv[i], L"-s",2)==0) fCheckParams |= 0x8;
else if (_wcsnicmp(argv[i], L"-d",2)==0) fCheckParams |= 0x1;
else if (_wcsnicmp(argv[i], L"-u",2)==0) fCheckParams |= 0x2;
else if (_wcsnicmp(argv[i], L"-p",2)==0) fCheckParams |= 0x4;
else if (_wcsnicmp(argv[i], L"-a",2)==0) fCheckParams |= 0x10;
else if (_wcsnicmp(argv[i], L"-i",2)==0) fCheckParams |= 0x20;
if ( fCheckParams==0x8 && i > 1) break; //if second param is not any of -d -u -p than break;
else if (fCheckParams==0x10 && i > 1) break;
else if (fCheckParams==0x20 && i > 1) break;
else if (fCheckParams == 0x7) break;
else if (i > 3) break;
}
if (fCheckParams != 0x8 && fCheckParams != 0x7 && fCheckParams != 0x10 && fCheckParams!=0x20) PrintUsageAndQuit();
} else if ( 1 == argc ) {
// try to detect whether we are being launched by the SCM
// or by the interactive user, who should have passed cmd line args
if ( !IsLocalSystem() )
PrintUsageAndQuit();
SERVICE_TABLE_ENTRY ste[] = {
{ L"AsPrincipal", ServiceMain },
{ 0, 0 }
};
StartServiceCtrlDispatcher( ste );
return;
}
if ( !IsAdmin() )
Quit( L"You must be a member of the local Administrator's group to run this program" );
StartAsService( argc - 1, (const wchar_t**)argv + 1 );
}
HRESULT RetrieveLogonSid(HANDLE hToken,PSID *pLogonSid)
{
PTOKEN_GROUPS ptgGroups = NULL;
DWORD cbBuffer = 0;
DWORD dwSidLength;
UINT i;
HRESULT hr=S_OK;
__try {
*pLogonSid = NULL;
GetTokenInformation(hToken, TokenGroups, ptgGroups, cbBuffer, &cbBuffer);
if (cbBuffer && !(ptgGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuffer))) return hr = E_OUTOFMEMORY;
if (!GetTokenInformation(hToken,TokenGroups,ptgGroups,cbBuffer,&cbBuffer)) return hr = GetLastError();
// Get the logon Sid by looping through the Sids in the token
for(i = 0 ; i < ptgGroups->GroupCount ; i++) {
if (ptgGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) {
if (!IsValidSid(ptgGroups->Groups[i].Sid)) return hr = E_FAIL;
dwSidLength=GetLengthSid(ptgGroups->Groups[i].Sid);
if((*pLogonSid = (PSID)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidLength)) == NULL) return hr = E_OUTOFMEMORY;
if (!CopySid(dwSidLength,*pLogonSid,ptgGroups->Groups[i].Sid)) return hr = GetLastError();
return S_OK;
}
}
return hr = E_INVALIDARG;
} __finally {
if (hr != S_OK) {
if(*pLogonSid != NULL) {
HeapFree(GetProcessHeap(), 0, *pLogonSid);
*pLogonSid = NULL;
}
}
if (ptgGroups != NULL) HeapFree(GetProcessHeap(), 0, ptgGroups);
}
return E_UNEXPECTED;
}
HRESULT InsertSidInAcl(PSID pSid,PACL pAclSource,PACL *pAclDestination,DWORD AccessMask,bool bAddSid,bool bFreeOldAcl)
{
ACL_SIZE_INFORMATION AclInfo;
DWORD dwNewAclSize;
LPVOID pAce;
DWORD AceCounter;
HRESULT hr=S_OK;
__try {
if (pAclSource == NULL) {
*pAclDestination = NULL;
return S_OK;
}
if (!IsValidSid(pSid)) return hr = E_FAIL;
if (!GetAclInformation(pAclSource,&AclInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) return hr = GetLastError();
// Compute size for new ACL, based on addition or subtraction of ACE
if (bAddSid) dwNewAclSize = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
else dwNewAclSize = AclInfo.AclBytesInUse - sizeof(ACCESS_ALLOWED_ACE) - GetLengthSid(pSid) + sizeof(DWORD);
*pAclDestination = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize);
if (*pAclDestination == NULL) return hr = E_OUTOFMEMORY;
if (!InitializeAcl(*pAclDestination, dwNewAclSize, ACL_REVISION)) return hr = GetLastError();
// copy existing ACEs to new ACL
for(AceCounter = 0 ; AceCounter < AclInfo.AceCount ; AceCounter++) {
if (!GetAce(pAclSource, AceCounter, &pAce)) return hr = GetLastError();
if (!bAddSid) {
// we only care about ACCESS_ALLOWED ACEs
if ((((PACE_HEADER)pAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE) {
PSID pTempSid=(PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
if (EqualSid(pSid, pTempSid)) continue;
}
}
if (!AddAce(*pAclDestination,ACL_REVISION,0,pAce,((PACE_HEADER)pAce)->AceSize)) return hr = GetLastError();
}
if (bAddSid && !AddAccessAllowedAce(*pAclDestination,ACL_REVISION,AccessMask,pSid)) return hr = GetLastError();
return S_OK;
} __finally {
if (hr != S_OK) {
if(*pAclDestination != NULL) HeapFree(GetProcessHeap(), 0, *pAclDestination);
} else if (bFreeOldAcl) HeapFree(GetProcessHeap(), 0, pAclSource);
}
return E_UNEXPECTED;
}
HRESULT AdjustWinstaDesktopSecurity(HWINSTA hWinsta, HDESK hDesktop, PSID pLogonSid, bool bGrant, HANDLE hToken)
{
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
PSECURITY_DESCRIPTOR sdDesktop = NULL;
PSECURITY_DESCRIPTOR sdWinsta = NULL;
SECURITY_DESCRIPTOR sdNewDesktop;
SECURITY_DESCRIPTOR sdNewWinsta;
DWORD sdDesktopLength = 0; /* allocation size */
DWORD sdWinstaLength = 0; /* allocation size */
PACL pDesktopDacl; /* previous Dacl on Desktop */
PACL pWinstaDacl; /* previous Dacl on Winsta */
PACL pNewDesktopDacl = NULL; /* new Dacl for Desktop */
PACL pNewWinstaDacl = NULL; /* new Dacl for Winsta */
BOOL bDesktopDaclPresent;
BOOL bWinstaDaclPresent;
BOOL bDaclDefaultDesktop;
BOOL bDaclDefaultWinsta;
HRESULT hr = S_OK;
PSID pUserSid = NULL;
__try {
GetUserObjectSecurity(hDesktop, &si, sdDesktop, sdDesktopLength, &sdDesktopLength);
if (sdDesktopLength) sdDesktop = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sdDesktopLength);
if (!GetUserObjectSecurity(hDesktop,&si,sdDesktop,sdDesktopLength,&sdDesktopLength)) return GetLastError();
GetUserObjectSecurity(hWinsta,&si,sdWinsta,sdWinstaLength,&sdWinstaLength);
if (sdWinstaLength) sdWinsta = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sdWinstaLength);
if (!GetUserObjectSecurity(hWinsta,&si,sdWinsta,sdWinstaLength,&sdWinstaLength)) return GetLastError();
if (!GetSecurityDescriptorDacl(sdDesktop,&bDesktopDaclPresent, &pDesktopDacl, &bDaclDefaultDesktop)) return GetLastError();
if (!GetSecurityDescriptorDacl(sdWinsta,&bWinstaDaclPresent,&pWinstaDacl,&bDaclDefaultWinsta)) return GetLastError();
// Create new DACL with Logon and User Sid for Desktop
if(bDesktopDaclPresent && (hr = InsertSidInAcl(pLogonSid,pDesktopDacl,&pNewDesktopDacl,
GENERIC_READ | GENERIC_WRITE | READ_CONTROL | DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW |
DESKTOP_CREATEMENU | DESKTOP_SWITCHDESKTOP | DESKTOP_ENUMERATE, bGrant,false)) != S_OK) return hr;
// Create new DACL with Logon and User Sid for Window station
if(bWinstaDaclPresent && (hr = InsertSidInAcl(pLogonSid,pWinstaDacl,&pNewWinstaDacl,
GENERIC_READ | GENERIC_WRITE | READ_CONTROL
| WINSTA_ACCESSGLOBALATOMS | WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES |
WINSTA_ACCESSCLIPBOARD | WINSTA_ENUMERATE | WINSTA_EXITWINDOWS, bGrant, false)) != S_OK) return hr;
// Initialize the target security descriptor for Desktop
if (bDesktopDaclPresent && !InitializeSecurityDescriptor(&sdNewDesktop, SECURITY_DESCRIPTOR_REVISION)) return GetLastError();
// Initialize the target security descriptor for Window station
if(bWinstaDaclPresent && !InitializeSecurityDescriptor(&sdNewWinsta,SECURITY_DESCRIPTOR_REVISION)) return GetLastError();
// Apply new ACL to the Desktop security descriptor
if(bDesktopDaclPresent && !SetSecurityDescriptorDacl(&sdNewDesktop,TRUE,pNewDesktopDacl,bDaclDefaultDesktop)) return GetLastError();
// Apply new ACL to the Window station security descriptor
if(bWinstaDaclPresent && !SetSecurityDescriptorDacl(&sdNewWinsta, TRUE, pNewWinstaDacl, bDaclDefaultWinsta)) return GetLastError();
// Apply security descriptors with new DACLs to Desktop and Window station
if (bDesktopDaclPresent && !SetUserObjectSecurity(hDesktop, &si,&sdNewDesktop)) return GetLastError();
if(bWinstaDaclPresent && !SetUserObjectSecurity(hWinsta,&si,&sdNewWinsta)) return GetLastError();
return S_OK;
}__finally{
if (sdDesktop != NULL) HeapFree(GetProcessHeap(), 0, sdDesktop);
if (sdWinsta != NULL) HeapFree(GetProcessHeap(), 0, sdWinsta);
if (pNewDesktopDacl != NULL) HeapFree(GetProcessHeap(), 0, pNewDesktopDacl);
if (pNewWinstaDacl != NULL) HeapFree(GetProcessHeap(), 0, pNewWinstaDacl);
}
return E_UNEXPECTED;
}
HRESULT GrantDesktopAccess(HANDLE hToken)
{
HWINSTA hWinsta = NULL;
HDESK hDesktop = NULL;
PSID pLogonSid = NULL;
HRESULT hr = E_FAIL;
__try {
if ((hr = RetrieveLogonSid(hToken, &pLogonSid))!=S_OK) return hr;
hWinsta=GetProcessWindowStation();
hDesktop=GetThreadDesktop(GetCurrentThreadId());
if (!SetHandleInformation(hDesktop, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) return GetLastError();
if (!SetHandleInformation(hWinsta, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) return GetLastError();
return AdjustWinstaDesktopSecurity(hWinsta, hDesktop, pLogonSid, true, hToken);
} __finally {
if(pLogonSid != NULL)
HeapFree(GetProcessHeap(), 0, pLogonSid);
}
return E_UNEXPECTED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -