* Copyright (c) 2007-2010 VMware, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include "../security-win32/except.h"
#include <setjmp.h>
#include "tools.h"
jmp_buf mark;
int count = 0;
* the saved EIP should point to the byte after the instruction
* which should be the beginning of the next instruction.
* (Note debuggers normally overwrite existing instructions
* and then would have to decrement EIP by 1 (since they know they used 0XCC)
* to execute to original interrupted instruction.)
*/
#define TRAP_OPT() __pragma optimize("", off) __debugbreak() __pragma optimize("", on)
#define TRAP() __asm { int 3 }
#define TRAP_TWO_BYTE() __asm { __emit 0xcd __emit 0x03 }
* but in our mode should be handled ok
*/
#define SINGLE_STEP() __asm { int 1 }
#define DEBUGGER_INTERFACE() __asm { int 2d }
*/
* the instruction why am I getting the original instruction natively?
*/
#define SKIP_INT3 ((GetExceptionInformation())->ContextRecord->CXT_XIP++)
int
TrapIfDebugger()
{
int trapped = 0;
__try {
TRAP();
trapped = 1;
} __except (SKIP_INT3, EXCEPTION_CONTINUE_EXECUTION) {
}
return !trapped;
}
int
TrapIfDebuggerVerbose()
{
EXCEPTION_RECORD exception;
CONTEXT *context;
int dbg = 0;
int trapped = 0;
print("about to trap\n");
__try {
initialize_registry_context();
TRAP();
print("continued after trap\n");
dbg = 1;
} __except (
context = (GetExceptionInformation())->ContextRecord,
dump_exception_info((GetExceptionInformation())->ExceptionRecord, context),
trapped = 1, print("in filter\n"),
(GetExceptionInformation())->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT
?
SKIP_INT3,
EXCEPTION_CONTINUE_EXECUTION :
EXCEPTION_CONTINUE_SEARCH) {
print("handler NOT REACHED\n");
}
if (!trapped)
print("didn't trap, continued in debugger?!\n");
return !trapped;
}
int
invalid_handle()
{
int dbg;
* kernel32!CloseHandle */
print("Invalid handle about to happen\n");
print("about to close\n");
__try {
HANDLE h = (HANDLE)9999;
dbg = 1;
CloseHandle(h);
dbg = 0;
} __except (print("in close filter\n", EXCEPTION_CONTINUE_EXECUTION)) {
}
print("continued successfully\n");
return dbg;
}
#define name_status(x, s) \
if ((x) == (s)) \
print(#s);
#include <windows.h>
static LONG
our_top_handler(struct _EXCEPTION_POINTERS *pExceptionInfo)
{
print("caught exception " PFX ": ", pExceptionInfo->ExceptionRecord->ExceptionCode);
name_status(pExceptionInfo->ExceptionRecord->ExceptionCode,
STATUS_GUARD_PAGE_VIOLATION);
name_status(pExceptionInfo->ExceptionRecord->ExceptionCode, STATUS_BREAKPOINT);
name_status(pExceptionInfo->ExceptionRecord->ExceptionCode, STATUS_SINGLE_STEP);
name_status(pExceptionInfo->ExceptionRecord->ExceptionCode, STATUS_INVALID_HANDLE);
count++;
print("exception, instance %d\n", count);
longjmp(mark, count);
}
int
main(int argc, char *argv[])
{
int i, j;
int dbg;
USE_USER32();
INIT();
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)our_top_handler);
i = setjmp(mark);
print("Test %d\n", i);
switch (i) {
case 0:
dbg = TrapIfDebuggerVerbose();
print("%s\n", dbg ? "debugger handled on first chance" : "not handled");
case 1:
dbg = TrapIfDebugger();
print("%s\n", dbg ? "debugger handled on first chance" : "not handled");
case 2:
dbg = invalid_handle();
print("%s\n", dbg ? "debugger handled on first chance" : "not handled");
default:;
}
print("All done\n");
return 0;
}