Win32 Structured anomaly Handling (SEH) (the following)

Source: Internet
Author: User

Expand

Let's first figure out what it means before digging through the unwinding implementation code. I've already talked about how all possible exception handlers are organized in a list that is pointed to by the first DWORD (fs:[0] of the thread information block. Because a handler for a particular exception may not be at the beginning of the list, you need to remove all exception handlers from the list, in turn, before the exception handler that actually handles the exception.

As you can see in the __except_handler3 function of Visual C + +, the expansion is done by __global_unwind2 this run-time library (RTL) function. This function is simply encapsulation of the Rtlunwind API. (now that the API has been made public, the information given is extremely simple and the details refer to the latest Platform SDK documentation.) )

__global_unwind2(void * pRegistFrame)
{

_RtlUnwind( pRegistFrame, &__ret_label, 0, 0 );
__ret_label:
}

Although technically rtlunwind is a KERNEL32 function, it is only forwarded to a function of the same name in NTDLL.DLL. Here is the pseudocode I wrote for this function.

Pseudo code for the Rtlunwind function:

void _rtlunwind (Pexception_registration pregistrationframe,

PVOID returnaddr,//Not used! (at least on the i386 machine)

Pexception_record Pexcptrec,

DWORD _eax_value)
{

DWORD stackuserbase;

DWORD Stackusertop;

Pexception_record Pexcptrec;

Exception_record Exceptrec;

Context context;

Get the bounds of the stack from fs:[4] and fs:[8]

Rtlpgetstacklimits (&stackuserbase, &stackusertop);

if (0 = pexcptrec)//Normal condition

{

Pexcptrec = &excptRec;

pexcptrec->exceptionflags = 0;

Pexcptrec->exceptioncode = Status_unwind;

Pexcptrec->exceptionrecord = 0;

Pexcptrec->exceptionaddress = [Ebp+4]; Rtlpgetreturnaddress ()-Get return address

Pexcptrec->exceptioninformation[0] = 0;

}

if (pregistrationframe)

Pexcptrec->exceptionflags |= exception_unwinding;

else//These two logos together are defined as Exception_unwind_context

Pexcptrec->exceptionflags|= (exception_unwinding| Exception_exit_unwind);

Context. Contextflags = (context_i486 | Context_control |

Context_integer | context_segments);

Rtlpcapturecontext (&context);

Context. ESP + 0x10;

Context. Eax = _eax_value;

Pexception_registration Pexcptreghead;

Pexcptreghead = Rtlpgetregistrationhead (); Returns the value of Fs:[0]

Start traversing the exception_registration structure linked list

while (-1!= pexcptreghead)

{

Exception_record excptRec2;

if (Pexcptreghead = = pregistrationframe)

{


Ntcontinue (&context, 0);

}

Else

{


If an exception frame is positioned on the stack, it is lower than the header of the list of exceptions


There must be an error.


if (Pregistrationframe && (pregistrationframe <= pexcptreghead))


{


Generate an exception


Excptrec2.exceptionrecord = Pexcptrec;


excptrec2.numberparameters = 0;


Excptrec2.exceptioncode = Status_invalid_unwind_target;


Excptrec2.exceptionflags = exception_noncontinuable;


Rtlraiseexception (&AMP;EXCEPTREC2);


}

}

PVOID Pstack = Pexcptreghead + 8; 8 = sizeof (exception_registration)

Make sure the Pexcptreghead is in the stack range and is a multiple of 4

if ((Stackuserbase <= pexcptreghead)


&& (stackusertop >= pstack)


&& (0 = = (Pexcptreghead & 3))

{


DWORD Pnewregisthead;


DWORD RetValue;


RetValue = Rtlpexecutehandlerforunwind (Pexcptrec, Pexcptreghead, &context,


&pnewregisthead, Pexceptreghead->handler);


if (RetValue!= disposition_continue_search)


{


if (RetValue!= disposition_collided_unwind)


{



Excptrec2.exceptionrecord = Pexcptrec;



excptrec2.numberparameters = 0;



Excptrec2.exceptioncode = status_invalid_disposition;



Excptrec2.exceptionflags = exception_noncontinuable;



Rtlraiseexception (&AMP;EXCPTREC2);


}


Else



Pexcptreghead = Pnewregisthead;


}


Pexception_registration Pcurrexcptreg = Pexcptreghead;


Pexcptreghead = pexcptreghead->prev;


Rtlpunlinkhandler (Pcurrexcptreg);

}

else//stack has been corrupted! Generate an exception

{


Excptrec2.exceptionrecord = Pexcptrec;


excptrec2.numberparameters = 0;


Excptrec2.exceptioncode = Status_bad_stack;


Excptrec2.exceptionflags = exception_noncontinuable;


Rtlraiseexception (&AMP;EXCPTREC2);

}

}

If executed here, the description has arrived exception_registration

The end of the structure list, this should not normally happen.

(because exceptions should normally be processed so that they do not go to the end of the list)

if (-1 = pregistrationframe)

Ntcontinue (&context, 0);

Else

Ntraiseexception (Pexcptrec, &context, 0);
}

The pseudocode for the Rtlunwind function ends here, and the following is the pseudocode of several functions it calls:

Pexception_registration rtlpgetregistrationhead (void)
{

return fs:[0];
}
Rtlpunlinkhandler (pexception_registration pregistrationframe)
{

Fs:[0] = pregistrationframe->prev;
}
void Rtlpcapturecontext (Context * pContext)
{

Pcontext->eax = 0;

PCONTEXT-&GT;ECX = 0;

Pcontext->edx = 0;

PCONTEXT-&GT;EBX = 0;

Pcontext->esi = 0;

Pcontext->edi = 0;

Pcontext->segcs = CS;

Pcontext->segds = DS;

Pcontext->seges = ES;

Pcontext->segfs = FS;

Pcontext->seggs = GS;

PCONTEXT-&GT;SEGSS = SS;

Pcontext->eflags = flags; It corresponds to the assembly code for __asm{Pushfd/pop [xxxxxxxx]}

PCONTEXT-&GT;EIP = return address of caller of this function//reader look at this function's

PCONTEXT-&GT;EBP = EBP//assembler Code of the caller of this function will know this

PCONTEXT-&GT;ESP = PCONTEXT-&GT;EBP + 8;
}

Although the size of the Rtlunwind function looks large, it is not difficult to understand if you separate it in a certain way. It first obtains the bounds of the current thread stack from fs:[4] and fs:[8. They are important to the subsequent legality checks to make sure that all the exception frames that will be expanded are in the stack range.

Rtlunwind then creates an empty Exception_record structure on the stack and assigns the status_unwind to its Exceptioncode domain, and assigns the exception_unwinding flag to its ExceptionFlags domain. A pointer to this structure is passed to each exception callback function as one of the parameters. The function then calls the Rtlcapturecontext function to create an empty context structure, which also becomes a parameter passed to each exception callback function when it is invoked during the unwind phase.

The remainder of the Rtlunwind function traverses the exception_registration structure list. For each of these frames, it calls the Rtlpexecutehandlerforunwind function, which I'll talk about later. It was this function that called the exception-handling callback function with the exception_unwinding flag. After each callback, it calls Rtlpunlinkhandler to remove the corresponding exception frame.

The first argument to the Rtlunwind function is the address of a frame that stops expanding the exception frame when it traverses the frame. There are also security check codes between these codes that are used to ensure that there is no problem. If any problems occur, Rtlunwind throws an exception indicating what the problem is, and the exception has a exception_noncontinuable flag. When a process is set to this flag, it is not allowed to run and must terminate.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.