Jump to content
Tuts 4 You
Sign in to follow this  
LCF-AT

Exception Handler - Log - Question

Rate this topic

Recommended Posts

LCF-AT

Hi guys,

today I would like to ask how to implement a 100% working handler to log exception.So in the past I tried already to do this and its also working so far but I think its not working always so that the reason why I do ask to know how to do it correctly.So the main basic way I choosed is only using SetUnhandledExceptionFilter API with address to my Handler routine to read exception infos / log them / MessageBox them.

invoke SetUnhandledExceptionFilter,offset HANDLER_SEH2

HANDLER_SEH2 proc

log code etc

invoke MessageBox,NULL, BUFFIS,chr$("Exception Info!"),MB_ICONINFORMATION  
mov eax, 1h
ret

As result I get this so far (mostly)...

30.08.2017 21:00:40

Exception: C0000005

regEax 00000000
regEcx 00000000
regEdx 00000022
regEbx 00000000
regEsp 0012FAE0
regEbp 0012FAE0
regEsi 00000111
regEdi 0012FB5C
regEip 004010A2

BaseAddress:    00401000
AllocationBase: 00400000

Exception occurs into module bones.exe

-----------EXECPTION-----------
004010A2   MOV DWORD PTR [EAX] , EAX
-------------------------------
004010A4   MOV EAX , 00000000H
004010A9   LEAVE 
004010AA   RETN 0010H
004010AD   JMP 00401114H
004010AF   CMP DWORD PTR [EBP+0CH] , 05H
004010B3   JNE 004010C0H
004010B5   MOV EAX , 00000000H
004010BA   LEAVE 
004010BB   RETN 0010H
004010BE   JMP 00401114H
004010C0   CMP DWORD PTR [EBP+0CH] , 4EH
004010C4   JNE 004010C8H
004010C6   JMP 00401114H
004010C8   CMP DWORD PTR [EBP+0CH] , 00000138H
004010CF   JNE 004010D7H
004010D1   LEAVE 
004010D2   RETN 0010H
004010D5   JMP 00401114H
004010D7   CMP DWORD PTR [EBP+0CH] , 7BH

...using DISAM lib to read commands and log them  etc.But the problem is that its not working always and I am not sure why.Sometimes I dont get the messagebox at the end of my routine what makes me think that my handler routine wasnt called after the exception happend.So I wanna  be just sure that it will always access my Handler routine if any exception occurs to log / show it.You know,similar as windows does to show a error MSG & infos.I am not sure whether using SetUnhandledExceptionFilter one time with my Handler routine is enough or not or whether it could be disabled by anything etc.Maybe you have some ideas how to do it right or example/s.

Thank you

Share this post


Link to post
Share on other sites
atom0s

If anything else calls SetUnhandledExceptionFilter after you have placed yours, it will override your exception handling. If that is the case, what you can do is hook SetUnhandledExceptionFilter and block any future calls to it after you have personally placed your own filter. 

Another exception method to look into is: AddVectoredExceptionHandler

  • Like 1

Share this post


Link to post
Share on other sites
VirtualPuppet

SutUnhandledExceptionFilter will only catch uncatched exceptions. If a previous exception-handler catches and exception and "handles" it (even if wrongly), it will not reach your handler (even if it might turn out to crash the application). If you use AddVectoredExceptionHandler instead, you will catch all exceptions (even if a handler is actively waiting for them) and can atleast log the trace-data, and return a value indicating that the exception-handler frame should search for a new handler.

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi again,

ok so you guys mean I should better use AddVectoredExceptionHandler.So just be sure again,so I dont wanna handle any exception with my code and will only log them if any does occur so thats all.At the end it should work go on with the original way etc you know.Also in that case I have another question.If I set a handler and it gets triggerd should I then remove it in my handler routine?If yes,what is if the exception gets successfully handled and later comes another exception so then it will no more access my Handler routine anymore.Just asking because I want to prevent any loops if no handlers are present etc.

	invoke AddVectoredExceptionHandler,TRUE,offset HANDLER_SEH2
	mov HANDLER,eax
	int 3h  <--- test exception
                 
HANDLER_SEH2 proc..
......                 
invoke RemoveVectoredExceptionHandler,HANDLER  <----
invoke MessageBox,NULL, BUFFIS,chr$("Exception Info!"),MB_ICONINFORMATION  
mov eax, EXCEPTION_CONTINUE_EXECUTION <----
ret  
HANDLER_SEH2 endp

Or should I just use EXCEPTION_CONTINUE_SEARCH at the end without to remove the Handler handle?Would be that ok?As I said I just wanna log / MSG it thats all.

PS: But what is if I procduce a exception in my Handler routine itself?Just asking if that could happen anyhow etc you know.

greetz

Share this post


Link to post
Share on other sites
VirtualPuppet
6 minutes ago, LCF-AT said:

Hi again,

ok so you guys mean I should better use AddVectoredExceptionHandler.So just be sure again,so I dont wanna handle any exception with my code and will only log them if any does occur so thats all.At the end it should work go on with the original way etc you know.Also in that case I have another question.If I set a handler and it gets triggerd should I then remove it in my handler routine?If yes,what is if the exception gets successfully handled and later comes another exception so then it will no more access my Handler routine anymore.Just asking because I want to prevent any loops if no handlers are present etc.


	invoke AddVectoredExceptionHandler,TRUE,offset HANDLER_SEH2
	mov HANDLER,eax
	int 3h  <--- test exception
                 
HANDLER_SEH2 proc..
......                 
invoke RemoveVectoredExceptionHandler,HANDLER  <----
invoke MessageBox,NULL, BUFFIS,chr$("Exception Info!"),MB_ICONINFORMATION  
mov eax, EXCEPTION_CONTINUE_EXECUTION <----
ret  
HANDLER_SEH2 endp

Or should I just use EXCEPTION_CONTINUE_SEARCH at the end without to remove the Handler handle?Would be that ok?As I said I just wanna log / MSG it thats all.

PS: But what is if I procduce a exception in my Handler routine itself?Just asking if that could happen anyhow etc you know.

greetz

Basically, AddVectoredExceptionHandler adds to the top of the chain, so it is the first to be called (will get called by _all_ exceptions, even those that gets handled, so it is perfect for logging).

You shouldn't perform code that can have exceptions inside an exception-handler, but if it does happen, you will just have a new exception raised, and if it's a repeated exception in the exception-handler, you'll enter an infinite loop :P 

And no, do not return EXCEPTION_CONTINUE_EXECUTION. It means you've handled the exception. You want to return EXCEPTION_CONTINUE_SEARCH, which means "I did not handle the exceptin, please keep searching in the chain."

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

yes I want to prevent such possible INI Loops if something was going wrong in my Handler log code etc. :) Good ok,so I could add a marker at the top of my Handler routine which I can reset at the end = Handler routine successfully passed = EXCEPTION_CONTINUE_SEARCH return or RemoveVectoredExceptionHandler and EXCEPTION_EXECUTE_HANDLER return or maybe just RemoveVectoredExceptionHandler & EXCEPTION_CONTINUE_SEARCH should also work to not come back to my Handler anymore.I will test a little around.

greetz

Share this post


Link to post
Share on other sites
VirtualPuppet
1 hour ago, LCF-AT said:

Hi,

yes I want to prevent such possible INI Loops if something was going wrong in my Handler log code etc. :) Good ok,so I could add a marker at the top of my Handler routine which I can reset at the end = Handler routine successfully passed = EXCEPTION_CONTINUE_SEARCH return or RemoveVectoredExceptionHandler and EXCEPTION_EXECUTE_HANDLER return or maybe just RemoveVectoredExceptionHandler & EXCEPTION_CONTINUE_SEARCH should also work to not come back to my Handler anymore.I will test a little around.

greetz

You shouldn't remove it. Just leave the handler there statically, and log exceptions through it :)

Edited by VirtualPuppet (see edit history)
  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi again,

so there is a problem with that infinite loop inside my Handler.So if there happens a exception because of any reason then my Handler routine gets called again / again etc without to stop = loop I wanted to prevent.Also if I just remove the Handler handle via RemoveVectoredExceptionHandler API right at the top. :(

invoke RemoveVectoredExceptionHandler,HANDLER  ; 1 call in my routine
.....
int 3h  ; setting exception at the end for testing
.....
mov eax,EXCEPTION_CONTINUE_SEARCH
ret

In this case the exception happens inside my exception log routine and then I come back again at the top of my routine also if I used the remove API = INFI LOOP for ever.So whats the right way now to prevent such INFI Loops in that case?Seems to be  a little tricky or?

greetz

Share this post


Link to post
Share on other sites
VirtualPuppet
1 hour ago, LCF-AT said:

Hi again,

so there is a problem with that infinite loop inside my Handler.So if there happens a exception because of any reason then my Handler routine gets called again / again etc without to stop = loop I wanted to prevent.Also if I just remove the Handler handle via RemoveVectoredExceptionHandler API right at the top. :(


invoke RemoveVectoredExceptionHandler,HANDLER  ; 1 call in my routine
.....
int 3h  ; setting exception at the end for testing
.....
mov eax,EXCEPTION_CONTINUE_SEARCH
ret

In this case the exception happens inside my exception log routine and then I come back again at the top of my routine also if I used the remove API = INFI LOOP for ever.So whats the right way now to prevent such INFI Loops in that case?Seems to be  a little tricky or?

greetz

You're not supposed to generate exceptions in a handler, so it's not supported by the Windows API.

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

so thats why I am asking for it what to do in a case if happens a excetpion in my handler log routine who should log exceptions.If that happens then = INFI Loop for ever and need to exit the app from outside.

greetz

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

I have another problem using a messagebox in my handler routine to show exception infos.So if I use diffrent threads and timers them my Handler proc + messagebox gets called also in a loop and then I have many same messageboxes open etc.So what to do in that case?Is there anything to stop entire app process so long the messagebox is shown etc?So at the moment I have disabled a MSG.

greetz

Share this post


Link to post
Share on other sites
evlncrn8

put a spinlock in the handler at the start, that'll do the job

theres also addvectoredcontinuehandler which might be of intrest

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi evlncrn8,

listen,could you maybe just post any example?Just need to know the important set APIs & what to set for APIs / lock in my Handler routine proc etc I could test later.Just wanna prevent that self accessing loops and prevent calling tons of same MSG boxes if the app works in the background with other threads etc you know.

Handler proc

Pause All work in app API/s suspend threads etc

Here my Log stuf / if exception happens here = dont call Handler proc again etc

MSG Infos / user get MSG to see so long till Ok was pressed

At the end xy / resume etc not sure yet

Continue / ret

Do you have something / code etc where I can have a look at?Just would like to know this parts correctly for 100 %.

Thanks

Share this post


Link to post
Share on other sites
evlncrn8

knocked this up for you quickly.. to do it as x64 its pretty much the same, just some register alteration.. which im sure you can do yourself

the idea is in the exception handler

exception handler start -> set spinlock -> do stuff

at the return from the exception handler make sure to unset the spinlock before returning otherwise you'll go into an infinite loop

in the exception handler, after the spinlock do your logging / logic etc..

 


.data?

global_exception_spinlock BYTE ? ; make sure its in uninitialized data


.code

; set spinlock

push TRUE
push FALSE
push offset global_exception_spinlock
call ASM_SpinLock

; do stuff.. all other threads causing exceptions will be 'trapped' in the spinlock, with the pause opcode the cpu usage is minimal

; reset spinlock

push FALSE
push TRUE
push offset global_exception_spinlock
call ASM_SpinLock

==========

ASM_SpinLock proc uses eax ebx ecx, addressofspinlock:LPVOID, value1:BYTE, value2:BYTE

  cmp   [addressofspinlock], (NULL)
  je    outoffunction

  movzx eax, [value1]
  movzx ebx, [value2]

  mov   ecx, [addressofspinlock]

dospinlockwaitbyte:

  lock  cmpxchg BYTE PTR [ecx], bl

optimisedcinditionalspinlockokorspinlockwaiter:

  jz    spinlockok

spinlockwaiter:

  db    0f3h, 090h      ; repz nop (pause)
  movzx eax, [value1]    ; this line might be redundant
  
  jmp   dospinlockwaitbyte

spinlockok:

outoffunction:

  ret

ASM_SpinLock endp
 

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi again,

thanks for the example.Ok I see what you mean.If somewhere else a exception raised then it hangs inside so long till it was reset.Good idea so far.I have test it a little and get also some trouble.If I force a exception then its showing the MSG box with infos I made.In the background are sill running other threads.So if I now set mem BP on my app then it stops on the running thread and if now force another exception then its also jumping to my handler in your SpinLock where it loops inside but now I the app hangs and I cant move the MSG box or press Ok button it etc.Not happens always so / sometimes its working to show MSG by  MSG.Maybe it has something to do that I test it in debugger itself.Not sure so far whether I could trust this method for 100 % you know.Maybe its really no good idea to use a MSG box and maybe I should just log datas to file only.

PS: So I think on this forum are many coder people who building apps and using surely also something like that to log exception / error logs etc.So did nobody build something like this by itself or are there just ready codes you can just add without to take care about it anymore?Just asking of course.For MASM I didnt found anything like that yet.

greetz

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

one more short question.Could anyone tell whether it was possible to get the exception name by exception code?Dont remember anymore how it was working to get the names.

greetz

Share this post


Link to post
Share on other sites
evlncrn8

      if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) exceptioninfo->ExceptionRecord->ExceptionCode, (SUBLANG_DEFAULT << 10), (LPSTR) &errorcodemessagebuffer, (sizeof(errorcodemessagebuffer)), NULL))

 

small snippet from what i use.. in the example you allocate the buffer and size yourself.. otherwise you have localfree overheads and shit... that code should be relatively easy to port to asm...
 

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

so FormatMessage I cant use to get the string of any exception code.Also I dont wanna code a bunch of exception value with names extra to add it in my code and make a compare to find the right exception name for exception code etc you know.

@evlncrn8

I tried it but dosent work to get anything....

0012FF6C   00401022  /CALL to FormatMessageA from bones.0040101D
0012FF70   00001200  |Flags = IGNORE_INSERTS|FROM_SYSTEM|0x0
0012FF74   00000000  |pSource = NULL
0012FF78   C0000005  |MessageId = 0xC0000005
0012FF7C   00000001  |LanguageId = 0x1 (LANG_ARABIC)
0012FF80   00438519  |Buffer = bones.00438519
0012FF84   00000100  |BufSize = 100 (256.)
0012FF88   00000000  \Arguments = NULL

LastErr 00003B01
0012FF6C   00401022  /CALL to FormatMessageA from bones.0040101D
0012FF70   00001200  |Flags = IGNORE_INSERTS|FROM_SYSTEM|0x0
0012FF74   00000000  |pSource = NULL
0012FF78   C0000005  |MessageId = 0xC0000005
0012FF7C   00000000  |LanguageId = 0x0 (LANG_NEUTRAL)
0012FF80   00438519  |Buffer = bones.00438519
0012FF84   00000100  |BufSize = 100 (256.)
0012FF88   00000000  \Arguments = NULL

ERROR_MR_MID_NOT_FOUND (0000013D)

Other question: So I found on my HDD a file called ntstatus.inc.Inside of the inc file I can see all exception equ values and names too.Now I can add it into my MASM project but how to make a compare without to compare?

STATUS_WAIT_1                    equ 00000001
STATUS_WAIT_2                    equ 00000002
.....
; MessageId: STATUS_ACCESS_VIOLATION
;
; MessageText:
;
;  The instruction at "0x%08lx" referenced memory at "0x%08lx". The memory could not be "%s".
;
STATUS_ACCESS_VIOLATION          equ 0C0000005h    ; winnt
....etc

As I said I only have the exception codes but how to get the name of it with that file above?There is also lib but this I cant use = not for MASM only this inc file.Can I do something with that maybe?

greetz

Share this post


Link to post
Share on other sites
atom0s
3 hours ago, evlncrn8 said:

      if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) exceptioninfo->ExceptionRecord->ExceptionCode, (SUBLANG_DEFAULT << 10), (LPSTR) &errorcodemessagebuffer, (sizeof(errorcodemessagebuffer)), NULL))

 

small snippet from what i use.. in the example you allocate the buffer and size yourself.. otherwise you have localfree overheads and shit... that code should be relatively easy to port to asm...
 

FormatMessage wont work on actual exceptions from the system, for example access violations. (0xC0000005) With your code the call will fail with another error 0x13D as it is not meant to handle exception codes. The best bet method is to create a lookup table that includes exceptions you know can happen with your application and add more as you go or as they happen. There are some public lists of full exception ids and names along with some in the various Windows SDK headers offered by Microsoft to get started.

In the plugin SDK for one of my projects, I have a simple C++ wrapper around a handful of known exceptions to convert them to strings, which can be seen here:

http://git.ashita.atom0s.com/Ashita/Ashitav3-Release/src/master/plugins/ADK/AS_Exception.h

This uses some preprocessor magic / macros to turn the raw codes into strings for the purpose of my project.

  • Like 1

Share this post


Link to post
Share on other sites
LCF-AT

Hi,

so what about the compare / set exception string names?Lets say I only check for 10 diffrent exception then I also need to write the exception names extra to output them.So in windows.inc file are already a few exceptions listet...

STATUS_BREAKPOINT         equ 80000003h
STATUS_SINGLE_STEP        equ 80000004h
STATUS_ACCESS_VIOLATION   equ 0C0000005h
....

...now I can check exception code for STATUS_ACCESS_VIOLATION for example....ok but to output the name I have to write also STATUS_ACCESS_VIOLATION another time etc you know what I mean right.So all in all I have to write a wolf if I wanna add all exception names.Thats just bad.I think somehow it should be work else anyhow.What about Olly or x32 Debugger?Did they also add all that manually?

My exception log looks so now at the moment....

09.09.2017 00:34:24

Exception: 80000003

regEax 00000001
regEcx 0012FA88
regEdx 77676C74
regEbx 00000000
regEsp 0012FAD8
regEbp 0012FAE0
regEsi 00000111
regEdi 75FEDB13
regEip 75FEDB13 Exception Address

D:\WinAsm\Exception Test\bones.exe
BaseAddress:    00401000
AllocationBase: 00400000

BaseAddress:    75FED000
AllocationBase: 75FA0000

Exception occurs into module: kernel32.dll
API address and name at or before Exception: 75FEDB13 GetModuleHandleA

Stack: 75FEDB13
------------------------------
00000000 | 0012FAD8 | 0040110D bones.exe
00000004 | 0012FADC | 00000000 
00000008 | 0012FAE0 | 0012FB0C 
0000000C | 0012FAE4 | 7616C4B7 user32.dll
00000010 | 0012FAE8 | 004E03C0 
00000014 | 0012FAEC | 00000111 
00000018 | 0012FAF0 | 000003EB 
......

75FEDB13   INT3 
75FEDB14   INT3 
75FEDB15   INT3 
75FEDB16   INT3 
75FEDB17   IN AL , DX
75FEDB18   POP EBP
75FEDB19   JMP 75FEDB08H
75FEDB1B   NOP 
75FEDB1C   NOP 
75FEDB1D   NOP 

....I think that should be enough infos I need to know so far.

greetz

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...