I need to run a program that requires UAC using the credentials of a specific administrator (not my account). I have the python code below that runs programs with "another user", but if the program requests UAC elevation, the code does not work, in this case the error "The operation requires elevation" occurs.
any idea how to solve it?
Code:
import ctypes
import os
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
CREATE_NEW_CONSOLE = 0x00000010
CREATE_NO_WINDOW = 0x08000000
DETACHED_PROCESS = 0x00000008
CREATE_NEW_PROCESS_GROUP = 0x00000200
CREATE_UNICODE_ENVIRONMENT = 0x00000400
if not hasattr(wintypes, 'LPBYTE'):
wintypes.LPBYTE = ctypes.POINTER(wintypes.BYTE)
class HANDLE(wintypes.HANDLE):
def detach(self):
handle, self.value = self.value, None
return wintypes.HANDLE(handle)
def close(self, CloseHandle=kernel32.CloseHandle):
if self:
CloseHandle(self.detach())
def __del__(self):
self.close()
class PROCESS_INFORMATION(ctypes.Structure):
_fields_ = (('hProcess', HANDLE),
('hThread', HANDLE),
('dwProcessId', wintypes.DWORD),
('dwThreadId', wintypes.DWORD))
LPPROCESS_INFORMATION = ctypes.POINTER(PROCESS_INFORMATION)
class STARTUPINFOW(ctypes.Structure):
_fields_ = (('cb', wintypes.DWORD),
('lpReserved', wintypes.LPWSTR),
('lpDesktop', wintypes.LPWSTR),
('lpTitle', wintypes.LPWSTR),
('dwX', wintypes.DWORD),
('dwY', wintypes.DWORD),
('dwXSize', wintypes.DWORD),
('dwYSize', wintypes.DWORD),
('dwXCountChars', wintypes.DWORD),
('dwYCountChars', wintypes.DWORD),
('dwFillAttribute', wintypes.DWORD),
('dwFlags', wintypes.DWORD),
('wShowWindow', wintypes.WORD),
('cbReserved2', wintypes.WORD),
('lpReserved2', wintypes.LPBYTE),
('hStdInput', wintypes.HANDLE),
('hStdOutput', wintypes.HANDLE),
('hStdError', wintypes.HANDLE))
def __init__(self, *args, **kwds):
self.cb = ctypes.sizeof(self)
super(STARTUPINFOW, self).__init__(*args, **kwds)
LPSTARTUPINFOW = ctypes.POINTER(STARTUPINFOW)
def _check_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
advapi32.CreateProcessWithLogonW.errcheck = _check_bool
advapi32.CreateProcessWithLogonW.argtypes = (
wintypes.LPCWSTR, # lpUsername
wintypes.LPCWSTR, # lpDomain
wintypes.LPCWSTR, # lpPassword
wintypes.DWORD, # dwLogonFlags
wintypes.LPCWSTR, # lpApplicationName
wintypes.LPWSTR, # lpCommandLine (inout)
wintypes.DWORD, # dwCreationFlags
wintypes.LPCWSTR, # lpEnvironment (force Unicode)
wintypes.LPCWSTR, # lpCurrentDirectory
LPSTARTUPINFOW, # lpStartupInfo
LPPROCESS_INFORMATION) # lpProcessInfo (out)
def CreateProcessWithLogonW(username, password, domain=None, logonflags=0,
executable=None, commandline=None, creationflags=0,
env=None, cwd=None, startupinfo=None):
if commandline is not None:
commandline = ctypes.create_unicode_buffer(commandline)
creationflags |= CREATE_UNICODE_ENVIRONMENT
if startupinfo is None:
startupinfo = STARTUPINFOW()
pi = PROCESS_INFORMATION()
advapi32.CreateProcessWithLogonW(username, domain, password, logonflags,
executable, commandline, creationflags,
env, cwd, ctypes.byref(startupinfo),
ctypes.byref(pi))
return pi.hProcess, pi.hThread, pi.dwProcessId, pi.dwThreadId
def startScript(username, password, domain):
exe = os.path.join(os.environ['WINDIR'],'system32','cmd.exe')
cflags = CREATE_NEW_CONSOLE
hProcess, hThread, pid, tid = CreateProcessWithLogonW(
username, password,domain, executable=exe, creationflags=cflags)
print('PID: %d' % pid)
if __name__ == "__main__":
username = "user"
password = "pass"
domain = "domain"
startScript(username, password, domain)
I already try this code, but the code below runs UAC on my current account, not the specific administrator account:
shell32 = ctypes.windll.shell32
result = shell32.ShellExecuteW(
None, # hwnd
"runas", # lpOperation
executable, # lpFile
params, # lpParameters
None, # lpDirectory
show_cmd, # nShowCmd
)