安全搜索进程内存空间(二)

来源:互联网 发布:现在在淘宝开店晚吗 编辑:程序博客网 时间:2024/06/10 03:30
 

2、异常信息

当一个异常发生时,操作系统向异常处理的线程堆栈中压入3个结构,这三个结构是:EXCEPTION_RECORDCONTEXT EXCEPTION_POINTERS

1、 EXCEPTION_ RECORD结构

EXCEPTION_ RECORD结构包含了有关最近发生异常的详细信息,这些信息独立于CPU。其结构如下:

EXCEPTION_ RECORD STRUCT {

   +0 DWORD        ExceptionCode       ;异常代码

   +4 DWORD        ExceptionFlags         ;异常标志

   +8 struct       EXCEPTION_RECORD ;指向另一个EXCEPTION_ RECORD的指针

   +C PVOID        ExceptionAddress       ;异常发生的地址

   +10 DWORD        NumberParatemeters    ;与异常联系的参数数量(0-15

   +14 ULONG_PTR   ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]

} EXCEPTION_ RECORD

其中,ExceptionCode字段定义了产生异常的原因。图二中表示程序引发了一个EXCEPTION_ACCESS_VIOLATION异常,异常代码为0xC0000005,查阅该异常代码后我们知道程序读写了一个没有可读写属性的地址。

3CONTEXT结构

CONTEXT结构包含了特定处理器的寄存器数据,系统使用CONTEXT结构来执行各种内部操作。该结构可参考WinNt.h的定义,在X86平台下该结构定义为CONTEXT86,后面将直接用CONTEXT代指CONTEXT86。因为由于该结构比较长,出于篇幅考虑只列出来结构的部分成员:

Typedef struct _ CONTEXT86{

……

//通用寄存器

   +9C DWORD   Edi;

   +A0 DWORD   Esi;

   +A4   DWORD   Ebx;

   +A8   DWORD   Edx;

+AC   DWORD   Ecx;

   +B0   DWORD   Eax;

//控制寄存器

   +B4   DWORD   Ebp;

   +B8   DWORD   Eip;

   +BC DWORD   SegCs;             

   +C0   DWORD   EFlags;           

   +C4   DWORD   Esp;

   +C8   DWORD   SegSs;

   ……

} CONTEXT86;

CONTEXT结构非常重要,通过修改CONTEXT结构中的成员,可以使程序能够在异常时执行相应的处理工作,使程序能够继续执行。在Windows Xp系统中,系统调用NTDLL.DLL模块中的KiUserExceptionDIspatcher函数来执行异常处理。该函数最终将程序中注册的异常处理函数的地址装入ECX,然后调用执行。此时堆栈的分布情况如下:

Esp+0x0 -> *EXCEPTION_RECORD
Esp+0x4 -> *_EXCEPTION_REGISTRATION(
简称ERR)
Esp+0x8 -> *CONTEXT record
Esp+0xC -> *Param

如果注册的异常处理函数将CONTEXT结构中保存的EIP值修改到一个“安全的地方”,那么执行完异常处理函数后,程序将返回到“安全代码”中去执行。

下面的例子程序将在执行搜索内存的操作之前向异常处理链表中注册一个异常处理函数,用于在发生地址访问错误的时候修正程序的执行路径,修改EIP的值为发生访问违例(执行内存比较)的下一条指令地址。这样程序将能够安全、顺利地执行完搜索内存的操作。

为了弄清楚异常发生时系统的状态我们进行如下跟踪分析:

Ollydbg中打开程序Seh.exe,由于搜索的起始地址为0x200000将会导致一个访问异常。我们OllyDbg的命令窗口中输入bp 0x7C9237BD,在Windows Xp系统将要调用异常处理函数时断下来观察堆栈的状态(Windows 2000 中是 0x77F8E43E)。此时程序的状态如图三所示:


图三、KiUserExceptionDIspatcher函数调用异常处理时的堆栈状态

此时Esp的值为0x12FBF0,该地址指向EXCEPTION_RECORD结构,结构偏移为0x0处保存了异常代码0xC0000005,偏移为0xC处保存了异常发生的地址0x401017,该指令是我们执行模式匹配的指令scasdEsp+40x12FFBC)保存了指向下一个异常处理结构的指针。Esp+80x12FCF0)保存了指向CONTEXT结构的指针,该结构偏移为0xB8处保存了异常发生时EIP寄存器的值0x401017,偏移为0x9C处保存了Edi寄存器的值0x200000CONTEXT保存的各寄存器的状态可参见图四。


图四、异常发生时CONTEXT结构的状态

按下F7后执行预定义的异常处理函数。该函数将修正CONTEXT中保存的EIP的值为指令add    ebx, 01000h在内存中的地址(0x0040101C)。当程序恢复执行时,将从该指令继续执行内存空间的搜索操作。修改后的CONTEXT状态可参见图五。


图五、修正后CONTEXT结构的状态