Link to home
Start Free TrialLog in
Avatar of jploettner
jploettner

asked on

running an application with assumed local admin privileges / Shell Execute question

We have a corp environment and our user are not local administrators on the workstations.  We have a few applications that need to be run w/ local admin privileges so I'm attempting to make a launcher application what will launch another exe as the local administrator account on the workstation.  I Have the impersonation working but when i use CreateProcessAsUser i get an error saying "a required privilege is not held by the client" error.

I need this to work similarly to RunAs on XP :)  Any help is greatly appreciated ;)

here is what I have so far (from various places):
            HANDLE hToken;
            CString sLogin, sPwd, tmp;
            LPVOID lpMsgBuf= NULL;
            LPTSTR lpBuffer;
            lpBuffer = new char[MAX_PATH];
            DWORD dwSize = MAX_PATH + 1;      
            
            STARTUPINFO startup_info;
            PROCESS_INFORMATION process_information;
            
            sLogin = "localadmin"; // valid account
            sPwd = "password";

            GetUserName(lpBuffer, &dwSize); // shows currently logged in user
            cout << "(before) I am currently: " << lpBuffer << endl;
            
            if (!LogonUser((char*)(LPCTSTR)sLogin, NULL, (char*)(LPCTSTR)sPwd,
                  LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
            {
                   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                                 (LPTSTR) &lpMsgBuf,     0,     NULL);
                   tmp.Format("%s %s error logon: %s\n", sPwd, sLogin, lpMsgBuf);
                   cout << tmp << endl;
                   LocalFree(lpMsgBuf);
                   return nRetCode;
            }

            if (!ImpersonateLoggedOnUser(hToken))
            {
                   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                                 (LPTSTR) &lpMsgBuf,     0,     NULL);
                   tmp.Format("%s %s error impersonate: %s\n", sLogin, sPwd, lpMsgBuf);
                   cout << tmp << endl;
                   LocalFree(lpMsgBuf);
                   return nRetCode;
            }

            GetUserName(lpBuffer, &dwSize); // now shows localadmin
            cout << "(after)  I am currently: " << lpBuffer << endl;

            ZeroMemory(&process_information,sizeof(process_information));
            GetStartupInfo(&startup_info);
            startup_info.cb=sizeof(STARTUPINFO);

            if(!CreateProcessAsUser(hToken, "calc.exe", "",NULL,NULL,FALSE,
                  (DWORD)NULL,NULL,NULL,&startup_info,&process_information))
            {
                   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                                 (LPTSTR) &lpMsgBuf,     0,     NULL);
                   tmp.Format("%s %s error CreateProcessAsUser: %s\n", sLogin, sPwd, lpMsgBuf);
                   cout << (LPCTSTR)tmp << endl;
                   LocalFree(lpMsgBuf);
                   return nRetCode;
            }
Avatar of Nievergelt
Nievergelt
Flag of Switzerland image

Avatar of jkr
The avvount you want to call 'LogonUser()' from needs to hold the the SE_TCB_NAME (aka "SeTcbPrivilege" or "Act as part of the operating system") privilege. You will have to assign that, or it won't work. The docs on 'LogonUser()' mention that explicitly:

"The process that calls LogonUser must have the SE_TCB_NAME privilege. The privilege does not need to be enabled. The LogonUser function enables the privilege as necessary. If the calling process does not have this privilege, LogonUser fails and GetLastError returns ERROR_PRIVILEGE_NOT_HELD.

In some cases, the process that calls LogonUser must also have the SE_CHANGE_NOTIFY_NAME privilege enabled; otherwise, LogonUser fails and GetLastError returns ERROR_ACCESS_DENIED. This privilege is not required for the local system account or accounts that are members of the administrators group. By default, SE_CHANGE_NOTIFY_NAME is enabled for all users, but some administrators may disable it for everyone."
Avatar of jploettner
jploettner

ASKER

jkr:

Seems you are the one that usually saves me :)

I tried the SE_TCB_NAME susgestion, here is the error from console:
GetUserName(jploettner)
calling OpenProcessToken...
OpenProcessToken worked...
calling LogonUser...
LogonUser worked...
calling ImpersonateLoggedOnUser...
ImpersonateLoggedOnUser worked...
GetUserName(snowman)
calling CreateProcessAsUser...
==================================
Error Source: CreateProcessAsUser
Error       : A required privilege is not held by the client.
==================================
Press any key to continue

I tried with and with out the ImpersonateLoggedOnUser :(  I'de give you 1000 points for this one if i could, work is torturing me over it and stuck in the mud :P

here is the lastest source:
            CString sLogin, sPwd, tmp;
            LPVOID lpMsgBuf= NULL;
            LPTSTR lpBuffer;
            lpBuffer = new char[MAX_PATH];
            DWORD dwSize = MAX_PATH + 1;      
            
            STARTUPINFO startup_info;
            PROCESS_INFORMATION process_information;
            TOKEN_PRIVILEGES tkp;
            HANDLE hToken;

            sLogin = "snowman"; // local admin account
            sPwd = "mypassword";

            GetUserName(lpBuffer, &dwSize);
            cout << "GetUserName(" << lpBuffer << ")" << endl;

            cout << "calling OpenProcessToken..." << endl;
            if(OpenProcessToken(GetCurrentProcess(),
                  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            {
                  if (!LookupPrivilegeValue(NULL, SE_TCB_NAME, &tkp.Privileges[0].Luid))
                  {
                        showerror("LookUpPrivilegeValue");
                        return nRetCode;
                  }

                  tkp.PrivilegeCount = 1;
                  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
                  if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0))
                  {
                        showerror("AdjustTokenPrivileges");
                        return nRetCode;
                  }

                  cout << "OpenProcessToken worked..." << endl;
            }
            else
            {
                  showerror("OpenProcessToken");
                  return nRetCode;
            }

            cout << "calling LogonUser..." << endl;
            if (!LogonUser((char*)(LPCTSTR)sLogin, NULL, (char*)(LPCTSTR)sPwd,
                  LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
            {
                  showerror("LogonUser");
                  return nRetCode;
            }
            else
                  cout << "LogonUser worked..." << endl;

            cout << "calling ImpersonateLoggedOnUser..." << endl;
            if (!ImpersonateLoggedOnUser(hToken))
            {
                  showerror("ImpersonateLoggedOnUser");
                  return nRetCode;
            }
            else
                  cout << "ImpersonateLoggedOnUser worked..." << endl;
            
            GetUserName(lpBuffer, &dwSize);
            cout << "GetUserName(" << lpBuffer << ")" << endl;

            ZeroMemory(&process_information,sizeof(process_information));
            GetStartupInfo(&startup_info);
            startup_info.cb=sizeof(STARTUPINFO);

          char app[] = "calc.exe";
            cout << "calling CreateProcessAsUser..." << endl;
            if (!CreateProcessAsUser(hToken, app, "", NULL, NULL, TRUE, NULL, NULL,
                  "c:\\windows\\system32\\", &startup_info, &process_information))
            {  
                  showerror("CreateProcessAsUser");
                  return nRetCode;
            }
            else
            {
                  cout << "CreateProcessAsUser worked..." << endl;
                  
                  CloseHandle(process_information.hProcess);
                  CloseHandle(process_information.hThread);
            }

ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial