this-is-me Posted December 11, 2004 Share Posted December 11, 2004 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: $PROCESS_QUERY_INFORMATION = 0x400 $PROCESS_ALL_ACCESS = 0x1F0FFF $TOKEN_IMPERSONATE = 0x4 $TOKEN_QUERY = 0x8 $TOKEN_DUPLICATE = 0x2 $TOKEN_ASSIGN_PRIMARY = 0x1 $TOKEN_READ = 0x20008 $NORMAL_PRIORITY_CLASS = 0x20 $MAXIMUM_ALLOWED = 33554432 $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) MsgBox(0,"",$phandle[0]) $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]) MsgBox(0,"",$ret[0]) $thrd = DllCall("kernel32.dll", "long", "GetCurrentThread") MsgBox(0,"",$thrd[0]) $curproc = DllCall("advapi32.dll", "int", "OpenThreadToken", "long", $thrd[0], "long", $TOKEN_DUPLICATE, "int", 1, "long_ptr", "") MsgBox(0,"",$curproc[4]) $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") endif 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 comment Share on other sites More sharing options...
this-is-me Posted December 12, 2004 Author Share Posted December 12, 2004 That is one reason why I used long_ptr instead on the return handle. long_ptr works fine, seeing that it works on the OpenProcessHandle call. Who else would I be? Link to comment Share on other sites More sharing options...
Valik Posted December 12, 2004 Share Posted December 12, 2004 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 comment Share on other sites More sharing options...
this-is-me Posted December 12, 2004 Author Share Posted December 12, 2004 Not debating that, but if it was arbitrary, then why would the following DllCalls (excluding DuplicateTokenEx) still function without error? Who else would I be? Link to comment Share on other sites More sharing options...
Dalarn Posted December 12, 2004 Share Posted December 12, 2004 (edited) ...a... Edited December 20, 2004 by Dalarn Link to comment Share on other sites More sharing options...
Valik Posted December 12, 2004 Share Posted December 12, 2004 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 comment Share on other sites More sharing options...
Sundance Posted June 8, 2009 Share Posted June 8, 2009 Hi this-is-me, i'am in the same situation as you are for 4 1/2 year. :-) Did you get the function 'DuplicateTokenEx'to work? I tried some combinations but it won't function. greetz Sundance Link to comment Share on other sites More sharing options...
Sundance Posted June 12, 2009 Share Posted June 12, 2009 (edited) 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. greetz Sundance PS: here is some additionally code expandcollapse popup#cs C++ 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 ); #ce #cs 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 #ce Global Const $STARTF_USESHOWWINDOW = 1 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); exit endif 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 June 12, 2009 by Sundance Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now