Jump to content
Sign in to follow this  
matrixnz

How to ImpersonateLoggedOnUser?

Recommended Posts

matrixnz

Brief Overview of what I'm trying to achieve

I have a program that runs as Local System Account, in the middle of this process I'd like to have the option to run IE, Word, etc.. as the currently logged in user. (The reason being is that, the System Account doesn't have access to the Web, Printers etc..)

What I've found while searching is that you can use the WinAPI ImpersonateLoggedOnUser, the problem is I have no idea how to impliment it.

Open Process Function

http://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx

Open Process Token Function

http://msdn.microsoft.com/en-us/library/aa379295(VS.85).aspx

Impersonate Logged On User Function

http://msdn.microsoft.com/en-us/library/aa378612(VS.85).aspx

From what I understand the simplist method is to get a user ProcessID for example Explorer.exe, then Open the Process, then Open the Process Token then use ImpersonateLoggedOnUser from the Process Token. However I can't seem to get it to work, I have no idea when it comes to Windows API so if anyone can assist it would be much appreciated.

Here is what I've tried so far:

#Include <WinAPI.au3>

$ProcessID = ProcessExists("EXPLORER.exe")
$ProcessHandle = _WinAPI_OpenProcess(0x0400, True, $ProcessID)
$ProcessToken = _WinAPI_OpenProcessToken($ProcessHandle)

MsgBox(0,'', $ProcessToken) ; Keeps returning 0, although $ProcessHandle

Func _WinAPI_OpenProcessToken($pHandle)
    Local $hToken, $aResult
    $aResult = DllCall("Kernel32.dll", "int", "OpenProcessToken", "int", $pHandle, "int", "TOKEN_ALL_ACCESS", "int", $hToken)
    Return $aResult
EndFunc

Share this post


Link to post
Share on other sites
Authenticity

#Include <WinAPI.au3>

Global Const $STANDARD_RIGHTS_REQUIRED = 0x000F0000
Global Const $TOKEN_ASSIGN_PRIMARY = 0x0001
Global Const $TOKEN_DUPLICATE = 0x0002
Global Const $TOKEN_IMPERSONATE = 0x0004
Global Const $TOKEN_QUERY = 0x0008
Global Const $TOKEN_QUERY_SOURCE = 0x0010
Global Const $TOKEN_ADJUST_PRIVILEGES = 0x0020
Global Const $TOKEN_ADJUST_GROUPS = 0x0040
Global Const $TOKEN_ADJUST_DEFAULT = 0x0080
Global Const $TOKEN_ADJUST_SESSIONID = 0x0100
Global Const $TOKEN_ALL_ACCESS_P = BitOR($STANDARD_RIGHTS_REQUIRED, $TOKEN_ASSIGN_PRIMARY, $TOKEN_DUPLICATE, $TOKEN_IMPERSONATE, $TOKEN_QUERY, $TOKEN_QUERY_SOURCE, $TOKEN_ADJUST_PRIVILEGES, $TOKEN_ADJUST_GROUPS, $TOKEN_ADJUST_DEFAULT)
Global Const $TOKEN_ALL_ACCESS = BitOR($TOKEN_ALL_ACCESS_P, $TOKEN_ADJUST_SESSIONID)

$ProcessID = ProcessExists("EXPLORER.exe")
$ProcessHandle = _WinAPI_OpenProcess(0x0400, False, $ProcessID)
ConsoleWrite($ProcessHandle & @CRLF)
$ProcessToken = _WinAPI_OpenProcessToken($ProcessHandle, $TOKEN_ALL_ACCESS)
ConsoleWrite($ProcessToken & @CRLF)

If $ProcessToken Then ConsoleWrite(_WinAPI_ImpersonateLoggedOnUser($ProcessToken) & @CRLF)
If $ProcessToken Then _WinAPI_CloseHandle($ProcessToken)
If $ProcessHandle Then _WinAPI_CloseHandle($ProcessHandle)


Func _WinAPI_OpenProcessToken($pHandle, $iAccess)
    Local $aResult = DllCall("advapi32.dll", "int", "OpenProcessToken", "hwnd", $pHandle, "int", $iAccess, "int*", 0)
    
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, 0)
    Return SetError(0, 0, $aResult[3])
EndFunc

Func _WinAPI_ImpersonateLoggedOnUser($hToken)
    Local $aResult = DllCall("advapi32.dll", "int", "ImpersonateLoggedOnUser", "hwnd", $hToken)
    
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError(0, 0, $aResult[0] <> 0)
EndFunc

Share this post


Link to post
Share on other sites
matrixnz

Hi Authenticity

Thanks for the post, all I can say is woah, I can run this as the logged on user without any problems, but running it as a different user (runas) for example the local Administrator, I get the following error:

_WinAPI_OpenProcess:Standard: Access is denied.

Cheers

Share this post


Link to post
Share on other sites
Authenticity

The last parameter of _WinAPI_OpenProcess() is false by default, you may want to supply true instead. Read the function description.

Share this post


Link to post
Share on other sites
matrixnz

Hi Authenticity

Sorry for the delay, had already tried that before posting, (I assume you were referring to $fDebugPriv) same problem unfortunately.

Cheers

Share this post


Link to post
Share on other sites
Authenticity

Try this one, it's taken from NomadMemory.au3.

#include <WinAPI.au3>
SetPrivilege("SeDebugPrivilege", True)

$PID = ProcessExists("svchost.exe")
$hProc = _WinAPI_OpenProcess(0x400, False, $PID)
ConsoleWrite($hProc & @CRLF)
If $hProc Then _WinAPI_CloseHandle($hProc)

;==================================================================================
; Function:         SetPrivilege( $privilege, $bEnable )
; Description:      Enables (or disables) the $privilege on the current process
;                   (Probably) requires administrator privileges to run
;
; Author(s):        Larry (from autoitscript.com's Forum)
; Notes(s):
; http://www.autoitscript.com/forum/index.php?s=&showtopic=31248&view=findpost&p=223999
;==================================================================================

Func SetPrivilege( $privilege, $bEnable )
    Const $MY_TOKEN_ADJUST_PRIVILEGES = 0x0020
    Const $MY_TOKEN_QUERY = 0x0008
    Const $MY_SE_PRIVILEGE_ENABLED = 0x0002
    Local $hToken, $SP_auxret, $SP_ret, $hCurrProcess, $nTokens, $nTokenIndex, $priv
    $nTokens = 1
    $LUID = DLLStructCreate("dword;int")
    If IsArray($privilege) Then    $nTokens = UBound($privilege)
    $TOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")
    $NEWTOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")
    $hCurrProcess = DLLCall("kernel32.dll","hwnd","GetCurrentProcess")
    $SP_auxret = DLLCall("advapi32.dll","int","OpenProcessToken","hwnd",$hCurrProcess[0],   _
            "int",BitOR($MY_TOKEN_ADJUST_PRIVILEGES,$MY_TOKEN_QUERY),"int*",0)
    If $SP_auxret[0] Then
        $hToken = $SP_auxret[3]
        DLLStructSetData($TOKEN_PRIVILEGES,1,1)
        $nTokenIndex = 1
        While $nTokenIndex <= $nTokens
            If IsArray($privilege) Then
                $priv = $privilege[$nTokenIndex-1]
            Else
                $priv = $privilege
            EndIf
            $ret = DLLCall("advapi32.dll","int","LookupPrivilegeValue","str","","str",$priv,   _
                    "ptr",DLLStructGetPtr($LUID))
            If $ret[0] Then
                If $bEnable Then
                    DLLStructSetData($TOKEN_PRIVILEGES,2,$MY_SE_PRIVILEGE_ENABLED,(3 * $nTokenIndex))
                Else
                    DLLStructSetData($TOKEN_PRIVILEGES,2,0,(3 * $nTokenIndex))
                EndIf
                DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,1),(3 * ($nTokenIndex-1)) + 1)
                DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,2),(3 * ($nTokenIndex-1)) + 2)
                DLLStructSetData($LUID,1,0)
                DLLStructSetData($LUID,2,0)
            EndIf
            $nTokenIndex += 1
        WEnd
        $ret = DLLCall("advapi32.dll","int","AdjustTokenPrivileges","hwnd",$hToken,"int",0,   _
                "ptr",DllStructGetPtr($TOKEN_PRIVILEGES),"int",DllStructGetSize($NEWTOKEN_PRIVILEGES),   _
                "ptr",DllStructGetPtr($NEWTOKEN_PRIVILEGES),"int*",0)
        $f = DLLCall("kernel32.dll","int","GetLastError")
    EndIf
    $NEWTOKEN_PRIVILEGES=0
    $TOKEN_PRIVILEGES=0
    $LUID=0
    If $SP_auxret[0] = 0 Then Return 0
    $SP_auxret = DLLCall("kernel32.dll","int","CloseHandle","hwnd",$hToken)
    If Not $ret[0] And Not $SP_auxret[0] Then Return 0
    return $ret[0]
EndFunc   ;==>SetPrivilege

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×