Я только что потратил 2 дня на то, чтобы прочитать кучу материала об олицетворении в C # (включая статьи, посвященные stackoverflow и codeproject), и вот результат моих исследований.
Если коротко, я просто хочу начать иостановить службу из приложения winform, работающего под стандартной (непривилегированной) учетной записью пользователя.Я хочу выдать себя за моего пользователя с учетной записью администратора.Обе учетные записи являются локальными учетными записями.
В приведенном ниже коде я не получаю никаких ошибок при извлечении токена (посредством вызовов Interop), но вызовы servicecontroller.Start и servicecontroller.Stop всегда завершаются неудачей.
Все статьи в Интернете описывают один и тот же процесс, чтобы выдавать себя за пользователя, но до сих пор я не мог заставить его работать или даже понять, что происходит не так.
У кого-нибудь естьПодсказка о том, что не так, понимаешь ...
Заранее спасибо
- Бруно
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
private void button1_Click(object sender, EventArgs e)
{
WindowsImpersonationContext wic = ImpersonateUser(
"Administrator",
"machinename",
"password");
try
{
ServiceController sc = new ServiceController("SERVICE_PERE");
Process p = new Process();
sc.Start();
}
catch (Exception ex)
{
Debugger.Break();
}
finally
{
wic.Undo();
}
}
private void button2_Click(object sender, EventArgs e)
{
WindowsImpersonationContext wic = ImpersonateUser(
"Administrator",
"machinename",
"password");
try
{
ServiceController sc = new ServiceController("SERVICE_PERE");
sc.Stop();
}
catch (Exception ex)
{
Debugger.Break();
}
finally
{
wic.Undo();
//CodeAccessPermission.RevertAssert();
}
}
public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
{
// initialize tokens
IntPtr pExistingTokenHandle = new IntPtr(0);
IntPtr pDuplicateTokenHandle = new IntPtr(0);
pExistingTokenHandle = IntPtr.Zero;
pDuplicateTokenHandle = IntPtr.Zero;
// if domain name was blank, assume local machine
if (sDomain == "")
sDomain = System.Environment.MachineName;
try
{
string sResult = null;
const int LOGON32_PROVIDER_DEFAULT = 0;
// create token
const int LOGON32_LOGON_INTERACTIVE = 2;
//const int SecurityImpersonation = 2;
// get handle to token
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref pExistingTokenHandle);
// did impersonation fail?
if (false == bImpersonated)
{
int nErrorCode = Marshal.GetLastWin32Error();
sResult = "LogonUser() failed with error code: " +
nErrorCode + "\r\n";
// show the reason why LogonUser failed
//MessageBox.Show(this, sResult, "Error",
// MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Get identity before impersonation
sResult += "Before impersonation: " +
WindowsIdentity.GetCurrent().Name + "\r\n";
bool bRetVal = DuplicateToken(pExistingTokenHandle,
2, ref pDuplicateTokenHandle);
// did DuplicateToken fail?
if (false == bRetVal)
{
int nErrorCode = Marshal.GetLastWin32Error();
// close existing handle
CloseHandle(pExistingTokenHandle);
sResult += "DuplicateToken() failed with error code: "
+ nErrorCode + "\r\n";
// show the reason why DuplicateToken failed
//MessageBox.Show(this, sResult, "Error",
// MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
else
{
// create new identity using new primary token
WindowsIdentity newId = new WindowsIdentity
(pDuplicateTokenHandle);
WindowsImpersonationContext impersonatedUser =
newId.Impersonate();
// check the identity after impersonation
sResult += "After impersonation: " +
WindowsIdentity.GetCurrent().Name + "\r\n";
//MessageBox.Show(this, sResult, "Success",
// MessageBoxButtons.OK, MessageBoxIcon.Information);
return impersonatedUser;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
// close handle(s)
if (pExistingTokenHandle != IntPtr.Zero)
CloseHandle(pExistingTokenHandle);
if (pDuplicateTokenHandle != IntPtr.Zero)
CloseHandle(pDuplicateTokenHandle);
}
}
}
public enum LogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
LOGON32_LOGON_NEW_CREDENTIALS = 9,
}
public enum LogonProvider
{
LOGON32_PROVIDER_DEFAULT = 0,
}