Python Request UAC with Another Admin

27 views Asked by At

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
)
0

There are 0 answers