Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Service and Interactive Sessions



Permlink Replies: 8 - Last Post: Jun 20, 2017 11:33 AM Last Post By: Remy Lebeau (Te...
Yannick LANCHEC

Posts: 43
Registered: 1/21/01
Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 14, 2017 8:52 AM
Hi,

I need to make a service (running with SYSTEM account), and this service has to execute a 'visual' software (like Notepad.exe) in the session of each logged user.

This service must run also on a RDP server.

What is the best method to enumerate the active sessions (LsaEnumerateSession ? WTSEnumerateSessions ? ? ?)

What is the best solution to execute the software ? (CreateProcessWithTokenW ? How to get the token from the Session)

Does someone has an example ?

Best Regards

Yannick
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 14, 2017 11:04 AM   in response to: Yannick LANCHEC in response to: Yannick LANCHEC
Yannick LANCHEC wrote:

I need to make a service (running with SYSTEM account), and this
service has to execute a 'visual' software (like Notepad.exe) in the
session of each logged user.

Use the Win32 API CreateProcessAsUser() function.

What is the best method to enumerate the active sessions
(LsaEnumerateSession ? WTSEnumerateSessions ? ? ?)

Either way should work. I use WTSEnumerateSessions() myself. To get
the user token needed for CreateProcessAsUser(), either enumeration API
will give you session IDs, which you can pass to WTSQueryUserToken().
Or, if you use the LSA enumeration, it also gives you LUIDs, which you
can pass to OpenTokenByLogonId().

Does someone has an example ?

There are tons of examples available online, especially on
StackOVerflow.

--
Remy Lebeau (TeamB)
Yannick LANCHEC

Posts: 43
Registered: 1/21/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 14, 2017 11:35 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy,

Thank you ! I'm going to look this.

Yannick

Remy Lebeau (TeamB) wrote:
Yannick LANCHEC wrote:

I need to make a service (running with SYSTEM account), and this
service has to execute a 'visual' software (like Notepad.exe) in the
session of each logged user.

Use the Win32 API CreateProcessAsUser() function.

What is the best method to enumerate the active sessions
(LsaEnumerateSession ? WTSEnumerateSessions ? ? ?)

Either way should work. I use WTSEnumerateSessions() myself. To get
the user token needed for CreateProcessAsUser(), either enumeration API
will give you session IDs, which you can pass to WTSQueryUserToken().
Or, if you use the LSA enumeration, it also gives you LUIDs, which you
can pass to OpenTokenByLogonId().

Does someone has an example ?

There are tons of examples available online, especially on
StackOVerflow.

--
Remy Lebeau (TeamB)
Yannick LANCHEC

Posts: 43
Registered: 1/21/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 19, 2017 2:53 PM   in response to: Yannick LANCHEC in response to: Yannick LANCHEC
Hi Remy !

Thank you for your help !

I have find samples and i can execute a program in several sessions.

Res:=CreateProcessAsUser(hToken,Nil,PChar(CmdLine),Nil,Nil,False,CREATE_UNICODE_ENVIRONMENT,Env,Nil,Si,Pi);

But i have a problem : If i execute this program (who needs to acces to the registry (HKLM)), i have a 0x2 error (file notr found), of course the program works in a normal session.

I have tested the HKU and it's OK, i have tested also KEY_WOW64_64KEY...

Thank you

Yannick

Yannick LANCHEC wrote:
Remy,

Thank you ! I'm going to look this.

Yannick

Remy Lebeau (TeamB) wrote:
Yannick LANCHEC wrote:

I need to make a service (running with SYSTEM account), and this
service has to execute a 'visual' software (like Notepad.exe) in the
session of each logged user.

Use the Win32 API CreateProcessAsUser() function.

What is the best method to enumerate the active sessions
(LsaEnumerateSession ? WTSEnumerateSessions ? ? ?)

Either way should work. I use WTSEnumerateSessions() myself. To get
the user token needed for CreateProcessAsUser(), either enumeration API
will give you session IDs, which you can pass to WTSQueryUserToken().
Or, if you use the LSA enumeration, it also gives you LUIDs, which you
can pass to OpenTokenByLogonId().

Does someone has an example ?

There are tons of examples available online, especially on
StackOVerflow.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 19, 2017 3:26 PM   in response to: Yannick LANCHEC in response to: Yannick LANCHEC
Yannick LANCHEC wrote:

But i have a problem : If i execute this program (who needs to acces
to the registry (HKLM)), i have a 0x2 error (file notr found), of
course the program works in a normal session.

Then the program has a logic bug, it is not accessing the Registry
correctly. That has nothing to do with CreateProcessAsUser().

--
Remy Lebeau (TeamB)
Yannick LANCHEC

Posts: 43
Registered: 1/21/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 19, 2017 11:55 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Yannick LANCHEC wrote:

But i have a problem : If i execute this program (who needs to acces
to the registry (HKLM)), i have a 0x2 error (file notr found), of
course the program works in a normal session.

Then the program has a logic bug, it is not accessing the Registry
correctly. That has nothing to do with CreateProcessAsUser().

--
Remy Lebeau (TeamB)

Hi Remy,

I have make a simple program that read (with WOW) a value, il i execute it normally it works, but if i execute it from a service, the openkey does not work, i get a code 0 with getlasterror.

////////////////////////////////////////////////////////////////////////////////
// Read
Procedure TForm1.btnReadClick(Sender: TObject);
Var
R:TRegistry;
Key,Name,Value:String;
Begin
Key:=EClef.Text;
Name:=ENom.Text;
Value:=EValeur.Text;
//
R:=TRegistry.Create;
R.RootKey:=HKEY_LOCAL_MACHINE;
R.Access:=KEY_ALL_ACCESS;
If CBWOW64.Checked Then R.Access:=R.Access+KEY_WOW64_64KEY;
If CBWOW32.Checked Then R.Access:=R.Access+KEY_WOW64_32KEY;
If R.OpenKey(Key,True) Then
Begin
Value:=R.ReadString(Name);
R.CloseKey;
ShowMessage('Read : HKLM\'+Key+' : '+Name+'='+Value);
End
Else
ShowMessage('Err='+IntToStr(GetLastError));
R.Free;
End;

Yannick
Lajos Juhasz

Posts: 801
Registered: 3/14/14
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 20, 2017 5:19 AM   in response to: Yannick LANCHEC in response to: Yannick LANCHEC
Yannick LANCHEC wrote:

Remy Lebeau (TeamB) wrote:
Yannick LANCHEC wrote:

But i have a problem : If i execute this program (who needs to
acces to the registry (HKLM)), i have a 0x2 error (file notr
found), of course the program works in a normal session.

Then the program has a logic bug, it is not accessing the Registry
correctly. That has nothing to do with CreateProcessAsUser().

--
Remy Lebeau (TeamB)

Hi Remy,

I have made a simple program that read (with WOW) a value, il i
execute it normally it works, but if i execute it from a service, the
openkey does not work, i get a code 0 with getlasterror.

//////////////////////////////////////////////////////////////////////
////////// // Read
Procedure TForm1.btnReadClick(Sender: TObject);
Var
R:TRegistry;
Key,Name,Value:String;
Begin
Key:=EClef.Text;
Name:=ENom.Text;
Value:=EValeur.Text;
//
R:=TRegistry.Create;
R.RootKey:=HKEY_LOCAL_MACHINE;
R.Access:=KEY_ALL_ACCESS;
If CBWOW64.Checked Then R.Access:=R.Access+KEY_WOW64_64KEY;
If CBWOW32.Checked Then R.Access:=R.Access+KEY_WOW64_32KEY;
If R.OpenKey(Key,True) Then
Begin
Value:=R.ReadString(Name);
R.CloseKey;
ShowMessage('Read : HKLM\'+Key+' : '+Name+'='+Value);
End
Else
ShowMessage('Err='+IntToStr(GetLastError));
R.Free;
End;

Yannick

You should restrict the right for the registry access:

  R:=TRegistry.Create(KEY_READ);
  R.RootKey:=HKEY_LOCAL_MACHINE;
  If CBWOW64.Checked Then R.Access:=R.Access+KEY_WOW64_64KEY;
  If CBWOW32.Checked Then R.Access:=R.Access+KEY_WOW64_32KEY;
  If R.OpenKeyReadOnly(Key) Then 


(An ordinary user has only read-only access to HKEY_LOCAL_MACHINE)
Yannick LANCHEC

Posts: 43
Registered: 1/21/01
Re: Service and Interactive Sessions
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 20, 2017 6:45 AM   in response to: Lajos Juhasz in response to: Lajos Juhasz
Lajos Juhasz wrote:
Yannick LANCHEC wrote:

Remy Lebeau (TeamB) wrote:
Yannick LANCHEC wrote:

But i have a problem : If i execute this program (who needs to
acces to the registry (HKLM)), i have a 0x2 error (file notr
found), of course the program works in a normal session.

Then the program has a logic bug, it is not accessing the Registry
correctly. That has nothing to do with CreateProcessAsUser().

--
Remy Lebeau (TeamB)

Hi Remy,

I have made a simple program that read (with WOW) a value, il i
execute it normally it works, but if i execute it from a service, the
openkey does not work, i get a code 0 with getlasterror.

//////////////////////////////////////////////////////////////////////
////////// // Read
Procedure TForm1.btnReadClick(Sender: TObject);
Var
R:TRegistry;
Key,Name,Value:String;
Begin
Key:=EClef.Text;
Name:=ENom.Text;
Value:=EValeur.Text;
//
R:=TRegistry.Create;
R.RootKey:=HKEY_LOCAL_MACHINE;
R.Access:=KEY_ALL_ACCESS;
If CBWOW64.Checked Then R.Access:=R.Access+KEY_WOW64_64KEY;
If CBWOW32.Checked Then R.Access:=R.Access+KEY_WOW64_32KEY;
If R.OpenKey(Key,True) Then
Begin
Value:=R.ReadString(Name);
R.CloseKey;
ShowMessage('Read : HKLM\'+Key+' : '+Name+'='+Value);
End
Else
ShowMessage('Err='+IntToStr(GetLastError));
R.Free;
End;

Yannick

You should restrict the right for the registry access:

  R:=TRegistry.Create(KEY_READ);
  R.RootKey:=HKEY_LOCAL_MACHINE;
  If CBWOW64.Checked Then R.Access:=R.Access+KEY_WOW64_64KEY;
  If CBWOW32.Checked Then R.Access:=R.Access+KEY_WOW64_32KEY;
  If R.OpenKeyReadOnly(Key) Then 


(An ordinary user has only read-only access to HKEY_LOCAL_MACHINE)

Hi Lajos !

You are right, a problem of rights !

My delphi is executed as admin each time, so it works better.

Thank you for your help.

Now my test prog display correctly informations from registry.

Best regards.

Yannnick
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Service and Interactive Sessions [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 20, 2017 11:33 AM   in response to: Yannick LANCHEC in response to: Yannick LANCHEC
Yannick LANCHEC wrote:

I have make a simple program that read (with WOW) a value, il i
execute it normally it works, but if i execute it from a service, the
openkey does not work

Don't use KEY_ALL_ACCESS rights. That is restricted to admins only.
And HKEY_LOCAL_MACHINE is generally read-only for non-admin users, so
KEY_ALL_ACCESS is asking for too many rights anyway. Always request
the absolute minimum rights you actually need.

If you are just going to read from a key, use
TRegistry.OpenKeyReadOnly() instead of TRegistry.OpenKey().
OpenKeyReadOnly() attempts several combinations of rights to try to
gain reading access. This is especially important for accessing HKLM.

i get a code 0 with getlasterror.

Registry functions do not use GetLastError() for error reporting. They
return error codes directly. If you are using a modern Delphi version,
TRegistry has LastError and LastErrorMsg properties.

Try something more like this:

Procedure TForm1.btnReadClick(Sender: TObject);
Var
  R: TRegistry;
  Key, Name, Value: String;
Begin
  Key := EClef.Text;
  Name := ENom.Text;
  Value := EValeur.Text;
  //
  R := TRegistry.Create;
  try
    R.RootKey := HKEY_LOCAL_MACHINE;
 
    // you can't enable KEY_WOW64_64KEY and KEY_WOW64_32KEY at the
    // same time, you should be using radio buttons instead of
    // checkboxes...
    //
    if CBWOW64.Checked then
      R.Access := KEY_WOW64_64KEY
    else if CBWOW32.Checked then
      R.Access := KEY_WOW64_32KEY;
 
    if R.OpenKeyReadOnly(Key) then
    begin
      Value := R.ReadString(Name);
      R.CloseKey;
      ShowMessage(Format('Read : HKLM\%s : %s=%s', [Key, Name, Value]));
    end
    else
      ShowMessage(Format('Err=%d: %s', [R.LastError, R.LastErrorMsg]));
  finally
    R.Free;
  end;
end;


--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02