I've been experimenting with assembly SEH for a while, but one thing I do not understand is why my code below doesn't execute the injected SEH but instead the default in ntdll.
I've got a simple ASM app name "one.exe" which doesn't implement any SEH by itself. I want to inject a SEH handler into this app so I can catch all necessary exceptions in a random code cave.
I thought this would be as easy as injecting the three-line SEH initializer, but when (purposely - mov ,1) causing an access violation exception, my exception handler isn't called. What did I do wrong?

Code injected into code-cave and called by "one.exe"
00401189 PUSH one.004011B0 ; se initializer
0040118E PUSH DWORD PTR FS:[0]
00401195 MOV DWORD PTR FS:[0],ESP
0040119C MOV EAX,0
004011A1 MOV BYTE PTR DS:,1 ; purposely cause exception to test
004011A4 RETN


Se-handler code also injected into "one.exe"
004011B0 PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL;
004011B2 PUSH 0                                   ; |Title = NULL
004011B4 PUSH One.004030BF                        ; |Text = "Exception caught!"
004011B9 PUSH DWORD PTR DS:[4030E8]               ; |hOwner = NULL
004011BF CALL user32.MessageBoxA                  ; \MessageBoxA
004011C4 RETN
Posted on 2008-08-09 13:02:08 by pn0k
I'd love to help you, as the problem is very obvious, however I'd like to hear your excuse for wanting to capture exceptions in a remote process before I do that, as it sounds to me a lot like you want to hook some SEH-based security / code obfuscation scheme (I'm thinking you wanna crack something).
Posted on 2008-08-10 20:05:08 by Homer

I'd love to help you, as the problem is very obvious, however I'd like to hear your excuse for wanting to capture exceptions in a remote process before I do that, as it sounds to me a lot like you want to hook some SEH-based security / code obfuscation scheme (I'm thinking you wanna crack something).


I can assure you I am not cracking anything. All I'm trying to do is to learn about SEH as close to the bone as possible. After all there is almost zero documentation on SEH beyond compiler specific variations - that is, no documentation on what happens behind the scenes. I've been reading some papers written by people who have reversed their own compiler-specific SEH apps (which is what I am doing as well) to get the info. But as I'm sure you know, nothing is as rewarding as discovering things yourself. "one.exe" is a simple ASM app that does nothing but display a window. I wrote it myself. I'm trying to replicate the code MASM compiler produces when utilizing SEH.

I'd really appreciate your help Homer, if you'd be so kind.
Posted on 2008-08-11 04:34:23 by pn0k
I don't think you should be pushing the address of the SEH function into FS:[0]

Take a look at Iczelion's PE Tutorial #2, which contains a simple exception handler...

You should be pushing the address of a structure that becomes linked into the SEH handler chain - its a linkedlist of 'record' structures. The structure is as follows (you can extend it)..


SEH struct
PrevLink dd ?    ; the address of the previous seh structure
CurrentHandler dd ?    ; the address of the exception handler
SafeOffset dd ?    ; The offset where it's safe to continue execution
PrevEsp dd ?      ; the old value in esp
PrevEbp dd ?     ; The old value in ebp
SEH ends



and Iczelion's example code to install the SEH is as follows:

             push fs:[0]
             pop seh.PrevLink
             mov seh.CurrentHandler,offset SEHHandler
             mov seh.SafeOffset,offset FinalExit
             lea eax,seh
             mov fs:[0], eax
             mov seh.PrevEsp,esp
             mov seh.PrevEbp,ebp

Why do all this? We do it so that RtlUnwind can walk the SEH record chain without falling over.
As you can see, the old SEH obtained from FS:[0] is stored in there before we point FS:[0] at the structure itself, creating the linkedlist I mentioned.. we also stow ebp and esp so they can be restored if/when the SEH is triggered, since we want those back at the very least.

In his example, the main SEH handler is:

SEHHandler proc C uses edx pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
    mov edx,pFrame
    assume edx:ptr SEH
    mov eax,pContext
    assume eax:ptr CONTEXT
    push .SafeOffset
    pop .regEip
    push .PrevEsp
    pop .regEsp
    push .PrevEbp
    pop .regEbp
    mov ValidPE, FALSE
    mov eax,ExceptionContinueExecution
    ret
SEHHandler endp

You can see there that when the exception occurs, we are passed a cpu CONTEXT structure, as well as the pointer to the SEH record where we safely stowed some registers earlier... here's our chance to restore those registers to nice safe values, and then we are returning the constant 'ExceptionContinueExecution' (I think its NULL) which will let the cpu continue (using the values we just forced apon it) - notice that EIP now points to a label called 'FinalExit'.. lets see that code.

FinalExit:
(...some junk I cut)...
             push seh.PrevLink
             pop fs:[0]
(..more junk..)
             ret

We didn't really need to point EIP here, but in that example we had nothing better to do than leave the program, and before we do that, we better restore the SEH chain to normal.
I would suggest that your code would be at the FinalExit label, since you're not planning on doing much once your messagebox has fired...
Posted on 2008-08-11 06:15:06 by Homer

I don't think you should be pushing the address of the SEH function into FS:[0]


Are you sure about that? All the articles I've been reading consistently provide examples following the below code (and also the code I used in my example in the original post). http://www.microsoft.com/msj/0197/exception/exception.aspx describes very well how it all works.
According to http://win32assembly.online.fr/Exceptionhandling.html we need to push an ERR structure (at least: DWORD Pointer-to next-ERR-structure, DWORD Pointer-to-own-exception-handler"). By utilizing the two push and one mov instructions we are creating this struct on the stack and sending it to the thread information block.
The ERR struct contains a pointer to the next (previous) ERR struct, and therefore the system is able to walk the handler chain as you describe.

Example taken directly from http://win32assembly.online.fr/Exceptionhandling.html
Establishing a "per-thread" exception handler
So now we can see how easy it is to establish this type of exception handler:-

Example
PUSH OFFSET HANDLER
PUSH FS:[0] ;address of next ERR structure
MOV FS:[0],ESP ;give FS:[0] the ERR address just made
...
...
...
POP FS:[0] ;restore next ERR structure to FS:[0]
ADD ESP,4h ;throw away rest of ERR structure
RET
;***********************
HANDLER:
...
... ;exception handler code goes here
...
MOV EAX,1 ;eax=1 go to next handler
RET ; ;eax=0 reload context & continue execution
Posted on 2008-08-11 08:41:35 by pn0k
OK, I see that, yes it should be ok.
Tell me, which process owns the memory that those strings are stored in?
Could it be that your SEH is actually firing - but then MessageBox is attempting to access illegal addresses (the strings) and causing the final exception handler to be invoked (in order to prevent a nested exception) ?

Posted on 2008-08-11 09:42:38 by Homer

Tell me, which process owns the memory that those strings are stored in?
Could it be that your SEH is actually firing - but then MessageBox is attempting to access illegal addresses (the strings) and causing the final exception handler to be invoked (in order to prevent a nested exception) ?


The strings are all stored in the current process "one.exe".
I am certain that not even the push instructions in the SE handler are executed because the SE handler is never called. To verify this I launched Olly, put a breakpoint on the first push instruction, when the program reached the faulty line (mov byte ptr ,1) it rose an exception as it should, I told Olly to pass it to the program, then pressed f9 to run the program where Olly paused it and the breakpoint in the custom SE handler was never reached. Darn I just can't find the bug here :/

Posted on 2008-08-11 10:49:56 by pn0k
Why not start by doing SEHs in one process and getting that to work? :)

Can't think of much use of SEH injection in other processes, tbh... well, perhaps for tracing, which can have legitimate purposes, but is definitely a bit shady.
Posted on 2008-08-11 11:22:51 by f0dder
Well what do you know. It turned out after all that the code above wasn't the culprit, it was Olly. Somehow Olly wasn't working right - perhaps wise not to have +200 plugins installed - it didn't break or modify the code properly so I tried with a fresh copy and my handler was called.
So to sum it up the above code works perfectly fine.

BTW: I do know how to get SEH to work in a single process;)
Posted on 2008-08-12 00:55:33 by pn0k
Olly is NOT a good debugger, and particularly so where SEH are concerned.
I suggest you put Olly on the back shelf, its still useful for certain things, however I would suggest switching to IDA (pro, 5+) and/or the debugger from Visual Studio (I don't code C but I have recently been using that debugger, and it's not too bad).

I am using IDA to poke around in other peoples stuff, and the VS debugger for my development work.
Both are quite capable, although their GUIs are a lot different to Olly, and take getting used to.
Posted on 2008-08-12 02:36:49 by Homer
IMHO Olly is a good enough debugger for the simpler stuff. It does have it's issues here and there, but I wouldn't say it's a bad debugger. I find IDAs debugger somewhat clunky to work with, but it does have the advantage of being integrated with probably the world's best x86 disassembler :)

I tend to use Olly when I need a quick look at some assembly code (dealing with small asm apps of my own, just-in-time attaching to a crashed program, etc.), IDA when I need to mess with other people's code (rarely use the debugger though), and Visual Studio for high-level debuggin... VS isn't all that hot for asm debugging, but it has a lot of nice features for HLL debugging.
Posted on 2008-08-12 05:12:22 by f0dder
I've only been using the VS debugger since Biterider has been implementing some support for it within OA32 - I'm able to see my actual sourcecode and exactly which line caused a problem, just like I was coding in a HLL.
Posted on 2008-08-12 06:03:23 by Homer