Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structured Exception Handler and Delphi

I am trying to set SEH without using try except
(This is for my own personal knowledge to get a better idea on how SEH works)

The following code doesn't work

type
    TSeh = packed record
    OldSeh:DWORD;
    NewSeh:DWORD;
    end;


procedure test;
begin
WriteLn('Hello from seh');
end;


var
    eu:TSeh;
    old_seh:DWORD;
begin
    asm
    mov eax,fs:[0]
    mov old_seh,eax
    end;
    eu.OldSeh := old_seh;
    eu.NewSeh := DWORD(@test);
    asm
        mov eax,offset eu
        mov fs:[0],eax
        ret //This will cause an exception because jumps on an invalid memory address
    end;
end.

But this does

procedure test;
begin
WriteLn('Hello from seh');
end;



begin
    asm
    push offset test
    push fs:[0]
    mov fs:[0],esp
    ret //This will cause an exception because jumps on an invalid memory address
    end;
end.

What am I doing wrong? What is the difference between the first code and the second one?

like image 682
opc0de Avatar asked Aug 09 '11 09:08

opc0de


People also ask

What is structured exception handler?

Structured exception handling (SEH) is a Microsoft extension to C and C++ to handle certain exceptional code situations, such as hardware faults, gracefully. Although Windows and Microsoft C++ support SEH, we recommend that you use ISO-standard C++ exception handling in C++ code.

What is the key feature of structured exception handling?

Structured exception handling enables you to have complete control over the handling of exceptions, provides support for debuggers, and is usable across all programming languages and machines. Vectored exception handling is an extension to structured exception handling.

What does an exception handler do?

An exception handler is code that stipulates what a program will do when an anomalous event disrupts the normal flow of that program's instructions. An exception, in a computer context, is an unplanned event that occurs while a program is executing and disrupts the flow of its instructions.

What is exception data structure?

In programming language mechanisms for exception handling, the term exception is typically used in a specific sense to denote a data structure storing information about an exceptional condition. One mechanism to transfer control, or raise an exception, is known as a throw. The exception is said to be thrown.


3 Answers

Windows requires all stack frames to be inside the stack allocated by the system. It also requires the stack frames to be in sequential order on the stack. Furthermore, for exception handling, it requires all 'exception records' to be on the stack, and for them to chain in a sequential order through stack memory.

I figured this out/read this somewhere years ago while writing a micro-thread library (http://www.eternallines.com/microthreads).

like image 87
David Butler Avatar answered Oct 01 '22 02:10

David Butler


You can't use test procedure as exception callback function because exception callback function have different prototype. Read Matt Pietrek article, IMO the best source of information about Win32 SEH.


Update

For the further investigations I would recommend the following changes in the code to make the problem a bit more clean:

function test: Integer;
begin
  WriteLn('Hello from seh');
  Result:= 0;
end;

(because exception callback should return integer value in EAX)

And for the first code snippet

begin
    asm
        mov eax,fs:[0]
        mov old_seh,eax
    end;
    eu.OldSeh := old_seh;
    eu.NewSeh := Cardinal(@test);
    asm
        lea eax, eu
        mov fs:[0],eax
        mov ds:[0],eax //This will cause an AV exception
    end;
end.

Now you see that the exception is handled correctly as:

---------------------------
Debugger Fault Notification
---------------------------
Project C:\Users\Serg\Documents\RAD Studio\Projects\Project13.exe faulted with
message: 'access violation at 0x004050f5: write of address 0x00000000'. Process
Stopped. Use Step or Run to continue.
---------------------------

but not by your exception handler. Probably OS ignores exception registration records that are not stack-based (OS can easily do it because it knows minimum and maximum stack values)

like image 28
kludg Avatar answered Oct 01 '22 02:10

kludg


For the first code, the TSeh is on the DATA global section of the executable, whereas the 2nd code stores it on the Stack.

This is IMHO where the difference is. The _EXCEPTION_REGISTRATION_RECORD structure should probably be on stack. Don't know why, honestly (some low-level SS register trick?).

To raise an exception, you should better try something like a division per zero or an access to a nil absolute address:

PInteger(nil)^ := 0; // will always raise an exception

asm
  xor eax,eax
  mov [eax],eax // will always raise an exception
end;

About how to intercept exceptions in Delphi, take a look at this article. In fact, Delphi add some custom layer over SEH over Windows.

And note also that the exception handling changes in Win64 mode. Worth reading when moving to up to come Delphi XE2.

like image 34
Arnaud Bouchez Avatar answered Oct 01 '22 02:10

Arnaud Bouchez