Jump to content

Recommended Posts

I have an autoit script set up to run as a service. I want to run a program from the service as the currently logged on user without having the user's username/password combination. I have found that if a process is already running in the user's context, a program can "copy" the security information of the user to run a new program.

The way I expect it to work has changed many times as I have made attempts to get a program to run in the security context of the user. Here is the current theory on how it will work:

The service retrieves a security token from one of the user's processes

The token is used to allow the service to temporarily impersonate the user

The service's security context (now the user's) is then duplicated and promoted to a primary token instead of just an impersonation context.

The process is launched using CreateProcessAsUser with the promoted context as a parameter

The script then returns to its original context.

I have the partially completed script as you see it here in its entirety:

$TOKEN_READ = 0x20008
$pid = ProcessExists("explorer.exe")
If Not @error Then
   $phandle = DllCall("kernel32.dll", "long", "OpenProcess", "long", $PROCESS_ALL_ACCESS, "int", 1, "long", $pid)
  ;bool OpenProcessToken(handle $handle, DWORD PROCESS_QUERY_INFORMATION, PHANDLE $handlereturn)
   $x = DllCall("advapi32.dll", "int", "OpenProcessToken", "long", $phandle[0], "long", BitOR($TOKEN_QUERY, $TOKEN_DUPLICATE), "long_ptr", "")
   $ret = DllCall("advapi32.dll", "int", "ImpersonateLoggedOnUser", "long", $x[3])
    $thrd = DllCall("kernel32.dll", "long", "GetCurrentThread")
    $curproc = DllCall("advapi32.dll", "int", "OpenThreadToken", "long", $thrd[0], "long", $TOKEN_DUPLICATE, "int", 1, "long_ptr", "")
    $dToken = DllCall("advapi32.dll", "int", "DuplicateTokenEx", "long", $curproc[4], "long", BitOR($TOKEN_IMPERSONATE, $TOKEN_READ, $TOKEN_ASSIGN_PRIMARY, $TOKEN_DUPLICATE), "long_ptr", "", "long", 2, "long", 1, "long_ptr", "")
    $arRet = DllCall("kernel32.dll", "long", "GetLastError")
    msgbox(0, "", $dToken[0] & "|" & $dToken[1] & "|" & $dToken[2] & "|" & $dToken[3] & "|" & $dToken[4] & "|" & $dToken[5] & "|" & $dToken[6] & "|" & $arRet[0])
;$ret2 = DllCall("advapi32.dll", "long", "CreateProcessAsUser", "long", $dToken[6], "str", "", "str", @WindowsDir & "\regedit.exe", "long_ptr", 0, "long_ptr", 0, "int", 0, "long", $NORMAL_PRIORITY_CLASS, "str", "", "str", "", "long_ptr", "", "long_ptr", "");next-to-last ptr can be null string
   DllCall("kernel32.dll", "long", "CloseHandle", "long", $phandle[0])
    DllCall("kernel32.dll", "long", "CloseHandle", "long", $curproc[4])
   DllCall("kernel32.dll", "long", "CloseHandle", "long", $x[3])
   DllCall("advapi32.dll", "int", "RevertToSelf")

The above code works as expexted with no errors until the call to DuplicateTokenEx, at which time the error recieved is 998 or ERROR_NOACCESS which means that there was an invaild access to a memory location. The last time I remember that error occuring was when I had an incorrect type of parameter to a DllCall (long instead of ptr_long).

I could really care less whether or not my particular code works. All I need is a way to launch a program from a service in the context of SYSTEM and for the program to run in the context of the currently logged in user.

If there is a quicker way to do this, then please enlighten me.

Who else would I be?
Link to post
Share on other sites

this-is-me, one of the things I noticed was that what is printed that is supposed to be that handle, I don't really think it is. I think somewhere AutoIt is just getting an arbitrary number or something. A PHANDLE is actually of type void** so I suspect maybe AutoIt was only dereferencing and reading the address of the handle and converting it to an int. It needs to deference further to actually see the handle, which is what you need. Thats why I wanted to test in C++, however, I had no quick way to find the PID of a process.

Link to post
Share on other sites

this-is-me, the next function called after OpenProcessToken IS DuplicateTokenEx which IS erroring. My theory is, what AutoIt is printing is the address of the handle as an integer. Who knows. At any rate, I bet a ptr_ptr type which was void** internally would solve the problem.

Link to post
Share on other sites
  • 4 years later...

I did successfully call the DuplicateTokenEx function ...

$dToken = DllCall("advapi32.dll", "int", "DuplicateTokenEx", "long_ptr", $hProcessToken, "int", $TOKEN_ALL_ACCESS, "long_ptr", "", "int", $TOKEN_TYPE_IMPERSONATION, "int", $TOKEN_TYPE_PRIMARY, "long_ptr*", "")

Now i wan't to call the CreateProcessAsUser function within the advapi32.dll .

Unfortunately the proggy exits with 'autoit3.exe has encountered a problem and needs to closed'... (i get it in german. so this is my translation :-) )

I've tried different types within the dll call and created the needed StartupInfo structure but nothin works.

Has somebody a hint?

I'am really now stuck with this behaviour of the script.



PS: here is some additionally code

   BOOL WINAPI CreateProcessAsUser(
     __in_opt    HANDLE hToken,
     __in_opt    LPCTSTR lpApplicationName,
     __inout_opt  LPTSTR lpCommandLine,
     __in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,
     __in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,
     __in        BOOL bInheritHandles,
     __in        DWORD dwCreationFlags,
     __in_opt    LPVOID lpEnvironment,
     __in_opt    LPCTSTR lpCurrentDirectory,
     __in        LPSTARTUPINFO lpStartupInfo,
     __out      LPPROCESS_INFORMATION lpProcessInformation
   Private Type STARTUPINFO 
     cb As Long 
     lpReserved As String 
     lpDesktop As String 
     lpTitle As String 
     dwX As Long 
     dwY As Long 
     dwXSize As Long 
     dwYSize As Long 
     dwXCountChars As Long 
     dwYCountChars As Long 
     dwFillAttribute As Long 
     dwFlags As Long 
     wShowWindow As Integer 
     cbReserved2 As Integer 
     lpReserved2 As Long 
     hStdInput As Long 
     hStdOutput As Long 
     hStdError As Long 
   End Type 
   Global Const $SW_SHOW = 5
   $structStartupInfo = DllStructCreate("int cb; char Reserved[256]; char Desktop[256]; char Title[256]; uint X; uint Y; uint XSize; uint YSize; uint XCountChars; uint YCountChars; uint FillAttribute; uint Flags; short ShowWindows; short cbReserved2; int_ptr lpReserved2; int_ptr StdInput; int_ptr StdOutput; int_ptr StdError")
   if @error Then 
       MsgBox(0,"","Error in DllStructCreate " & @error);
   DllStructSetData($structStartupInfo, "cb",DllStructGetSize($structStartupInfo))
   DllStructSetData($structStartupInfo,"Desktop", "WinSta0\Default")
   DllStructSetData($structStartupInfo, "Flags", $STARTF_USESHOWWINDOW)
   DllStructSetData($structStartupInfo, "ShowWindows", $SW_SHOW)
   ConsoleWrite("cb: " & DllStructGetData($structStartupInfo,1))
   $pStartupInfo = DllStructGetPtr($structStartupInfo)
   $dProcess = DllCall("advapi32.dll", "long", "CreateProcessAsUser", "long_ptr", $dToken[6], "str", "", "str", @WindowsDir & "\notepad.exe", "long_ptr", "", "long_ptr", "", "int", 0, "long", $NORMAL_PRIORITY_CLASS, "str", "", "str", "", "long_ptr", $pStartupInfo, "long_ptr", $PointerToProcessInformation);next-to-last ptr can be null string
Edited by Sundance
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...