为什么非模拟代码不被捕获?

时间:2023-01-16 15:41:10

My C# code uses impersonation by calling Win32 functions via P/Invoke

我的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;
}

also I have AppDomain.CurrentDomain.UnhandledException handler installed that also logs all unhandled exception.

我也有AppDomain.CurrentDomain。安装了UnhandledException处理器,并记录所有未处理的异常。

I'm sure that the code that logs exceptions works fine both with and without impersonation.

我确信日志异常的代码可以很好地处理模拟和非模拟。

Now the problem is that in the above code it looks like catch is not entered and UnhandledException is also not called. The only trace of the exception is an entry in the Event Viewer.

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

If I add a finally like this:

如果我像这样加上最后一个:

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

then the exception is logged okay both from catch and from UnhandledException handler.

然后从catch和UnhandledException处理程序记录异常。

What's happening? Does the thread being impersonated prevent usual exception handling?

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

2 个解决方案

#1


3  

Without seeing the code of the LogException, I can't be sure, but it could be that whatever you are doing in there is doing so in the context of the impersonated / loggedon user and that that user does not have user rights to be doing whatever it is you are doing e.g. writing to a file etc and that the code then crashes at that point. The fact that your code works only after you have "Reverted to Self" seems to bear this out.

LogException没有看到的代码,我不能确定,但它可能是,不管你是在这样的背景下扮演/ loggedon用户,该用户没有用户权利做你想做的任何事如写入文件代码等,然后崩溃。事实上,您的代码只有在您“返回到Self”之后才能工作,这似乎证明了这一点。

So what I'm trying to say it, chances are your exception is actually being caught by the catch, but that the LogException is failing due to it trying to do work in context of an incorrect user.

我想说的是,你的异常很可能会被捕获,但LogException会失败因为它试图在错误用户的环境中工作。

To test this out, inside your LogException, try force your current context to "Self" before attempting any logging and see whether the 1st snippet now starts working.

要测试这一点,请在LogException中,尝试在尝试任何日志记录之前将当前上下文强制为“Self”,并查看第一个代码片段现在是否开始工作。

#2


1  

Turns out the problem was with logging code. At some point we added code that retrieves current process start time (Process.StartTime) and that code yields Access denied when called from an impersonated thread.

原来问题出在日志代码上。在某些时候,我们添加了检索当前进程启动时间(process . starttime)的代码,并且当从模拟线程调用时,该代码会产生被拒绝的访问。

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

Logging code also called System.Diagnostics.Trace.WriteLine() before invoking code with Process.StartTime and writes through "trace listeners" succeeded, only writes through the latter code failed.

在调用进程代码之前,日志代码也被称为system .诊断。trace.writeline()。StartTime并通过“跟踪监听器”写入成功,只通过后一段代码写入失败。

So there's no difference in catching exceptions with or without impersonation. It's even possible to install an exception filter so that it is invoked in security context of impersonated code which can possibly result in privileges elevation. Details for the latter here.

因此,捕获具有或不具有模拟的异常没有区别。甚至可以安装异常过滤器,以便在模拟代码的安全上下文中调用异常过滤器,这可能导致特权提升。后面的细节。

#1


3  

Without seeing the code of the LogException, I can't be sure, but it could be that whatever you are doing in there is doing so in the context of the impersonated / loggedon user and that that user does not have user rights to be doing whatever it is you are doing e.g. writing to a file etc and that the code then crashes at that point. The fact that your code works only after you have "Reverted to Self" seems to bear this out.

LogException没有看到的代码,我不能确定,但它可能是,不管你是在这样的背景下扮演/ loggedon用户,该用户没有用户权利做你想做的任何事如写入文件代码等,然后崩溃。事实上,您的代码只有在您“返回到Self”之后才能工作,这似乎证明了这一点。

So what I'm trying to say it, chances are your exception is actually being caught by the catch, but that the LogException is failing due to it trying to do work in context of an incorrect user.

我想说的是,你的异常很可能会被捕获,但LogException会失败因为它试图在错误用户的环境中工作。

To test this out, inside your LogException, try force your current context to "Self" before attempting any logging and see whether the 1st snippet now starts working.

要测试这一点,请在LogException中,尝试在尝试任何日志记录之前将当前上下文强制为“Self”,并查看第一个代码片段现在是否开始工作。

#2


1  

Turns out the problem was with logging code. At some point we added code that retrieves current process start time (Process.StartTime) and that code yields Access denied when called from an impersonated thread.

原来问题出在日志代码上。在某些时候,我们添加了检索当前进程启动时间(process . starttime)的代码,并且当从模拟线程调用时,该代码会产生被拒绝的访问。

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

Logging code also called System.Diagnostics.Trace.WriteLine() before invoking code with Process.StartTime and writes through "trace listeners" succeeded, only writes through the latter code failed.

在调用进程代码之前,日志代码也被称为system .诊断。trace.writeline()。StartTime并通过“跟踪监听器”写入成功,只通过后一段代码写入失败。

So there's no difference in catching exceptions with or without impersonation. It's even possible to install an exception filter so that it is invoked in security context of impersonated code which can possibly result in privileges elevation. Details for the latter here.

因此,捕获具有或不具有模拟的异常没有区别。甚至可以安装异常过滤器,以便在模拟代码的安全上下文中调用异常过滤器,这可能导致特权提升。后面的细节。