Handle access violations in COM interop - c#

My managed app is using COM interop. Unfortunately there is a bug in the COM component that causes access violation. When the bug is hit, the whole app crashes, the handler attached to AppDomain.CurrentDomain.UnhandledException didn't get a chance to run. I wonder if there is a way to handle the AV, show a friendly message to the user and recover the managed app?

There is NO way to "handle" an Access Violation.
Depending on the component you are using and how it is implemented even isolating it inside a second AppDomain might still crash your process - AppDomains are "only" a .NET-thing, from the native perspective of the OS they are NOT isolated.
IF you have some problematic component you can always make your usage of it more robust by using the following approach:
Create a process (EXE) which wraps the usage of that component and exposes an API (for example via any IPC mechanism). You can then start that EXE as a separate process (from your main EXE) and use it... IF you need to kill that component after a certain time and/or when some condition is met you can always kill that "wrapper EXE" from your main EXE... depending on the specific component it might even be useful to implement some special "cleanup code" (possibly in a separate thread) within that "wrapper EXE" which gets executed when you need to kill that "wrapper EXE".
Since you are implementing this in .NET you can even have that "wrapper EXE" as "embedded resource" in your main executable and start it even from RAM without writing it to the filesystem.

There is fundamentally no way to "handle" an Access Violation. You have no way to know which memory the COM component has trashed before it sent the AV.
The only thing you can do with a component like this is to try to run it in a separate AppDomain. That way, if it crashes, it only crashes one AppDomain.

Related

Prevent native C++ DLL crashing C# App

We have a c# WPF app and we use a 3rd party SDK with a native C++ DLL, we call the methods with DllImport attributes.
Unfortunately code is not that great and that C++ DLL crashes our C# app.
Is there an elegant and efficient way to isolate the calls to the C++ DLL so their exceptions don't crash our app? We are getting a stream of images and data so it needs to be fast.
We use WCF to offload some operations in a windows service, so we have an infrastructure to do this, but I don't think it will be fast enough to transfer data and image buffers to/from it.
Would a different AppDomain be a good choice? Any examples how to do this?
thanks
Its probably the right behaviour to terminate the app in this situation. If you have control over the DLL I would consider handling its exceptions differently
From memory, i believe (in early versions of .Net) you could just catch via ExternalException class:
Note : .NET v4 and above it disables the delivery of certain exceptions by default
To reenable this i 'believe' you can just edit your manifest or use an attribute, take a look at
legacyCorruptedStateExceptionsPolicy Element
HandleProcessCorruptedStateExceptionsAttribute Class
a similar crash occured to me not long ago.I think first you should resove the native dll error . There is no way that you can use to catch an exception from a native code.
The only way to make sure the C++ DLL does not crash your C# process is to move it to another process which you can restart if it crashes.
You can wrap the C++ DLL in a separate application / service and communicate with your C# application via named pipes to transfer the image data. You will also need some kind of heart beat to detect if the wrapper crashed and restart it as needed.
We implemented this solution for a microscope which came with an ActiveX component that kept crashing our application. This approach worked well and was fast enough.
AppDomains don't provide isolation for native assemblies as they use unmanaged memory, due to this I'm not sure if an access violation in a secondary app domain will bring down your whole process.
I'm guessing that your problem is due to state corruption. So before trying to outboard the service you can try catching those exceptions.
How to handle AccessViolationException
So long as the library itself can recover, you might be OK. Worth giving a go.

Running a .Net application in a sandbox

Over the months, I've developed a personal tool that I'm using to compile C# 3.5 Xaml projects online. Basically, I'm compiling with the CodeDom compiler. I'm thinking about making it public, but the problem is that it is -very-very- easy to do anything on the server with this tool.
The reason I want to protect my server is because there's a 'Run' button to test and debug the app (in screenshot mode).
Is this possible to run an app in a sandbox - in other words, limiting memory access, hard drive access and BIOS access - without having to run it in a VM? Or should I just analyze every code, or 'disable' the Run mode?
Spin up an AppDomain, load assemblies in it, look for an interface you control, Activate up the implementing type, call your method. Just don't let any instances cross that AppDomain barrier (including exceptions!) that you don't 100% control.
Controlling the security policies for your external-code AppDomain is a bit much for a single answer, but you can check this link on MSDN or just search for "code access security msdn" to get details about how to secure this domain.
Edit: There are exceptions you cannot stop, so it is important to watch for them and record in some manner the assemblies that caused the exception so you will not load them again.
Also, it is always better to inject into this second AppDomain a type that you will then use to do all loading and execution. That way you are ensured that no type (that won't bring down your entire application) will cross any AppDomain boundary. I've found it is useful to define a type that extends MarshalByRefObject that you call methods on that executes insecure code in the second AppDomain. It should never return an unsealed type that isn't marked Serializable across the boundary, either as a method parameter or as a return type. As long as you can accomplish this you are 90% of the way there.

How to deal with exceptions on separate threads in an external dll?

I'm loading in a dll that spawns a few threads within itself. Every now and then the program crashes with an unhandled exception. I can't wrap all my library calls in try/catch statements because the exceptions are being thrown on separate threads, and I don't have access to the library's source to debug/fix the bad error handling. I'd like the program to keep doing other things when these exceptions happen, is there a graceful way to handle these exceptions? Or is the only thing I can do to do a global catch all exceptions method?
If you load the DLL into a separate appdomain, you should be able to isolate exceptions generated with a AppDomain.UnhandledException, but, be aware that this is not fool proof and there are certain situations where it will still take your process out too and there is nothing you can do about it (stack overflow, out of memory etc).
The best you can do in that case is load them in a separate process completely with some kind of dll communication harness and using some form of remoting to talk to that process.
I would recommend to implement a separate process (EXE) which your application launches and which in turn loads the DLL.
This allows you to kill/restart the process whenever need be...
I see several options on how to communicate - for example:
you could use COM (if you implement it as an out-of-process COM server)
you could use shared memory (very high performance, see this for a walkthrough and this for a .NET 2 wrapper)
IF the method must be compatible with several Windows versions THEN I would refrain from using anything "networky" for the IPC (since some come with a desktop firewall).

How to host Plug-ins safely with .NET 2.0

I am writing a chess game which allows two programs compete, the player needs to write a DLL and expose a function to tell the main application where his player will move next, suppose the function looks like this
public static void MoveNext(out int x, out int y, out int discKind);
The player's DLL can be written using C# or C++.
In the chess game application, I start a new thread to call the function that the player's DLL exposed to get where he will move in a turn, and I start a timer to prevent the player timeouts, if a player timesout i will kill the corresponding thread by following APIs
thread.Abort();
thread.Join();
I have the following issues as described below:
The thread cannot be killed with 100% assurance (it depends on the player's code)
During test I found that, if the player uses a deep recursions (and if there is memory leak in the player's program), the memory usage of the host application will increase and then the host application will be terminated without any exceptions.
Are there any techniques, ideas or methods that can handle the above issues?
From this CodeInChaos suggested to load player's DLL into separate domain and then unload it when necessary, I am not sure if it still works for the unmanaged DLL (C++) and if it will cause a low efficiency?
An unhandled exception in their AppDomain will still cause your program to terminate in .Net 2.0. You get a chance to respond to the exception through an event handler but not the ability to handle it.
Your best bet is to use processes for the kind of isolation you're looking for.
If you can ensure your plugin DLL's are always managed code, then you have the option of createing a new application domain in your main application logic and loading the assembly containing the plugin into that domain.
This then gives you the option of trapping unhandled excpetions in that specific app domain and you then have the option of Unloading that whole app domain. That way you can cope with other peoples application plugins misbehaving and throwing exceptions. you also gain the option of specifying partial trust to further restrict what a plugin can do.
However this will not help if you cannot enforce the use of managed code plugins, and the earlier option of a set of seperate processes would be more apropriate.
Reading your post agin it seems you have some quality issues with the plugins you have to use. If you must cope with such buggy plugins I would take the previous advice and go with seperate processes.

How to share a process?

How can I snuggle into another process? Like, share another process's name? So if my application is griddemo.exe, and I want to snug into, let's say, explorer.exe, is that possible? Just read something about CreateRemoteThread() from kernel32. Is that in the right direction? Would there be security/UAC issues?
First of all sorry, but my answer will be longer as another answers.
I use DLL injection since years in different version of operation system (from windows NT 4.0 till Windows 7) and I had no time any problem with any virus scanner (inclusive both Norton and McAfee in different versions). So I disagree with Stephen Cleary (see his answer) in this aspect.
Usage of CreateRemoteThread() is really only one of the ways. AppInit_DLLs is another way. Both has its advantage and disadvantage. The main advantage of AppInit_DLLs is a simplicity to inject DLL in any process. The main disadvantages of AppInit_DLLs approach are following:
All GUI application will load the DLL. If you want to load it only in one process like explorer.exe you can't do this. So the working space of all GUI processes will be increased by your DLL. An error in your DLL (especially inside of DllMain or in any dependency DLL of your DLL) can crash many processes which you don't currently know.
You can not inject your DLL with respect of AppInit_DLLs approach in a console application or in any EXE which have no dependency to User32.dll.
You should be very careful inside of your DllMain, because it will be called before User32.dll will be full initialized. So a safe DLL which you can use inside of DllMain of your DLL is Kernel32.dll.
With respect of CreateRemoteThread() one can start an additional thread in a process. The main problem of CreateRemoteThread() is that its lpStartAddress parameter must be an address from the remote process. So one have to use functions OpenProcess, VirtualAllocEx and WriteProcessMemory to write some information into the memory of the destination process. To be able to open a process one have to have debug privilege enabled. If you want to do only 2 + 2 inside of the destination process you can copy the corresponding binary code directly into destination process. All real interesting work can be done with usage of some Windows API. So mostly one don't copy a code. Instead of that one call LoadLibrary("MyPath\\MyDll.dll") inside of destination process. Because the prototype of LoadLibrary is the same as prototype of ThreadProc of CreateThread you can call LoadLibrary as a ThreadProc of CreateRemoteThread(). This way has the name DLL Injection.
I recommend you to use this DLL Injection only if it really required. If your destination application has some other way like plug-ins to load you DLL inside the process your should use this way instead of DLL Injection.
Some general problems you will have to solve after you have a working example of DLL Injection. This problems you can don't see at the first time, but after a long usage of your application you will see its importance:
You should find the moment when the destination process are already running before you can use CreateRemoteThread().
The destination application must be already initialized before you call CreateRemoteThread(). So you should not use CreateRemoteThread() too early. In case of explorer.exe you can use a start of your small trigger program from Run registry key. At the moment is explorer.exe fully prepared for DLL injection.
You should take in consideration 64-bit version of Windows.
Don't forget about DLL relocation inside of destination process. Be careful, that you DLL can be loaded in the destination process at the other address as in your process. Mostly it is a good idea to choose a good base address (linker option) for you DLL which you will inject. The Kernel32.dll can be sometime (very seldom) loaded at the other address as in your source process. You can create a DLL Injection code which are free of this problem.
Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process. The problem you can see on XP (which is not connected to domain) or especially on Vista or Windows 7 if you try make DLL injection from a windows service. To fix the problem you should make DLL Injection either from the process running on the same terminal session as destination process or you have to switch current session before using of CreateRemoteThread. Your process must have SE_TCB_NAME privilege enabled and use SetTokenInformation with TokenSessionId parameter. To get session id of the destination process you can use different methods. Functions with the prefix WTS (like WTSGetActiveConsoleSessionId) can be very useful.
So everything is not very easy, but it is really interesting subject where you can study a lot of things about operating system. You should only spend a little time to analyse your problem and different ways to solve it before you choose one way which corresponds your project requirements and start programming.
DLL injection is the traditional method of doing this. It's quite tricky, especially since virus scanners look askance at the practice. So even if you get it working, Norton/McAfee would be likely to block you - or block you in the future.
One easy way of DLL injection is the AppInit_DLLs registry value. Note that Microsoft has reserved the right to simply remove this functionality (and likely will do so in the future).
The Microsoft-approved way to achieve DLL injection is licensing Microsoft Detours.
Note that your DLL must be built against the CLR version 4.0 or higher to perform DLL injection safely, because this is the first version to support in-proc side-by-side.
If you mean injecting your code into another process, then dll injection is one technique:
http://en.wikipedia.org/wiki/DLL_injection
Haven't done this for years, so not sure how happy modern MS Windows operating systems (i.e. post XP) are going to be with this.
I've not tried this lately, but another way to do this would be to create a Hook DLL:
Create a DLL that contains a Hook Procedure like MessageProc.
Install this DLL into Windows\System32.
Use FindWindows(Ex) to locate your victim process' window.
Use GetWindowThreadProcessId() to find the owning thread of that window. This is necessary to avoid injecting your DLL into every single process on the system.
Use SetWindowsHookEx to hook that thread.
PostMessage a WM_USER message to the window - activating your Hook DLL if it isn't already active.
This would likely invoke the new Windows Vista/7 UIPI/UAC if you're not a sufficiently privileged user but this depends on many factors - your mileage may vary.

Categories

Resources