使用LogonUser与ImpersonateLoggedOnUser模拟用户访问共享失败求助
问题分析与解决方案
你的代码存在三个关键问题导致远程资源访问失败:
1. 错误的登录类型选择
你使用的LOGON32_LOGON_NEW_CREDENTIALS登录类型仅适用于本地会话内的凭据替换,它不会将模拟身份的凭据传递给远程服务器(NTLM或Kerberos身份验证不会使用该令牌的凭据),无法用于远程域控制器的资源访问。
2. system()函数无法继承线程模拟令牌
system()会启动新的cmd.exe进程,该进程默认使用父进程的主令牌,而非当前线程的模拟令牌。也就是说,即使主线程成功模拟了域管理员,dir命令实际还是以原进程身份执行,自然触发权限拒绝。
3. UNC路径转义错误
代码中的\\MY-DC\C$在C字符串中解析后会变成\MY-DC\C$,而正确的UNC远程路径需要以双反斜杠开头,正确写法应为\\\\MY-DC\\C$,否则系统会将其识别为本地路径而非远程服务器路径。
修正后的代码示例
以下代码解决了上述所有问题,通过正确的登录类型获取令牌,并使用CreateProcessAsUser()直接在目标用户上下文启动进程:
#include <windows.h> #include <stdio.h> int main(int argc, char** argv) { if (argc != 4) { printf("使用方式: %s <用户名> <域名> <密码>\n", argv[0]); return 1; } HANDLE hToken = NULL; BOOL logonSuccess = LogonUserA( argv[1], argv[2], argv[3], LOGON32_LOGON_INTERACTIVE, // 适合远程访问的登录类型 LOGON32_PROVIDER_DEFAULT, &hToken ); if (!logonSuccess) { printf("LogonUserA 失败,错误码: %d\n", GetLastError()); return 1; } printf("LogonUserA 成功\n"); STARTUPINFOA si = {0}; si.cb = sizeof(STARTUPINFOA); PROCESS_INFORMATION pi = {0}; // 正确转义的UNC路径命令 char cmdLine[] = "cmd.exe /c dir \\\\MY-DC\\C$ > file.txt"; // 使用目标用户令牌启动进程 BOOL createSuccess = CreateProcessAsUserA( hToken, NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); if (!createSuccess) { printf("CreateProcessAsUserA 失败,错误码: %d\n", GetLastError()); CloseHandle(hToken); return 1; } printf("进程启动成功\n"); // 等待命令执行完成 WaitForSingleObject(pi.hProcess, INFINITE); // 清理资源 CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hToken); printf("操作完成\n"); return 0; }
关键说明
- 登录类型选择:
LOGON32_LOGON_INTERACTIVE创建的令牌包含完整用户权限,支持远程资源访问的身份验证流程;若需明文凭据传递(不推荐,存在安全风险),也可使用LOGON32_LOGON_NETWORK_CLEARTEXT。 - 进程启动方式:
CreateProcessAsUser()直接使用目标用户令牌启动进程,确保子进程完全运行在目标用户上下文,避免system()的令牌继承问题。 - 权限要求:当前进程需具备
SE_INCREASE_QUOTA_NAME和SE_ASSIGNPRIMARYTOKEN_NAME权限,通常以管理员身份运行程序即可满足。 - 资源清理:务必关闭所有打开的句柄(令牌、进程、线程),避免资源泄漏。
内容的提问来源于stack exchange,提问作者EfM
相关产品推荐
相关产品推荐

