ImpersonateLoggedOnUser

Just starting out? Need help? Post your questions and find answers here.
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

ImpersonateLoggedOnUser

Post by Droopy »

I Logon / Impersonate successfully toto
but when Notepad is launched, the name of the user who launch Notepad
is not toto, it's my account !!

Code: Select all

Username.s="toto"
Domain.s="."
Password.s="passe"
Token.l

Debug logonuser_(@Username,@Domain,@Password,2,0,@Token)

Debug ImpersonateLoggedOnUser_(Token)

RunProgram("notepad.exe","","")
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Do either of these work for you?:

Code: Select all

Procedure u(string$)
  sLen = Len(string$)
  uLen = (sLen<<1)+2
  *uBuffer = AllocateMemory(uLen)
  MultiByteToWideChar_(#CP_ACP, 0, string$, sLen, *uBuffer, uLen)
  ProcedureReturn *uBuffer
EndProcedure

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44

Procedure Error(message$, hToken)
  wError = GetLastError_()
  If wError
    *ErrorBuffer = AllocateMemory(1024)
    If *ErrorBuffer
      FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
      message$+Chr(10)+PeekS(*ErrorBuffer)
      FreeMemory(*ErrorBuffer)
    EndIf
  EndIf
  If hToken:RevertToSelf_():CloseHandle_(hToken):EndIf
  MessageRequester("Error", message$)
  ProcedureReturn #FALSE
EndProcedure

Procedure RunAsUser(Program$, UserName$, Domain$, Password$)
  If LogonUser_(@Username$, @Domain$, @Password$, 2, 0, @hToken)=0:ProcedureReturn Error("LogonUser", 0):EndIf
  If ImpersonateLoggedOnUser_(hToken)=0:ProcedureReturn Error("ImpersonateLoggedOnUser", hToken):EndIf
  GetStartupInfo_(@si.STARTUPINFO)
  hProcess = CreateProcessAsUser_(hToken, Program$, "", #NULL, #NULL, #FALSE, #NORMAL_PRIORITY_CLASS, #NULL, #NULL, @si, @pi.PROCESS_INFORMATION)
  If hProcess=0:ProcedureReturn Error("CreateProcessAsUser", hToken):EndIf
  RevertToSelf_()
  CloseHandle_(hToken)
  ProcedureReturn hProcess
EndProcedure

#LOGON_WITH_PROFILE = 1
Procedure RunAsUser2(Program$, UserName$, Domain$, Password$)
  GetStartupInfo_(@si.STARTUPINFO)
  hProcess = CallFunctionFast(*CreateProcessWithLogonW, u(Username$), u(Domain$), u(Password$), #LOGON_WITH_PROFILE, u(Program$), "", #NULL, #NULL, #FALSE, @si, @pi.PROCESS_INFORMATION)
  If hProcess=0:ProcedureReturn Error("CreateProcessWithLogonW", 0):EndIf
  ProcedureReturn hProcess
EndProcedure

Username.s = "toto"
Domain.s = "."
Password.s = "passe"

Debug RunAsUser("notepad.exe", Username, Domain, Password)
Debug RunAsUser2("calc.exe", Username, Domain, Password)
Last edited by El_Choni on Tue Apr 12, 2005 10:52 pm, edited 1 time in total.
El_Choni
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

Thanks El_Choni
but I can't use this code
cause I want to impersonate the Thread ( as an local administrator)
for creating users / SetComputer name
without launching external program
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

I thought you wanted to launch a program as another user, that's what your code tries to do anyway :?:
El_Choni
Tommeh
Enthusiast
Enthusiast
Posts: 149
Joined: Sun Aug 29, 2004 2:25 pm
Location: United Kingdom

Post by Tommeh »

On msdn, it says this code is part of the .net framework and needs the included header: mscoree.h

I think this may only be for .net ;)
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

I want my software launched by a user, was impersonated as an administrator

So the next command ( Purebasic code ) of this software was in an administrator security context .

So the next code work

Code: Select all

ComputerName.s="PPPPP"
If SetComputerName_(@ComputerName)

Without creating another exe and launch it with CreateProcessWithLogonW
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

I don't Windows would let a limited user impersonate an administrator. Wouldn't make too much sense, would it?
El_Choni
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

With user right you can launch another exe as an administrator ( If you know the username / password )

I just want the same without launch external program
Max.
Enthusiast
Enthusiast
Posts: 225
Joined: Fri Apr 25, 2003 8:39 pm

Post by Max. »

Hopefully, I am not off, but actually, El Choni's example works well for me (thanks for that!).

Here a stripped down version and a description of the test (needs NTFS):

1. Logged on as user "A"
2. Created a directory "C:\ElChoni"
3. Changed security, so only the user "B" has write access, others only read
4. Started the program below, that attempts to create a file in that restricted dir

a) User "A" (before impersonation) tries: no success
b) Calling the impersonation routine, impersonating "B": success

Now let's check if it really is as it pretended to be:

- et voila, the file was created

Code: Select all

;Stripped down from sample by El Choni
;http://forums.purebasic.com/english/viewtopic.php?t=14727&highlight=


Username$ = "b"
Domain$ = "."
Password$ = "mypassword"



Procedure u(string$)
  sLen = Len(string$)
  uLen = (sLen<<1)+2
  *uBuffer = AllocateMemory(uLen)
  MultiByteToWideChar_(#CP_ACP, 0, string$, sLen, *uBuffer, uLen)
  ProcedureReturn *uBuffer
EndProcedure

Procedure Error(message$, hToken)
  wError = GetLastError_()
  If wError
    *ErrorBuffer = AllocateMemory(1024)
    If *ErrorBuffer
      FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
      message$+Chr(10)+PeekS(*ErrorBuffer)
      FreeMemory(*ErrorBuffer)
    EndIf
  EndIf
  If hToken:RevertToSelf_():CloseHandle_(hToken):EndIf
  MessageRequester("Error", message$)
  ProcedureReturn #FALSE
EndProcedure 

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44

Procedure ImpersonateUser(UserName$, Domain$, Password$)
  
  If LogonUser_(@Username$, @Domain$, @Password$, 2, 0, @hToken)=0
    ProcedureReturn Error("LogonUser", 0)
  EndIf
  
  If ImpersonateLoggedOnUser_(hToken)=0:
    ProcedureReturn Error("ImpersonateLoggedOnUser", hToken)
  EndIf
  
  GetStartupInfo_(@si.STARTUPINFO)
  
  ;After impersonation
  Result=CreateFile(0,"C:\ElChoni\UserB.txt")
  If Result
    Debug "Successful: impersonated user"
    CloseFile(0)
  Else
    Debug "Error: impersonated user"
  EndIf
  
  
  RevertToSelf_()
  CloseHandle_(hToken)
  ProcedureReturn hProcess
EndProcedure 

;Before impersonation
Result=CreateFile(0,"C:\ElChoni\UserA.txt")
If Result
  Debug "Successful: main user"
  CloseFile(0)
Else
  Debug "Error: main user"
EndIf

ImpersonateUser(Username$,Domain$,Password$)

;Now reverted to state "before impersonation"
Isn't that what you mean to do (just chose a random built in function to make it easier to test. API should work as well)?

But:

The user that impersonates (here: A) needs to have the privilege ImpersonateUser!
Athlon64 3800+ · 1 GB RAM · Radeon X800 XL · Win XP Prof/SP1+IE6.0/Firefox · PB 3.94/4.0
Intel Centrino 1.4 MHz · 1.5 GB RAM · Radeon 9000 Mobility · Win XP Prof/SP2+IE6.0/Firefox · PB 3.94/4.0
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

Thanks a lot :D , the code of El_Choni works well

but i don't understand 2 portions of code :(

Code: Select all

!extrn _CreateProcessWithLogonW@44 
Global *CreateProcessWithLogonW 
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44 
and

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
is it possible to El_Choni to comment this piece of code :D
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

I retest the El Choni code and it doesn't work
The code of Max works well but the following code is no needed

Code: Select all

!extrn _CreateProcessWithLogonW@44 
Global *CreateProcessWithLogonW 
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44 
and

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
My first code works well, the software is impersonated ( file creation / add user ) except for launching external program !!


Thanks a lot El Choni & Max
Max.
Enthusiast
Enthusiast
Posts: 225
Joined: Fri Apr 25, 2003 8:39 pm

Post by Max. »

Droopy wrote:I retest the El Choni code and it doesn't work
The code of Max works well
"My" code is El Choni's code, where I just removed calling an external application. It is the same. And impersonation works until the RevertToSelf_ call. Just for clarification.
Athlon64 3800+ · 1 GB RAM · Radeon X800 XL · Win XP Prof/SP1+IE6.0/Firefox · PB 3.94/4.0
Intel Centrino 1.4 MHz · 1.5 GB RAM · Radeon 9000 Mobility · Win XP Prof/SP2+IE6.0/Firefox · PB 3.94/4.0
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

In the code posted by Max, these two pieces of code are not used, they were only needed for my example.

This:

Code: Select all

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44
Enables calling to CreateProcessWithLogonW, as it's not natively included in PB, and AFAIK will only work in Windows 2000, XP and 2003. Using it this way speeds up things, but you won't be able to check if the function exists in the machine or not as if you used OpenLibrary & Co.

And this:

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
Is just to provide a valid argument to CreateProcessWithLogonW, I don't know if it's necessary or not.

I wasn't able to check any of the code in my machine, which only has 1 user. Right now I'm in a machine with several users, and the code doesn't work: the users don't have password, and I don't know how to tell that to LogonUser_()

Well, that's all about it. Regards,
El_Choni
Post Reply