Windows 서비스에서 CreateProcessAsUser를 사용하여 현재 활성 사용자에 대한 응용 프로그램을 시작합니다. 지금까지 로컬 드라이브의 응용 프로그램과 잘 작동합니다.CreateProcessAsUser : "5 : Access Denied"네트워크 공유에 액세스하려고 시도했습니다.
그러나 실행 파일이 네트워크 공유에있는 경우 전체 서버 이름 (\ myserver \ path \ app.exe)을 사용하면 5 : ERROR_ACCESS_DENIED가 생성됩니다. 매핑 된 드라이브 (P : \ path \ app.exe)를 대신 사용하면 2 : ERROR_FILE_NOT_FOUND도 생성 할 수 있습니다.
탐색기에서 응용 프로그램을 실행할 수 있습니다. 서비스가 제대로 서버에서 나를 사칭하지 못하여 적절한 토큰 복제본을 얻을 수없는 것 같습니다.
다양한 게시물에서 CreateProcessAsUser의 여러 구현을 시도해 보았습니다. 이것은 나를 위해 새로운 (환각) 물건입니다, 그리고 솔직히, 내가 .NET으로 돌아가는 데 기다릴 수 없어 :) 내가 잘못된 행을 추측하는 것은 주위 여기에 있습니다 :
이DuplicateTokenEx(
hUserToken,
(Int32)MAXIMUM_ALLOWED,
ref sa,
(Int32)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(Int32)TOKEN_TYPE.TokenPrimary,
ref hUserTokenDup);
CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true);
Int32 dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
PROCESS_INFORMATION pi;
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "winsta0\\default";
CreateProcessAsUser(hUserTokenDup, // client's access token
null, // file to execute
commandLine, // command line
ref sa, // pointer to process SECURITY_ATTRIBUTES
ref sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
workingDirectory, // name of current directory
ref si, // pointer to STARTUPINFO structure
out pi); // receives information about new process
여기에 전체 샘플 코드, 난 그것은 유용 할 수 있습니다 같아요 :
StringBuilder result = new StringBuilder();
Win32API.CreateProcessAsUser(@"C:\Windows\notepad.exe", @"C:\Windows\", out result);
내 질문 : 무엇을 위해 조정해야
using System;
using System.Text;
using System.Security;
using System.Management;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Win32
{
public class Win32API
{
[StructLayout(LayoutKind.Sequential)]
struct SECURITY_ATTRIBUTES
{
public Int32 Length;
public IntPtr lpSecurityDescriptor;
public Boolean bInheritHandle;
}
enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation = 2
}
[StructLayout(LayoutKind.Sequential)]
struct STARTUPINFO
{
public Int32 cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public UInt32 dwX;
public UInt32 dwY;
public UInt32 dwXSize;
public UInt32 dwYSize;
public UInt32 dwXCountChars;
public UInt32 dwYCountChars;
public UInt32 dwFillAttribute;
public UInt32 dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public UInt32 dwProcessId;
public UInt32 dwThreadId;
}
enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3,
}
const UInt32 MAXIMUM_ALLOWED = 0x2000000;
const Int32 CREATE_UNICODE_ENVIRONMENT = 0x00000400;
const Int32 NORMAL_PRIORITY_CLASS = 0x20;
const Int32 CREATE_NEW_CONSOLE = 0x00000010;
[DllImport("kernel32.dll", SetLastError = true)]
static extern Boolean CloseHandle(IntPtr hSnapshot);
[DllImport("kernel32.dll")]
public static extern UInt32 WTSGetActiveConsoleSessionId();
[DllImport("Wtsapi32.dll")]
static extern UInt32 WTSQueryUserToken(UInt32 SessionId, ref IntPtr phToken);
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
extern static Boolean CreateProcessAsUser(
IntPtr hToken,
String lpApplicationName,
String lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Boolean bInheritHandle,
Int32 dwCreationFlags,
IntPtr lpEnvironment,
String lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
extern static Boolean DuplicateTokenEx(
IntPtr ExistingTokenHandle,
UInt32 dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 TokenType,
Int32 ImpersonationLevel,
ref IntPtr DuplicateTokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
static extern Boolean CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
Boolean bInherit);
[DllImport("userenv.dll", SetLastError = true)]
static extern Boolean DestroyEnvironmentBlock(IntPtr lpEnvironment);
/// <summary>
/// Creates the process in the interactive desktop with credentials of the logged in user.
/// </summary>
public static Boolean CreateProcessAsUser(String commandLine, String workingDirectory, out StringBuilder output)
{
Boolean processStarted = false;
output = new StringBuilder();
try
{
UInt32 dwSessionId = WTSGetActiveConsoleSessionId();
output.AppendLine(String.Format("Active console session Id: {0}", dwSessionId));
IntPtr hUserToken = IntPtr.Zero;
WTSQueryUserToken(dwSessionId, ref hUserToken);
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
IntPtr hUserTokenDup = IntPtr.Zero;
DuplicateTokenEx(
hUserToken,
(Int32)MAXIMUM_ALLOWED,
ref sa,
(Int32)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(Int32)TOKEN_TYPE.TokenPrimary,
ref hUserTokenDup);
if (hUserTokenDup != IntPtr.Zero)
{
output.AppendLine(String.Format("DuplicateTokenEx() OK (hToken: {0})", hUserTokenDup));
Int32 dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
IntPtr pEnv = IntPtr.Zero;
if (CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
output.AppendLine(String.Format("CreateEnvironmentBlock() success."));
}
else
{
output.AppendLine(String.Format("CreateEnvironmentBlock() FAILED (Last Error: {0})", Marshal.GetLastWin32Error()));
pEnv = IntPtr.Zero;
}
// Launch the process in the client's logon session.
PROCESS_INFORMATION pi;
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "winsta0\\default";
output.AppendLine(String.Format("CreateProcess (Path:{0}, CurrDir:{1})", commandLine, workingDirectory));
if (CreateProcessAsUser(hUserTokenDup, // client's access token
null, // file to execute
commandLine, // command line
ref sa, // pointer to process SECURITY_ATTRIBUTES
ref sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
workingDirectory, // name of current directory
ref si, // pointer to STARTUPINFO structure
out pi // receives information about new process
))
{
processStarted = true;
output.AppendLine(String.Format("CreateProcessAsUser() OK (PID: {0})", pi.dwProcessId));
}
else
{
output.AppendLine(String.Format("CreateProcessAsUser() failed (Last Error: {0})", Marshal.GetLastWin32Error()));
}
if (DestroyEnvironmentBlock(pEnv))
{
output.AppendLine("DestroyEnvironmentBlock: Success");
}
else
{
output.AppendLine(String.Format("DestroyEnvironmentBlock() failed (Last Error: {0})", Marshal.GetLastWin32Error()));
}
}
else
{
output.AppendLine(String.Format("DuplicateTokenEx() failed (Last Error: {0})", Marshal.GetLastWin32Error()));
}
CloseHandle(hUserTokenDup);
CloseHandle(hUserToken);
}
catch (Exception ex)
{
output.AppendLine("Exception occurred: " + ex.Message);
}
return processStarted;
}
}
}
그것은이 같은 지역의 실행 파일과 함께 좋은 작품 중복 토큰을 사용하여 네트워크 공유에 올바르게 액세스합니까?
이하여 DuplicateTokenEx의 반환 값을 확인하고 CreateProcessAsUser를 사용하여 실패한 이유에 대한 아이디어를 얻지 못하면 마지막 오류를 가져옵니다. –
@ 500-InternalServerError - DuplicateTokenEx는 정상적으로 작동하지만 CreateProcessAsUser는 5 : ERROR_ACCESS_DENIED를 제공합니다. 실제 사용자를 모방하기 위해 내가 바꿀 수있는 옵션에 대한 제안이 있습니까? – Joe
이것이 작동하는 것은 간단하지 않습니다. [이 질문] (http://stackoverflow.com/questions/8081429/createprocessasuser-doesnt-work-when-change-user) 몇 가지 단서를 제공 할 수 있습니다. –