【问题标题】:Why is exception from impersonated code not caught?为什么没有捕获模拟代码的异常?
【发布时间】:2013-03-03 23:41:48
【问题描述】:

我的 C# 代码通过 P/Invoke 调用 Win32 函数来使用模拟

internal class Win32Native
{
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int ImpersonateLoggedOnUser(IntPtr token);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int RevertToSelf();
}

try {
    var token = obtainTokenFromLogonUser();
    Win32Native.ImpersonateLoggedOnUser( token );
    throw new Exception(); // this is for simulation
    Win32Native.RevertToSelf()
} catch( Exception e ) {
    LogException( e );
    throw;
}

我还安装了AppDomain.CurrentDomain.UnhandledException 处理程序,它还会记录所有未处理的异常。

我确信记录异常的代码无论有没有模拟都可以正常工作。

现在的问题是,在上面的代码中,似乎没有输入catch,也没有调用UnhandledException。该异常的唯一痕迹是事件查看器中的一个条目。

如果我像这样添加finally

try {
    var token = obtainTokenFromLogonUser();
    Win32Native.ImpersonateLoggedOnUser( token );
    try {
       throw new Exception(); // this is for simulation
    } finally {
        Win32Native.RevertToSelf()
    }
} catch( Exception e ) {
    LogException( e );
    throw;
}

然后从catchUnhandledException 处理程序都可以正常记录异常。

发生了什么事?被模拟的线程是否会阻止通常的异常处理?

【问题讨论】:

  • 如果你在LogException 设置断点:你到达那里了吗?
  • @MarcGravell:我不知道,没有调试器可以复制它。我意识到LogException() 本身可能存在一些问题,但到目前为止,它所依赖的代码无论是模拟还是非模拟都运行良好。
  • 在这里猜测一下:由于 .NET 会跟踪执行上下文,因此异常处理可能会意识到上下文已更改并阻止异常处理程序执行,除非首先执行还原。如果代码与模拟用户一起运行,不这样做会导致特权提升...
  • 出于兴趣 - 你为什么选择原生路线而不是使用 WindowsIdentity 中的内置支持?
  • @Damien_The_Unbeliever:这是我碰巧在 Google 上找到的最好的。

标签: c# .net exception exception-handling impersonation


【解决方案1】:

如果没有看到 LogException 的代码,我无法确定,但可能是您在其中所做的任何事情都是在模拟/登录用户的上下文中执行的,并且该用户没有用户权限做任何你正在做的事情,例如写入文件等,然后代码在那时崩溃。您的代码仅在您“恢复为自我”之后才有效这一事实似乎证明了这一点。

所以我想说的是,你的异常很可能实际上被 catch 捕获了,但是 LogException 失败是因为它试图在不正确的用户的上下文中工作。

要对此进行测试,请在 LogException 中尝试将当前上下文强制设置为“Self”,然后再尝试任何日志记录,并查看第一个 sn-p 现在是否开始工作。

【讨论】:

    【解决方案2】:

    原来问题出在日志记录代码上。在某些时候,我们添加了检索当前进程开始时间 (Process.StartTime) 的代码,当从模拟线程调用该代码时,该代码会生成 Access denied

    Access is denied
    System.ComponentModel.Win32Exception
    at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
    at System.Diagnostics.Process.GetProcessTimes()
    at System.Diagnostics.Process.get_StartTime()
    //our logging code here
    

    记录代码也称为System.Diagnostics.Trace.WriteLine() 之前 使用Process.StartTime 调用代码并通过“跟踪侦听器”写入成功,仅通过后一个代码写入失败。

    因此,无论有没有模拟,捕捉异常都没有区别。甚至可以安装一个异常过滤器,以便在模拟代码的安全上下文中调用它,这可能导致特权提升。 Details for the latter here.

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 1970-01-01
      • 2011-11-28
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 2012-01-22
      相关资源
      最近更新 更多