Как запустить интерактивный процесс в Windows на Java? - PullRequest
1 голос
/ 21 сентября 2019

Мне нужно запустить приложение в Windows с правами администратора на рабочем столе другого пользователя.

Я запускаю свой код как администратор с повышенными правами.

Я нашел эту статью (она описывает, как это сделатьэто на .net):

https://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-32-and-64-bit-Archite

Я перевел код из статьи на Java, но advapi32.CreateProcessAsUser возвращает false.Кто-нибудь видит, что я пропустил в этом коде?

зависимости pom

<dependencies>
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>5.2.0</version>
    </dependency>
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna-platform</artifactId>
        <version>5.2.0</version>
    </dependency>
</dependencies>

мой код

import com.sun.jna.platform.win32.*;

public class Test {
    public static void main(String[] args) {
        // id of the process which we you as a pointer to the target desktop where we will open new application from current user
        int procId = 26100;

        String applicationName = "C:\\Windows\\System32\\cmd.exe";

        Kernel32 kernel32 = Kernel32.INSTANCE;

        int securityLevel = WinNT.READ_CONTROL;
        final int PROCESS_VM_READ=0x0010;
        final int PROCESS_QUERY_INFORMATION=0x0400;
        WinNT.HANDLE hProcess = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, procId);
        System.out.println(hProcess);

        Advapi32 advapi32 = Advapi32.INSTANCE;

        // obtain a handle to the access token of the winlogon process
        WinNT.HANDLEByReference hPToken = new WinNT.HANDLEByReference();
        if (!advapi32.OpenProcessToken(hProcess, WinNT.TOKEN_DUPLICATE, hPToken)) {
            kernel32.CloseHandle(hProcess);
            throw new RuntimeException("1");
        }
        System.out.println(hPToken);

        // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
        // I would prefer to not have to use a security attribute variable and to just
        // simply pass null and inherit (by default) the security attributes
        // of the existing token. However, in C# structures are value types and therefore
        // cannot be assigned the null value.
        WinBase.SECURITY_ATTRIBUTES sa = new WinBase.SECURITY_ATTRIBUTES();
        sa.dwLength = new WinDef.DWORD(sa.size());

        WinNT.HANDLEByReference hUserTokenDup = new WinNT.HANDLEByReference();

        // copy the access token of the winlogon process;
        // the newly created token will be a primary token
        if (!advapi32.DuplicateTokenEx(hPToken.getValue(), securityLevel, sa,
                (int) WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                (int) WinNT.TOKEN_TYPE.TokenPrimary, hUserTokenDup)) {
            kernel32.CloseHandle(hProcess);
            kernel32.CloseHandle(hPToken.getValue());
            throw new RuntimeException("2");
        }
        System.out.println(hUserTokenDup);

        WinBase.STARTUPINFO si = new WinBase.STARTUPINFO();
        si.cb = new WinDef.DWORD(si.size());

        // interactive window station parameter; basically this indicates
        // that the process created can display a GUI on the desktop
        si.lpDesktop = "winsta0\\default";

        final int NORMAL_PRIORITY_CLASS = 0x0020;
        final int CREATE_NEW_CONSOLE    = 0x0010;

        // flags that specify the priority and creation method of the process
        int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

        WinBase.PROCESS_INFORMATION procInfo = new WinBase.PROCESS_INFORMATION();

        // create a new process in the current User's logon session
        boolean result = advapi32.CreateProcessAsUser(
                hUserTokenDup.getValue(),  // client's access token
                null,             // file to execute
                applicationName,  // command line
                sa,           // pointer to process SECURITY_ATTRIBUTES
                sa,           // pointer to thread SECURITY_ATTRIBUTES
                false,            // handles are not inheritable
                dwCreationFlags,  // creation flags
                null,      // pointer to new environment block
                null,             // name of current directory
                si,           // pointer to STARTUPINFO structure
                procInfo      // receives information about new process
        );
        System.out.println(procInfo);
        System.out.println("result: " + result);
    }
}

1 Ответ

3 голосов
/ 25 сентября 2019
  1. Согласно CreateProcessAsUser.hToken:

Дескриптор первичного токена, который представляет пользователя.Дескриптор должен иметь права доступа TOKEN_QUERY , TOKEN_DUPLICATE и TOKEN_ASSIGN_PRIMARY .

Итак, вы должны OpenProcessToken с TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY.

Дублированный токен также не имеет достаточных разрешений.Вы указываете только права доступа READ_CONTROL.

Согласно DuplicateTokenEx.dwDesiredAccess:

Для запроса тех же прав доступа, что и у существующего токенаукажите ноль.

Итак, вам нужно установить securityLevel на ноль.

Или просто укажите TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY прямо на DuplicateTokenEx
...