Hook kernel exception handler with Windows driver - c++

I am looking to hook the exception handling process when a nonexecutable memory page is executed or a nonreadable memory page is read. I am unsure if this is possible without subverting PatchGuard. What kind of driver object do I need to create if this is possible?

Related

Where do I look to trace application exit call?

I have a VB.NET WinForms application which calls a video display subsystem written in Native C++. (DirectShow)
After a number of sessions rendering several video files, the application simply exits, without any indicators as to why.
There is no exception, unhandled or otherwise.
As best I can determine from log file records, the application exits when it should be at an idle state, waiting for the next window action (button click) on the form.
There is a Forms_Closing event handler, but it never seems to be called.
The problem is intermittent, and rare. I suspect some kind of memory corruption in the C++ Native code might be the cause.
How can I hook the method which is calling the "Application.Exit" processing?
Is there some other way to determine where the call originates which shuts down the application?

Rare EXCEPTION_ACCESS_VIOLATION when debugging any process started with CREATE_SUSPENDED

While writing an x86 WinAPI-based debugger, I've encountered a rare condition when the debuggee (which usually works well) suddenly terminates with EXCEPTION_ACCESS_VIOLATION after I attach to it with my native debugger. I can stably reproduce this on any applications it seems (tried on .NET Hello World-styled application and on notepad.exe on multiple Windows 10 machines).
Essentially I've written a simple WaitForDebugEvent loop:
CreateProcessW(L"C:\\Windows\\SYSWOW64\\notepad.exe", […], CREATE_SUSPENDED, […]);
DebugActiveProcess(processId);
DEBUG_EVENT debugEvent = {};
while (WaitForDebugEvent(&debugEvent, INFINITE)) {
switch (debugEvent.dwDebugEventCode) {
// log all the events
}
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
}
DebugActiveProcessStop(processId);
(here's the full listing: I won't paste it all here, because there's some additional non-essential boilerplate there; the MCVE is 136 lines long)
For the sake of an example, I'll just log all the debugger events and detect whether the debuggee is ready to "proceed normally" or it will terminate due to an exception.
Most of the time, my debugging session looks like that:
CREATE_PROCESS_DEBUG_EVENT (which reports creation of both the process and its initial thread)
LOAD_DLL_DEBUG_EVENT (I was never able to get the name for this DLL, but this is documented in MSDN)
CREATE_THREAD_DEBUG_EVENT (which, I suspect, is a thread injected by debugger)
LOAD_DLL_DEBUG_EVENT […] — after this, many DLLs get loaded into the target process and everything looks okay, the process works as intended
But sometimes (in about 1.5% of all runs), the event sequence changes:
CREATE_PROCESS_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
CREATE_THREAD_DEBUG_EVENT
EXCEPTION_DEBUG_EVENT: EXCEPTION_ACCESS_VIOLATION (which I never was able to gather details for: it reports a DEP violation, and the address is empty)
After that, I cannot proceed with debugging, because my debuggee is in exception state and will terminate soon. I was never able to catch notepad.exe crash without my debugger attached (and I doubt it is that bad and will crash for no reason), so I suspect that my debugger causes these exceptions.
One bizarre detail is that I could "fix" the situation by calling Sleep(1) immediately after WaitForDebugEvent. So, this is possibly some sort of race condition, but race condition between what? Between the debugger thread and other threads in the debuggee? Is it a thing? How are we supposed to debug other applications, then? How could actual debuggers work if it is a thing?
I couldn't reproduce the issue with the same code compiled for x64 CPU (and debugging an x64 process).
What could actually cause this erroneous behavior? I've carefully read the documentation about the API functions I call, and checked some other debugger examples online, but still wasn't able to find what's wrong with my debugger: it looks like I follow all the right conventions.
I have tried to debug my debuggee with WinDBG while it is still paused in my debugger, but had no luck doing that. First of all, it's difficult to attach to the debuggee with another debugger (WinDBG only allows to use non-intrusive mode, which is less functional it seems?), and the call stacks for the process' threads aren't usually meaningful.
Steps to reproduce
Checkout this repository, compile with MSVC and then execute in cmd:
Debug\NetRuntimeWaiter.exe > log.txt
It is important to redirect output to the log file and not show it in the terminal: without that, timings for the log writer get changed, and the issue won't reproduce (due to a possible race condition I mentioned earlier?).
Usually the program will start and terminate 1000 notepads in about 10 seconds, and 10-15 of 1000 invocations will hold the error condition (i.e. EXCEPTION_ACCESS_VIOLATION).
the DebugActiveProcess (and undocumented DbgUiDebugActiveProcess which is internally called by DebugActiveProcess) have serious design problem: after calling NtDebugActiveProcess it create remote thread in the target process, via DbgUiIssueRemoteBreakin call - as result new thread in target process is created - DbgUiRemoteBreakin - this thread call DbgBreakPoint and then RtlExitUserThread
all this not documented and explained, only this note from DebugActiveProcess:
After all of this is done, the system resumes all threads in the
process. When the first thread in the process resumes, it executes a
breakpoint instruction that causes an EXCEPTION_DEBUG_EVENT
debugging event to be sent to the debugger.
of course this is wrong. why is DbgUiRemoteBreakin first (??) thread ? and which thread resume first undefined. why not exactly write - we create additional (but not first) thread in process ? and this thread execute breakpoint.
however, when process already running - create this additional thread not create problems. but in case we create process in suspended state, and then just call DebugActiveProcess - the DbgUiRemoteBreakin really became first executing thread in process and process initialization was done on this thread, instead of created first thread. on xp this always lead to fail process initialize at connect to csrss phase. (csrss wait connect to it only on first created thread in process). on later systems this is fixed and process can execute as usual. but can and not, because thread on which it was initialized is exit. it can cause subtle problems.
solution here - not use DebugActiveProcess but NtDebugActiveProcess in it place.
the debug object we can create or via DbgUiConnectToDbg() and then get it via DbgUiGetThreadDebugObject() (system store debug object in thread TEB) or direct by call NtCreateDebugObject
also if we create debuggee process from another process(B) we can do next:
duplicate debug object from debugger process to this B process
call DbgUiSetThreadDebugObject(hDdg) just before call
CreateProcessW with DEBUG_ONLY_THIS_PROCESS or DEBUG_PROCESS
system will be use DbgUiGetThreadDebugObject() for get debug object
from your thread and pass it to low level process create api
remove debug object from your thread via
DbgUiSetThreadDebugObject(0)
really no matter who is create process with debug object. matter who is handle events posted to this debug object.
all undocumented api definitions you can take from ntdbg.h and then link with ntdll.lib or ntdllp.lib

Creating a watchdog to capture minidumps

I'm trying to add the functionality of capturing mini-dumps when my program crashes. From what I've read, this is best achieved by use of another application (the watchdog) that is used to host the real application, and performs the dump.
From looking at posts such as this, I've come up with the following (both App and WatchDog are implemented in C++ using Win32):
When the watchdog starts, it creates 2 events, an ExitedOk event, and an Exception event, both of which are set to be inheritable and aren't signalled. It also creates an inheritable file mapping.
The watchdog then launches the "real app", and waits in a WaitOnMultipleObjects for either ExitedOk or Exception to be signalled.
When the app starts, it creates the same 2 events (it will inherit the handles)
The app is configured such that if it exits ok, it signals ExitedOk, or if an unhandled exception occurs, it stores the exception/thread info using the inherited filemapping, signals Exception, and then sleeps(Infinite).
If the WaitOnMultipleObjects in the watchdog is signalled with an ExitedOk, nothing happens. If it is signalled with an Exception, then it reads the exception/thread info using the filemapping, and then calls MiniDumpWriteDump.
Clearly the Sleep() is an issue. Is this best resolved through another event? Such that the App waits until the watchdog signals some "FinishedCreatingDump" event?
Secondly, I thought that the whole point of the watchdog was so that you weren't doing any work in the crashed process that is potentially unstable? If I'm understanding the workflow correctly, and that you do indeed need the SetEvent/OpenFileMapping/MapViewOfFile in the process that actually crashed, isn't that just as bad as calling MiniDumpWriteDump from it?

How do I get at the exception information when using MiniDumpWriteDump out-of-process?

When using the MiniDumpWriteDump function to create a core dump of a process on Windows, it is recommended (e.g. here, and here) that the MiniDumpWriteDump is run from another "watchdog" process because it may well not work when called from within the same process.
At the moment, our application is calling it in-process on an unhandled exception (we do it from a watchdog thread). Since we sometimes have problems with it not working, we'd like to move it to a separate process.
Now, signalling the other process to start writing the dump is trivial (just use an event, semaphore, you name it) but how do I pass the LPEXCEPTION_POINTERS info I get for the callback function I register with SetUnhandledExceptionFilter to the other process so that it can be passed to MiniDumpWriteDumps ExceptionParam argument??
You also need the MINIDUMP_EXCEPTION_INFORMATION.ThreadId value. The simplest way, and the way I made it work, is to use a memory-mapped file to transfer both the ThreadId and the ExceptionPointers. And a named event to wake up the watchdog. It doesn't matter that the pointer is not valid in the context of the watchdog process.
Use CreateFileMapping + MapViewOfFile in the watched process as part of its initialization, OpenFileMapping + MapViewOfFile in the watchdog. Your SetUnhandledExceptionFilter should then only call GetCurrentThreadId() and copy the tid and the pExcept to the memory mapped file view, call SetEvent() to wake up the watchdog and block forever until the watchdog terminates it.
While Hans answer is correct, I found that an easier way is to use WM_COPYDATA to transfer information from main process to minidump process. Register a class and a HWND_MESSAGE type window with some custom names in minidump process, then wait for WM_COPYDATA message in WndProc. Use FindWindow with same class name and window name in main process to obtain HWND to your minidump window. Use SendMessage with this handle to send WM_COPYDATA message with whenever struct you want to use. This will block your application until minidump process will receive and process it. Note that one of WM_COPYDATA parameters is a handle to window that sent it, but you will still need to use OpenProcess to get a proper process handle to use in MiniDumpWriteDump, so a "minimal" message to send is probably
process ID (to obtain process handle with OpenProcess)
thread ID (to initialize MINIDUMP_EXCEPTION_INFORMATION)
LPEXCEPTION_POINTERS (to initialize MINIDUMP_EXCEPTION_INFORMATION)
This way you will get all the necessary data in minidump's WndProc to call MiniDumpWriteDump. Make sure to set ClientPointers field in MINIDUMP_EXCEPTION_INFORMATION to TRUE since we're debugging external process. Note that when running under debugger in MSVC the call to MiniDumpWriteDump might produce flurry of exceptions like trying to read invalid memory address - simply ignore this, it's normal (and you don't need to intercept any of those)
Once your minidump process finished writing the dump, it will return from WndProc and main process will return from SendMessage. Then you can either terminate your main app or do any other stuff in exception handler (e.g. we show a nice message box to user and close the app gracefully).

Callback from other thread

I have problem with callbacks from other application thread. Dll is some kind of wrapper between Addinational application and Application program and its working within Application program memory(with same PID). Addinational application(other thread and PID) is application which in main loop looking for "something" and when found it, it calls Callback function from Dll and then Dll calls Callback function from Application program. Maybe its little confusing look at image above.
And theres crash(when dll calls callback function from application program) with message:
Unhandled exception at 0x70786a46 in MainProgram.exe: 0xC0000005: Access violation reading location 0x00000164.
Call stack mshtml.dll
Propably application program using IE controls to update UI. How could I update UI when Addinational application callsback?
SendMessage is a general solution for posting results to a GUI thread. It does all thread synchronization for you and doesn’t return until the message has been processed by the receiver thread's window.
PostThreadMessage is less reliable since the message may/will be lost when the receiver is in a modal loop for e.g. MessageBox, unless you have added a hook that intercepts the thread message – so just use SendMessage.
More advanced techniques involve doing the thread synchronization yourself, e.g. with a buffer, but anyway that will probably also involve SendMessage for a GUI thread, so, I suggest you just start with that, and if that’s good enough, then don’t do more.
EDIT: dang, I see now that although the first sentence talks about threads, it's really about sending data from one process to another process. Well, for that there is WM_COPYDATA. Please consider that a (user level) pointer from one process, is not valid in the other process.
So you want to call a function that belongs to another process. I think you need to read about RPC:s http://msdn.microsoft.com/en-us/library/windows/desktop/aa378651%28v=vs.85%29.aspx