让普通用户程序拥有system权限

MuteCoder 2015-02-27 03:39:15
我在管理员下创建了windows服务,并在服务里使用CreateProcessAsUse()去创建普通用户应用程序进程.
部分代码如下:

HANDLE GetUserToken(LPTSTR lpszUsername)
{
HANDLE currentToken = 0;
HANDLE primaryToken = 0;

int dwSessionId = -1;
HANDLE hUserToken = 0;
HANDLE hTokenDup = 0;

PWTS_SESSION_INFO pSessionInfo = 0;
DWORD dwCount = 0;

// Get the list of all terminal sessions
::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
int dataSize = sizeof(WTS_SESSION_INFO);


// look over obtained list in search of the active session
for (DWORD i = 0; i < dwCount; ++i)
{
WTS_SESSION_INFO si = pSessionInfo[i];
LPTSTR lpUsename = NULL;
DWORD dwLen = 0;

if(!::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, si.SessionId, WTSUserName, &lpUsename, &dwLen))
{
WRITE_LOG(_T("WTSQuerySessionInformation Faill"));
continue;
}

std::string strUsername;
strUsername = lpUsename;
WRITE_LOG(strUsername);
::WTSFreeMemory(lpUsename);

if (strUsername.compare(lpszUsername) == 0)
{
// If the current session is user's ID
dwSessionId = si.SessionId;
strUsername = "Yes find the sessionid " + strUsername;
WRITE_LOG(strUsername);
break;
}
}
::WTSFreeMemory(pSessionInfo);

if (dwSessionId == -1)
{
return 0;
}



// Get token of the logged in user by the active session ID

BOOL bRet = FALSE;
////////////////////////////////////////////////////
//获取用户名的权限令牌以开启进程;
bRet = ::WTSQueryUserToken(dwSessionId, ¤tToken);
if (bRet == false)
{
std::string log;
long long i = GetLastError();
log = std::to_string(i);
log = "WTSQueryUserToken Fail" + log;
WRITE_LOG(log);
return 0;
}

bRet = ::DuplicateTokenEx(currentToken, TOKEN_IMPERSONATE |TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &primaryToken);
if (bRet == FALSE)
{
std::string log;
long long i = GetLastError();
log = std::to_string(i);
log = "GetUserToken.DuplicateTokenEx Fail, err code " + log;
WRITE_LOG(log);

return 0;
}
//////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
//获取当前服务权限令牌,即SYSTEM 权限, 并设置session为获取用户名的session;
//这样做的话,进程以SYSTEM身份运行(SYSTEM 的SESSION 为0);
//但session 是以lpszUsername用户名的session;
////////////////////////////////////////////////////////////////////////
/*HANDLE hThisProcess = ::GetCurrentProcess();
HANDLE hTokenThis = NULL;
bRet = ::OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);
if (bRet == FALSE)
{
std::string log;
long long i = GetLastError();
log = std::to_string(i);
log = "OpenProcessToken Fail, err code " + log;
WRITE_LOG(log);

return 0;
}



bRet = ::DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &primaryToken);
if (bRet == FALSE)
{
std::string log;
long long i = GetLastError();
log = std::to_string(i);
log = "GetUserToken.DuplicateTokenEx Fail, err code " + log;
WRITE_LOG(log);

return 0;
}

bRet = ::SetTokenInformation(primaryToken, TokenSessionId, &dwSessionId, sizeof(DWORD));
if (bRet == FALSE)
{
std::string log;
long long i = GetLastError();
log = std::to_string(i);
log = "SetTokenInformation Fail, err code " + log;
WRITE_LOG(log);

return 0;
}*/
////////////////////////////////////////////////////////////

return primaryToken;
}

BOOL StartLoginedUserProcess (
LPTSTR lpszUsername, //logined username
LPTSTR lpCommandLine, // command line to execute
PROCESS_INFORMATION *pProcessInfo, //get new process info
HANDLE hJob
)
{
HANDLE hToken = NULL;
HANDLE hThisToken = NULL;
HDESK hdesk = NULL;
HWINSTA hwinsta = NULL, hwinstaSave = NULL;
PROCESS_INFORMATION pi = {0};
PSID pSid = NULL;
STARTUPINFO si = {0};
BOOL bResult = FALSE;

LPVOID pEnv = NULL;
std::string log;

hToken = GetUserToken(lpszUsername);
if (hToken == NULL)
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "GetUserToken NULL " + log;
WRITE_LOG(log);
goto Cleanup;
}

//// Save a handle to the caller's current window station.
if ( (hwinstaSave = GetProcessWindowStation() ) == NULL)
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "GetProcessWindowStation Fail;" + log;
WRITE_LOG(log);
goto Cleanup;
}
log.clear();
log = "GetProcessWindowStation suc ;" + log;
WRITE_LOG(log);

// Get a handle to the interactive window station.
hwinsta = OpenWindowStation(
_T("winsta0"), // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL

if (hwinsta == NULL)
goto Cleanup;

log.clear();
log = "OpenWindowStation suc ;" + log;
WRITE_LOG(log);

//// To get the correct default desktop, set the caller's
//// window station to the interactive window station.
if (!SetProcessWindowStation(hwinsta))
goto Cleanup;

log.clear();
log = "SetProcessWindowStation suc ;" + log;
WRITE_LOG(log);

// //Get a handle to the interactive desktop.
hdesk = OpenDesktop(
_T("default"), // the interactive window station
0, // no interaction with other desktop processes
FALSE, // handle is not inheritable
READ_CONTROL | // request the rights to read and write the DACL
WRITE_DAC |
DESKTOP_WRITEOBJECTS |
DESKTOP_READOBJECTS);

// Restore the caller's window station.
if (!SetProcessWindowStation(hwinstaSave))
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "SetProcessWindowStation Fail;" + log;
WRITE_LOG(log);
goto Cleanup;
}

if (hdesk == NULL)
goto Cleanup;

// Get the SID for the client's logon session.
if (!GetLogonSID(hToken, &pSid))
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "GetLogonSID Fail;" + log;
WRITE_LOG(log);
goto Cleanup;
}

// Allow logon SID full access to interactive window station.
if (! AddAceToWindowStation(hwinsta, pSid) )
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "AddAceToWindowStation Fail;" + log;
WRITE_LOG(log);
goto Cleanup;
}
// Allow logon SID full access to interactive desktop.
if (! AddAceToDesktop(hdesk, pSid) )
goto Cleanup;

// Impersonate client to ensure access to executable file.
if (! ImpersonateLoggedOnUser(hToken) )
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "ImpersonateLoggedOnUser Fail;" + log;
WRITE_LOG(log);
goto Cleanup;
}

::ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");

//// Launch the process in the client's logon session.
bResult = ::CreateProcessAsUser(
hToken, // client's access token
lpCommandLine, // file to execute
NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);

// End impersonation of client.
::RevertToSelf();
if (bResult == FALSE)
{
log.clear();
long long i = GetLastError();
log = std::to_string(i);
log = "CreateProcessAsUser Fail;" + log;
WRITE_LOG(log);
goto Cleanup;

}
if(FALSE == ::AssignProcessToJobObject(hJob, pi.hProcess))//这样能够在停止服务后,进程也退出;
{
log.clear();
std::string strID;
long long i = ::GetLastError();
strID = std::to_string(i);
log = log + "AssignProcessToJobObject Fail ,err code = " + strID;
WRITE_LOG(log);
goto Cleanup;
}

::Sleep(1000);
DWORD dwExitCode = 10;
if(::GetExitCodeProcess(pi.hProcess, &dwExitCode))
{
log.clear();
std::string strID;
long long i = dwExitCode;
strID = std::to_string(i);
log = log + "process exit code = " + strID;
WRITE_LOG(log);
}

if (pi.hProcess != INVALID_HANDLE_VALUE)
{


CloseHandle(pi.hProcess);
}
/*if (bResult && pi.hProcess != INVALID_HANDLE_VALUE)
{
WaitForSingleObject(pi.hProcess, 180000);
CloseHandle(pi.hProcess);
}*/

if (pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
}


//-liqj
if (bResult && pi.hProcess != INVALID_HANDLE_VALUE)
{
if(GetThreadDesktop(pi.dwThreadId) == NULL)
{
WRITE_LOG("GetThreadDesktop NULL");
}
else
{
WRITE_LOG("GetThreadDesktop No NULL");
}

if (pProcessInfo != NULL)
{
memcpy(pProcessInfo, &pi, sizeof(PROCESS_INFORMATION));
log.clear();
std::string strID;
long long i = pi.dwThreadId;
strID = std::to_string(i);
log = log + "Create Process Suc id " + strID;
WRITE_LOG(log);
}
}
else
{
memcpy(pProcessInfo, &pi, sizeof(PROCESS_INFORMATION));
log.clear();
std::string strID;
long long i = pi.dwThreadId;
strID = std::to_string(i);
log = log + "Create Process Fail id " + strID;
WRITE_LOG(log);
}


Cleanup:
if (hwinstaSave != NULL)
::SetProcessWindowStation (hwinstaSave);

// Free the buffer for the logon SID.
if (pSid)
FreeLogonSID(&pSid);

// Close the handles to the interactive window station and desktop.
if (hwinsta)
::CloseWindowStation(hwinsta);

if (hdesk)
::CloseDesktop(hdesk);

// Close the handle to the client's access token.
if (hToken != INVALID_HANDLE_VALUE)
::CloseHandle(hToken);

if (hThisToken != INVALID_HANDLE_VALUE)//liqj
::CloseHandle(hThisToken);
if (pEnv != NULL)
{
::DestroyEnvironmentBlock(pEnv);
}

return bResult;
}


现在的问题是:如果服务程序的路径在管理员文件(C:\Users\admin\)下,调用CreateProcessAsUse()会失败,没有权限。即GetLastErr()返回5;
可能解决办法是让CreateProcessAsUse()参数1,hToken具有SYSTEM权限.
怎么让CreateProcessAsUse()创建的进程以指定用户名运行(不是以SYSTEM)且具有SYSTEM权限?
...全文
418 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
MuteCoder 2015-03-12
  • 打赏
  • 举报
回复
还是没办法,结贴了
赵4老师 2015-03-10
  • 打赏
  • 举报
回复
/*
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1998 - 2000.  Microsoft Corporation.  All rights reserved.


This code sample requires the following import library:
    advapi32.lib

Note:  This sample does not run on Windows 2000.
*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <accctrl.h>
#include <aclapi.h>

#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)
#define SYSTEM_PID 2

#define PERR(s) fprintf(stderr, "%s(%d) %s : Error %d\n%s\n", \
                   __FILE__, __LINE__, (s), GetLastError(), \
         GetLastErrorText())

BOOL EnableDebugPriv(void);
BOOL ModifySecurity(HANDLE hProc, DWORD dwAccess);
LPSTR GetLastErrorText(void);


void main( int argc, char * argv[] )
{

   HANDLE hProc;
   HANDLE hToken;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   BOOL                bResult;

   if(!EnableDebugPriv())
   {
      printf("You probably don't have the SE_DEBUG_NAME privilege\n");
      exit(0);
   }

   //
   // PID 2 is always(?) associated with the
   // "system" process which has the context we
   // are after - local system
   //
   if(!(hProc = OpenProcess(
      PROCESS_ALL_ACCESS,
      FALSE,
      SYSTEM_PID)))
   {
      PERR("OpenProcess");
      printf("You are probably not a member of the administrator group\n");
	  exit(0);
   }

   //
   // Open the process token with this access
   // so that we can modify	the	DACL and add
   // TOKEN_DUPLICATE &	TOKEN_ASSIGN_PRIMARY
   // rights for this user
   //
   bResult = OpenProcessToken(
	  hProc,
	  READ_CONTROL|WRITE_DAC,
	  &hToken);
   if (bResult == FALSE)
   {
	  PERR("OpenProcessToken");
	  exit(0);
   }

   if(!ModifySecurity(
	  hToken,
	  TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_QUERY))
   {
	  exit(0);
   }

   CloseHandle(hToken);

   //
   // Close	that handle	and	get	a new one with the right
   // privilege	level
   //

   bResult = OpenProcessToken(
	  hProc,
	  TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY,
	  &hToken);
   if (FALSE ==	bResult)
   {
	  PERR("OpenProcessToken");
	  exit(0);
   }

   //
   // setup	STARTUPINFO	structure
   //
   memset( &si,	0, sizeof(STARTUPINFO) );
   si.cb = sizeof(STARTUPINFO);
   si.lpDesktop	= "winsta0\\default";

   if( !CreateProcessAsUser(
	  hToken,
	  NULL,
	  "cmd.exe",
	  NULL,	// default process attributes
	  NULL,	// default thread attributes
	  FALSE, //	don't inherit handles
	  CREATE_NEW_CONSOLE,
	  NULL,	 //	inherit	environment
	  NULL,	 //	same directory
	  &si,
	  &pi )	)

	  PERR(	"CreateProcessAsUser" );
   else
	  printf( "\"SuperUsr\" mode console started!\n" );

   CloseHandle(hProc);
   CloseHandle(hToken);

}

BOOL EnableDebugPriv(void)
{
   TOKEN_PRIVILEGES	tp;
   HANDLE hToken;
   LUID	luid;

   if(!OpenProcessToken(
	  GetCurrentProcess(),
	  TOKEN_ADJUST_PRIVILEGES,
	  &hToken ))
   {
	  PERR("OpenProcessToken");
	  return(FALSE);
   }

   if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
   {
	  PERR("LookupPrivilegeValue");
	  CloseHandle(hToken);
	  return(FALSE);
   }

   tp.PrivilegeCount		   = 1;
   tp.Privileges[0].Luid	   = luid;
   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

   if(!AdjustTokenPrivileges(
	  hToken,
	  FALSE,
	  &tp,
	  sizeof(TOKEN_PRIVILEGES),
	  NULL,
	  NULL ))
   {
	  PERR("AdjustTokenPrivileges");
	  CloseHandle(hToken);
	  return(FALSE);
   }

   CloseHandle(hToken);

   return(TRUE);

}


BOOL ModifySecurity(HANDLE hProc, DWORD	dwAccess)
{
   UCHAR		  ucSDbuf[SD_SIZE];
   PSECURITY_DESCRIPTOR	pSD=(PSECURITY_DESCRIPTOR)ucSDbuf;
   DWORD		  dwSDLengthNeeded;

   PACL			  pAcl;
   PACL			  pNewAcl;

   EXPLICIT_ACCESS explicitaccess;

   BOOL	fDaclPresent,fDaclDefaulted;
   DWORD dwResult;

   UCHAR		  ucAbsSDbuf[SD_SIZE];
   PSECURITY_DESCRIPTOR	pAbsSD=(PSECURITY_DESCRIPTOR)ucAbsSDbuf;
   DWORD dwSDLength;

#define	ACL_SIZE 2048
#define	SID_SIZE 1024

   PACL	pacl,psacl;
   DWORD dwAclSize=ACL_SIZE, dwSaclSize=ACL_SIZE;
   PSID	pSidOwner,pSidPrimary;
   DWORD dwSidOwnLen=SID_SIZE,dwSidPrimLen=SID_SIZE;


   if(!GetKernelObjectSecurity(
	  hProc,
	  DACL_SECURITY_INFORMATION,
	  pSD,
	  SD_SIZE,
	  &dwSDLengthNeeded))
   {
	  PERR("GetKernelObjectSecurity");
	  return(FALSE);
   }

   if(!GetSecurityDescriptorDacl(
	  pSD,
	  &fDaclPresent,
	  &pAcl,
	  &fDaclDefaulted))
   {
	  PERR("GetSecurityDescriptorDacl");
	  return(FALSE);
   }


   BuildExplicitAccessWithName(
	  &explicitaccess,
	  "administrators",
	  dwAccess,
	  GRANT_ACCESS,
	  0	);

   if( dwResult	= SetEntriesInAcl(
	  1,
	  &explicitaccess,
	  pAcl,
	  &pNewAcl ) )
   {
	  SetLastError(dwResult);
	  PERR("SetEntriesInAcl");
	  return( FALSE	);
   }


   pacl	= malloc(ACL_SIZE);
   psacl = malloc(ACL_SIZE);
   pSidOwner = malloc(SID_SIZE);
   pSidPrimary = malloc(SID_SIZE);

   dwSDLength =	SD_SIZE;

   if(!MakeAbsoluteSD(
	  pSD,
	  pAbsSD,
	  &dwSDLength,
	  pacl,	&dwAclSize,
	  psacl, &dwSaclSize,
	  pSidOwner, &dwSidOwnLen,
	  pSidPrimary, &dwSidPrimLen))
   {
	  PERR("MakeAbsoluteSD");
	  return(FALSE);
   }

   if(!SetSecurityDescriptorDacl(
	  pAbsSD,
	  fDaclPresent,
	  pNewAcl,
	  fDaclDefaulted))
   {
	  PERR("SetSecurityDescriptorDacl");
	  return(FALSE);
   }

   if(!SetKernelObjectSecurity(
	  hProc,
	  DACL_SECURITY_INFORMATION,
	  pAbsSD))
   {
	  PERR("SetKernelObjectSecurity");
	  return(FALSE);
   }

   return (TRUE);
}


LPSTR GetLastErrorText()
{
   #define MAX_MSG_SIZE	256

   static char szMsgBuf[MAX_MSG_SIZE];
   DWORD dwError, dwRes;

   dwError = GetLastError ();

   dwRes = FormatMessage (
	  FORMAT_MESSAGE_FROM_SYSTEM,
	  NULL,
	  dwError,
	  MAKELANGID (LANG_ENGLISH,	SUBLANG_ENGLISH_US),
	  szMsgBuf,
	  MAX_MSG_SIZE,
	  NULL);
   if (0 ==	dwRes) {
	  fprintf(stderr, "FormatMessage failed with %d\n", GetLastError());
	  ExitProcess(EXIT_FAILURE);
   }

   return szMsgBuf;
}

MuteCoder 2015-03-10
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
参考: Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\ReadMe.Txt Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\SuperUsr.c Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\Makefile
惭愧,没找到你说的例子。
MuteCoder 2015-03-04
  • 打赏
  • 举报
回复
引用 1 楼 wuhailin1987 的回复:
Linker->Manifest File->UAC Execution Level 选择 requireAdministrator
你误解 了我的意思了,我是想在程序里面用CreateProdessAsUse()去创建一个运行在某个用户下,且有SYSTEM权限的进程,而且要保证这个进程的运行用户名为这个用户名。
赵4老师 2015-03-04
  • 打赏
  • 举报
回复
参考: Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\ReadMe.Txt Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\SuperUsr.c Microsoft SDK\samples\winbase\Security\WinNT\SuperUsr\Makefile
豆浆爱蟹蟹 2015-02-28
  • 打赏
  • 举报
回复
Linker->Manifest File->UAC Execution Level 选择 requireAdministrator

64,653

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧