【发布时间】:2019-09-21 13:54:11
【问题描述】:
我需要在另一个用户桌面上以管理员权限在 Windows 中运行应用程序。
我可以使用 PsExec -i https://docs.microsoft.com/en-us/sysinternals/downloads/psexec 执行此操作,但我想在我的 Java 应用程序中执行此操作而无需额外的 exe 文件。
我以具有提升权限的管理员身份运行我的代码。
我找到了这篇文章(它描述了如何在 .net 上进行操作):
https://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-32-and-64-bit-Archite
我将文章中的代码翻译成 Java,但 advapi32.CreateProcessAsUser 返回 false 并且出现 1314 错误。有人看到我在这段代码中遗漏了什么吗?
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.Native;
import com.sun.jna.platform.win32.*;
public class TestWinRunSessionId {
public static void main(String[] args) {
System.out.println(System.getProperty("user.name"));
// id of the process which we use as a pointer to the target desktop (not administrator) where we will open new application from current user (administrator)
int procId = 18160;
WinNT.HANDLE hProcess = Kernel32.INSTANCE.OpenProcess(
WinNT.PROCESS_ALL_ACCESS,
false,
procId
);
System.out.println(hProcess);
WinNT.HANDLEByReference hPToken = new WinNT.HANDLEByReference();
boolean openProcessToken = Advapi32.INSTANCE.OpenProcessToken(
hProcess,
WinNT.TOKEN_DUPLICATE,
hPToken
);
if (!openProcessToken) {
Kernel32.INSTANCE.CloseHandle(hProcess);
throw new RuntimeException("1");
}
System.out.println(hPToken);
WinBase.SECURITY_ATTRIBUTES sa = new WinBase.SECURITY_ATTRIBUTES();
sa.dwLength = new WinDef.DWORD(sa.size());
WinNT.HANDLEByReference hUserTokenDup = new WinNT.HANDLEByReference();
boolean duplicateTokenEx = Advapi32.INSTANCE.DuplicateTokenEx(
hPToken.getValue(),
WinNT.TOKEN_ALL_ACCESS,
sa,
WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
WinNT.TOKEN_TYPE.TokenPrimary,
hUserTokenDup
);
if (!duplicateTokenEx) {
Kernel32.INSTANCE.CloseHandle(hProcess);
Kernel32.INSTANCE.CloseHandle(hPToken.getValue());
throw new RuntimeException("2");
}
System.out.println(hUserTokenDup);
WinBase.STARTUPINFO si = new WinBase.STARTUPINFO();
si.cb = new WinDef.DWORD(si.size());
si.lpDesktop = "winsta0\\default";
boolean result = Advapi32.INSTANCE.CreateProcessAsUser(
hUserTokenDup.getValue(), // client's access token
null, // file to execute
"C:\\Windows\\System32\\cmd.exe", // command line
sa, // pointer to process SECURITY_ATTRIBUTES
sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
WinBase.CREATE_UNICODE_ENVIRONMENT | WinBase.CREATE_NEW_CONSOLE, // creation flags ???
null, // pointer to new environment block ???
null, // name of current directory
si, // pointer to STARTUPINFO structure
new WinBase.PROCESS_INFORMATION() // receives information about new process
);
System.out.println("result: " + result);
System.out.println("error: " + Native.getLastError());
}
}
【问题讨论】:
-
看看能不能把错误码弄出来。在调用
CreateProcessAsUser之前,在某处执行Native.setPreserveLastError(true),在调用CreateProcessAsUser之后立即调用Native.getLastError()以获取错误代码。 -
我有 5 个代码。这意味着访问被拒绝,但我以管理员身份运行命令。
-
我想我应该研究一下这个案例stackoverflow.com/questions/13290296/…也许对我有帮助。