Link to home
Start Free TrialLog in
Avatar of jhshukla
jhshuklaFlag for United States of America

asked on

Impersonate as SYSTEM

I want to access files stored under "X:\System Volume Information" but I cannot do so even with Admin provoleges. I have seen virus scanners (McAfee to be specific) scan that folder even when a "User" is loggen on. I bet the process runs with SYSTEM privileges - a bit higher than Admin. How can I impersonate the SYSTEM account?

the actual goal is to read file information from that folder. so if there is a way to access that info without impersonation that would be much better from security standpoint. I am looking for a solution in .NET but C/C++ would work.
Avatar of jkr
jkr
Flag of Germany image

>>How can I impersonate the SYSTEM account?

The easiest way would IMO be a small service that - by default - runs as 'LocalSystem' to gather that information. Youcould also obtain a token from a process that is running under that account(services.exe or svchost.exe is a good choice <s>). You'll need the PID to call 'OpenProcess()', then 'OpenProcessToken()' with 'TOKEN_IMPERSONATE' access. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q175030 ("HOWTO: Enumerate Applications Using Win32 APIs (Q175030)") on how to get that PID - it comes with sample code. Then, once you have the token, you have to call 'ImpersonateLoggedOnUser()', et voilà, you are there.
Avatar of jhshukla

ASKER

ok that makes sense. is there a way to impersonate the SYSTEM without getting a list of processes?
I got to the point where i can get process handles from PID but OpenProcessToken fails with GetLastError = 5 (Access denied). here is relevant code (C#):
            private void Impersonate()
            {
                  int pid = GetSystemPID();

                  const int TOKEN_IMPERSONATE = 0x0004; // copied from WinNT.h
                  const int READ_CONTROL = 0x00020000; // copied from WinNT.h
                  const int PROCESS_QUERY_INFORMATION = 0x0040; // copied from WinNT.h
                  int tokenHandle = 0;
                  int proc = OpenProcess(READ_CONTROL | PROCESS_QUERY_INFORMATION, false, pid);
                  bool returnValue = OpenProcessToken(proc, TOKEN_IMPERSONATE, ref tokenHandle);
                  if ( returnValue == true )
                  {
                        MessageBox.Show("Token Obtained");
                  }
                  else
                  {
                        MessageBox.Show(String.Format("Error {0}", GetLastError()));
                  }
                  ...
            }

            private int GetSystemPID()
            {
                  System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses(); // lists ALL running processes, even those that don't appear in TaskMgr
                  for ( int i=0; i<procs.Length; i++ )
                  {
                        if ( procs[i].ProcessName.CompareTo("System") == 0) // THE system process other than SysIdleProc. PID = 4
                              return procs[i].Id;
                  }
                  return -1;
            }
one more piece of info. gives me the same error even if i try to get the token from the current process.
Hm, what account are you running that under?

Also, would be using a service too much effort?
Admin account, and where did i say i run a service? it is just a regular .NET application.
>>and where did i say i run a service?

Nowhere, I brought that up earlier, since services run under 'LocalSystem' natively and therefore can access that directory.
yes it would be too much effort. this program just reads and reports disk usage for all folders on given drive. too much effort to run the program. not too much to change the settings to make a service.
another thing that is noticed was that mcconsol.exe (GUI to McAfee) ran as admin and was still able to access SysVolInfo. I wonder if it was using a service to get raw data.
I had to combine TOKEN_IMPERSONATE | TOKEN_QUERY to get the token for a process. I can impersonate as admin through any other process started by admin but I am still unable to impersonate as the localsystem.
Bad news here, too. I did some experiments (even though I did not mention that here, sorry) and checked some earlier projects, but the security set on that process does not seem to allow to get an impersonation token even from a process that runs as admin. What I did in the past to overcome that all ends up with having a service running and communicate with that one, so that ends up in a circle...
okay, I do not plan to release the prog to anyone else. it will be running only on my machine and i know that i will have certain services running all the time. is it possible to impersonate the system using token from any other process? i haven't had luck so far. I have been requesting minimal privileges:

      HANDLE hProc = OpenProcess(READ_CONTROL | PROCESS_QUERY_INFORMATION, false, PID);
      retVal = OpenProcessToken(hProc, TOKEN_IMPERSONATE | TOKEN_QUERY | STANDARD_RIGHTS_READ, &hToken);
another thought. what if i create an on-demand service? will that service run with localsystem privileges? what i plan to do is create a launcher application that will start the service and the service will do whatever my original application was supposed to do.
ASKER CERTIFIED SOLUTION
Avatar of rbvoigt
rbvoigt

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
>>what if i create an on-demand service? will that service run with localsystem privileges?

Yes, that's what I am having in mind and currently am working on... it's just not non-trivial, and I am quite busy, so bear with me.
>> Easiest way to impersonate system is with the built-in scheduler service.
>> Just run at (current time + 2 minutes) /interactive cmd.exe
how? where?

>> it's just not non-trivial
do two negations mean it is trivial?
Avatar of rbvoigt
rbvoigt

The command called "at"....


The AT command schedules commands and programs to run on a computer at
a specified time and date. The Schedule service must be running to use
the AT command.

AT [\\computername] [ [id] [/DELETE] | /DELETE [/YES]]
AT [\\computername] time [/INTERACTIVE]
    [ /EVERY:date[,...] | /NEXT:date[,...]] "command"

\\computername     Specifies a remote computer. Commands are scheduled on the
                   local computer if this parameter is omitted.
id                 Is an identification number assigned to a scheduled
                   command.
/delete            Cancels a scheduled command. If id is omitted, all the
                   scheduled commands on the computer are canceled.
/yes               Used with cancel all jobs command when no further
                   confirmation is desired.
time               Specifies the time when command is to run.
/interactive       Allows the job to interact with the desktop of the user
                   who is logged on at the time the job runs.
/every:date[,...]  Runs the command on each specified day(s) of the week or
                   month. If date is omitted, the current day of the month
                   is assumed.
/next:date[,...]   Runs the specified command on the next occurrence of the
                   day (for example, next Thursday).  If date is omitted, the
                   current day of the month is assumed.
"command"          Is the Windows NT command, or batch program to be run.
isn't it equivalent to "scheduled task"?
thanks both of you guys.
The "at" command and scheduled tasks both use the scheduler service, but they give you different options.  I don't know any way using at to schedule for startup, shutdown, or idle, which you can do with the scheduled tasks property page.  At does let you run as SYSTEM and interact with the program graphically, which Scheduled Tasks doesn't/