📄 seh.cpp
字号:
/*++
This file is mostly derived from mamaich's debugger codename BlindStudio.
Copyleft (c) 2002 Sten
Contact information:
mail: stenri@mail.ru
Copyright (c) 2001 mamaich
Contact information:
web: www.reversing.net/mamaich
mail: mamaich@reversing.net
ICQ# 70241285
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Module Name:
seh.cpp
Abstract: Exception handler
Revision History:
Sten 05/06/2002
The file is fully rewritten for better understanding.
mamaich 14/06/2001
Initial release
--*/
extern "C"{
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}
#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#pragma warning ( disable: 4127 ) // conditional expression is constant
#include "defs.h"
#include "undoc.h"
#include <stdio.h>
#define MAX_HANDLERS 0x12
static void *OldHandlers[MAX_HANDLERS];
static int SehInited=0;
static int IntNo=0;
static char *IntrDescr[MAX_HANDLERS+1]=
{
"Divide by zero", // #00
"Debug exception", // #01
"NMI", // #02
"Breakpoint exception", // #03
"Overflow exception", // #04
"BOUND range exceeded", // #05
"Invalid opcode", // #06
"Coprocessor not available", // #07
"Double fault", // #08
"Coprocessor segment overrun", // #09
"Invalid TSS", // #0A
"Segment not present", // #0B
"Stack fault", // #0C
"General protection exception", // #0D
"Page-fault exception", // #0E
"Floating point error", // #0F
"Alignment check", // #10
"Machine-check exception", // #11
"KeBugCheckEx called" // Bug Check
};
void InstallBugCheckHandler(void *Handler);
///////////////////////////////////////////////////////////////////////////
//
// Handler for all processor-generated exceptions & KeBugCheckEx
//
///////////////////////////////////////////////////////////////////////////
void __declspec(naked) MyIntr(void)
{
__asm
{
pushad
push fs
push ds
push es
mov eax,23h
mov ds,ax
mov es,ax
mov ebp,esp
// sub esp,__LOCAL_SIZE
sti
}
static int Dbg;
Dbg = 0;
if (IntNo == MAX_HANDLERS)
{ // BugCheckEx called
static int BCC; // Bug Check Code
static int BC1; // Param 1
static int BC2; // Param 2
static int BC3; // Param 3
static int BC4; // Param 4
__asm
{
mov eax,[esp+12+32+4]
mov BCC, eax
mov eax,[esp+12+32+8]
mov BC1, eax
mov eax,[esp+12+32+12]
mov BC2, eax
mov eax,[esp+12+32+16]
mov BC3, eax
mov eax,[esp+12+32+20]
mov BC4, eax
}
DbgPrint("SEH: Warning! BugCheckEx %08X: %08X, %08X, %08X, %08X\n",
BCC, BC1,BC2,BC3,BC4);
DbgPrint("SEH: Warning! System is unstable.\n");
}
if (Dbg)
DbgPrint("SEH: Exception %02x (%s) caught!\n", IntNo, IntrDescr[IntNo%(MAX_HANDLERS+1)]);
if (0) // IntNo==0xE) // TODO: if this is a page fault - try to resolve if myself
{
//*! Not implemented
}
static EXCEPTION_REGISTRATION_RECORD *FirstRec;
static EXCEPTION_REGISTRATION_RECORD *Rec;
__asm
{
mov eax,fs:[0]
mov Rec,eax
}
FirstRec=Rec;
while ((ULONG)Rec!=-1)
{
if(Dbg)
DbgPrint("SEH: Exception Handler: %08X\n", Rec->Handler);
static CONTEXT Ctx;
static EXCEPTION_RECORD Er;
Er.ExceptionCode=0xc0000005;
Er.ExceptionFlags=0;
Er.ExceptionRecord=(EXCEPTION_RECORD*)-1;
Er.ExceptionAddress=(void*)Ctx.Eip;
Er.NumberParameters=0;
__asm
{
mov eax, [esp+12+8]
mov Ctx.Ebp,eax
mov eax,[esp+12+12]
add eax,8
mov Ctx.Esp,eax
mov eax,[esp+12+32] // This is one handler for all exceptions, so
cmp eax,0x80000000 // skip error code on stack if it is present
ja Ok
mov eax,[esp+12+32+4]
Ok: mov Ctx.Eip,eax
}
if (Dbg)
{
static bool DblFault=false;
if(!DblFault)
{
DblFault=true;
DbgPrint("SEH: Exception at Eip=%08X, Esp=%08X\n",Ctx.Eip,Ctx.Esp);
DbgPrint("Stack trace: (not implemented)\n");
// DisplayStackTrace(Ctx.Eip, Ctx.Ebp);
DbgPrint("Stack trace finished.\n");
DblFault=false;
}
}
if (Rec->Handler(&Er, Rec, &Ctx, &Ctx)!=ExceptionContinueSearch)
{
while(FirstRec!=Rec)
{
static CONTEXT CtxUw;
static EXCEPTION_RECORD ErUw;
if (Dbg) DbgPrint("SEH: Unwinding...\n");
ErUw.ExceptionCode=0xC0000027; // Unwind
ErUw.ExceptionFlags=2;
ErUw.ExceptionRecord=(EXCEPTION_RECORD*)-1;
ErUw.ExceptionAddress=(void*)Ctx.Eip;
ErUw.NumberParameters=0;
FirstRec=FirstRec->Next;
FirstRec->Handler(&ErUw, FirstRec, &CtxUw, &CtxUw);
}
DbgPrint("SEH: Exception handled. Resuming execution from %08X\n", Ctx.Eip);
DbgPrint("SEH: Hanging up... Continuing exceptions is not implemented!\n");
__asm sti;
a: goto a;
}
Rec=Rec->Next;
}
DbgPrint("SEH: Internal error! This code should never be executed!\n");
// this function never returns
__asm sti;
b: goto b;
}
void InitSEH()
{
#include <pshpack1.h> // turn one byte packing of structures on
static struct Intr
{
UCHAR Bytes[2]; // 0xc7, 0x05 - mov IntNo,_number_
VOID *IntNoPtr;
ULONG IntNum;
UCHAR Push; // 0x68 - push MyIntr
VOID *FuncAddr;
UCHAR Retn; // 0xc3 - retn
} Handlers[MAX_HANDLERS+1];
#include <poppack.h> // turn packing of structures off
if (SehInited) return;
for(int i=0; i<MAX_HANDLERS+1; i++)
{
Handlers[i].Bytes[0]=(UCHAR)0xc7;
Handlers[i].Bytes[1]=(UCHAR)0x05;
Handlers[i].IntNoPtr=&IntNo;
Handlers[i].IntNum=i;
Handlers[i].Push=(UCHAR)0x68;
Handlers[i].FuncAddr=MyIntr;
Handlers[i].Retn=(UCHAR)0xc3;
}
// for(i=0; i<MAX_HANDLERS; i++)
// {
// OldHandlers[i]=SetInterruptHandler(i, &Handlers[i]);
// }
// Under NtIce don't hook anything except page faults
OldHandlers[0xE] = SetInterruptHandler(0xE, &Handlers[0xE]);
InstallBugCheckHandler(&Handlers[MAX_HANDLERS]);
SehInited++;
}
////////////////////////////////////////////////////////////////////////////
//
// Cleanup SEH
//
////////////////////////////////////////////////////////////////////////////
void CleanupSEH()
{
// for(int i=0; i<MAX_HANDLERS; i++)
// {
// SetInterruptHandler(i,OldHandlers[i]);
// }
SetInterruptHandler(0xE, OldHandlers[0xE]);
RemoveBugCheckHandler();
SehInited--;
}
////////////////////////////////////////////////////////////////////////////
//
// Internal. Installs the KeBugCheckEx hook
//
////////////////////////////////////////////////////////////////////////////
static bool KEBInit=false;
static char PrevKEBBytes[6];
void InstallBugCheckHandler(void *Handler)
{
char *KB = (char*)KeBugCheckEx; // Get the start address of KeBugCheckEx
if (KEBInit) return;
for(int i=0; i<6; i++) PrevKEBBytes[i]=KB[i];
KEBInit=true;
KB[0]=0x68; // Push MyIntr
*(PULONG)(KB+1)=(ULONG)Handler;
KB[5]=(UCHAR)0xc3; // Ret
}
////////////////////////////////////////////////////////////////////////////
//
// Internal. Uninstalls the KeBugCheckEx hook
//
////////////////////////////////////////////////////////////////////////////
void RemoveBugCheckHandler()
{
if (KEBInit)
{
char *KB=(char*)KeBugCheckEx; // Get the start address of KeBugCheckEx
for (int i=0; i<6; i++)
KB[i]=PrevKEBBytes[i];
KEBInit=false;
}
}
////////////////////////////////////////////////////////////////////////////
//
// Internal. Used in PageIn
//
////////////////////////////////////////////////////////////////////////////
void HookKeBugCheckEx()
{
#include <pshpack1.h> // turn one byte packing of structures on
static struct Intr
{
char Bytes[2]; // 0xc7, 0x05 - mov IntNo,_number_
void *IntNoPtr;
int IntNum;
char Push; // 0x68 - push MyIntr
void *FuncAddr;
char Retn; // 0xc3 - retn
}Handler;
#include <poppack.h> // turn packing of structures off
Handler.Bytes[0]=(UCHAR)0xc7;
Handler.Bytes[1]=(UCHAR)0x05;
Handler.IntNoPtr=&IntNo;
Handler.IntNum=MAX_HANDLERS;
Handler.Push=(UCHAR)0x68;
Handler.FuncAddr=MyIntr;
Handler.Retn=(UCHAR)0xc3;
InstallBugCheckHandler(&Handler);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -