News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

SEH skip tables

Started by Vektor, December 11, 2007, 11:08:12 AM

Previous topic - Next topic

Vektor

I needed for my server project a SEH procedure that skips the instruction that caused the exception so i thought that using 2 tables to parse the machine code would do that job.
In these tables, at each position is the number of bytes the corresponding machine code has. First table is for all opcodes, second is for opcodes that start with 0F.
Also:
  • -1 = mod R/M is present
  • -2 = 0F, second table is used
  • -3 = mod R/M + immediate 32bit value
  • -4 = mod R/M + immediate 8bit value
For those who need them, here they are:
opc_table:
db -1 ;00
db -1 ;01
db -1 ;02
db -1 ;03
db -1 ;04
db 5 ;05
db 1 ;06
db 1 ;07
db -1 ;08
db -1 ;09
db -1 ;0a
db -1 ;0b
db -1 ;0c
db 5 ;0d
db 1 ;0e
db -2 ;0f
db -1 ;10
db -1 ;11
db -1 ;12
db -1 ;13
db -1 ;14
db 5 ;15
db 1 ;16
db 1 ;17
db -1 ;18
db -1 ;19
db -1 ;1a
db -1 ;1b
db -1 ;1c
db 5 ;1d
db 1 ;1e
db 1 ;1f
db -1 ;20
db -1 ;21
db -1 ;22
db -1 ;23
db -1 ;24
db 5 ;25
db 1 ;26
db 1 ;27
db -1 ;28
db -1 ;29
db -1 ;2a
db -1 ;2b
db -1 ;2c
db 5 ;2d
db 1 ;2e
db 1 ;2f
db -1 ;30
db -1 ;31
db -1 ;32
db -1 ;33
db -1 ;34
db 5 ;35
db 1 ;36
db 1 ;37
db -1 ;38
db -1 ;39
db -1 ;3a
db -1 ;3b
db -1 ;3c
db 5 ;3d
db 1 ;3e
db 1 ;3f
db 1 ;40
db 1 ;41
db 1 ;42
db 1 ;43
db 1 ;44
db 1 ;45
db 1 ;46
db 1 ;47
db 1 ;48
db 1 ;49
db 1 ;4a
db 1 ;4b
db 1 ;4c
db 1 ;4d
db 1 ;4e
db 1 ;4f
db 1 ;50
db 1 ;51
db 1 ;52
db 1 ;53
db 1 ;54
db 1 ;55
db 1 ;56
db 1 ;57
db 1 ;58
db 1 ;59
db 1 ;5a
db 1 ;5b
db 1 ;5c
db 1 ;5d
db 1 ;5e
db 1 ;5f
db 1 ;60
db 1 ;61
db -1 ;62
db -1 ;63
db 1 ;64
db 1 ;65
db 1 ;66
db 1 ;67
db 5 ;68
db -3 ;69 imm32+modrm
db 2 ;6a
db -4 ;6b imm8+modrm
db 1 ;6c
db 1 ;6d
db 1 ;6e
db 1 ;6f
db 2 ;70
db 2 ;71
db 2 ;72
db 2 ;73
db 2 ;74
db 2 ;75
db 2 ;76
db 2 ;77
db 2 ;78
db 2 ;79
db 2 ;7a
db 2 ;7b
db 2 ;7c
db 2 ;7d
db 2 ;7e
db 2 ;7f
db -4 ;80
db -3 ;81
db -4 ;82
db -4 ;83
db -1 ;84
db -1 ;85
db -1 ;86
db -1 ;87
db -1 ;88
db -1 ;89
db -1 ;8a
db -1 ;8b
db -1 ;8c
db -1 ;8d
db -1 ;8e
db -1 ;8f
db 1 ;90
db 1 ;91
db 1 ;92
db 1 ;93
db 1 ;94
db 1 ;95
db 1 ;96
db 1 ;97
db 1 ;98
db 1 ;99
db 7 ;9a
db 1 ;9b
db 1 ;9c
db 1 ;9d
db 1 ;9e
db 1 ;9f
db 5 ;a0
db 5 ;a1
db 5 ;a2
db 5 ;a3
db 1 ;a4
db 1 ;a5
db 1 ;a6
db 1 ;a7
db 2 ;a8
db 5 ;a9
db 1 ;aa
db 1 ;ab
db 1 ;ac
db 1 ;ad
db 1 ;ae
db 1 ;af
db 2 ;b0
db 2 ;b1
db 2 ;b2
db 2 ;b3
db 2 ;b4
db 2 ;b5
db 2 ;b6
db 2 ;b7
db 5 ;b8
db 5 ;b9
db 5 ;ba
db 5 ;bb
db 5 ;bc
db 5 ;bd
db 5 ;be
db 5 ;bf
db -4 ;c0
db -4 ;c1
db 3 ;c2
db 1 ;c3
db -1 ;c4
db -1 ;c5
db -4 ;c6
db -3 ;c7
db 4 ;c8
db 1 ;c9
db 3 ;ca
db 1 ;cb
db 1 ;cc
db 2 ;cd
db 1 ;ce
db 1 ;cf
db 2 ;d0
db -1 ;d1
db -1 ;d2
db -1 ;d3
db 2 ;d4
db 2 ;d5
db 1 ;d6
db 1 ;d7
db -1 ;d8
db -1 ;d9
db -1 ;da
db -1 ;db
db -1 ;dc
db -1 ;dd
db -1 ;de
db -1 ;df
db 2 ;e0
db 2 ;e1
db 2 ;e2
db 2 ;e3
db 2 ;e4
db 2 ;e5
db 2 ;e6
db 2 ;e7
db 5 ;e8
db 5 ;e9
db 7 ;ea
db 2 ;eb
db 1 ;ec
db 1 ;ed
db 1 ;ee
db 1 ;ef
db 1 ;f0
db 1 ;f1
db 1 ;f2
db 1 ;f3
db 1 ;f4
db 1 ;f5
db -4 ;f6
db -1 ;f7
db 1 ;f8
db 1 ;f9
db 1 ;fa
db 1 ;fb
db 1 ;fc
db 1 ;fd
db -1 ;fe
db -1 ;ff

opc_0f db -1 ;00
db -1 ;01
db -1 ;02
db -1 ;03
db 2 ;04 n/a
db 2 ;05
db 2 ;06
db 2 ;07
db 2 ;08
db 2 ;09
db 2 ;0a
db 2 ;0b
db 2 ;0c
db 2 ;0d
db 2 ;0e
db 2 ;0f
db 2 ;10 n/a
db 2 ;11 n/a
db 2 ;12 n/a
db 2 ;13 n/a
db 2 ;14 n/a
db 2 ;15 n/a
db 2 ;16 n/a
db 2 ;17 n/a
db 2 ;18 n/a
db 2 ;19 n/a
db 2 ;1a n/a
db 2 ;1b n/a
db 2 ;1c n/a
db 2 ;1d n/a
db 2 ;1e n/a
db 2 ;1f n/a
db 3 ;20
db 3 ;21
db 3 ;22
db 3 ;23
db 3 ;24
db 2 ;25 n/a
db 3 ;26
db 2 ;27 n/a
db 2 ;28 n/a
db 2 ;29 n/a
db 2 ;2a n/a
db 2 ;2b n/a
db 2 ;2c n/a
db 2 ;2d n/a
db 2 ;2e n/a
db 2 ;2f n/a
db 2 ;30
db 2 ;31
db 2 ;32
db 2 ;33
db 2 ;34 n/a
db 2 ;35 n/a
db 2 ;36 n/a
db 2 ;37 n/a
db 2 ;38 n/a
db 2 ;39 n/a
db 2 ;3a n/a
db 2 ;3b n/a
db 2 ;3c n/a
db 2 ;3d n/a
db 2 ;3e n/a
db 2 ;3f n/a
db -1 ;40
db -1 ;41
db -1 ;42
db -1 ;43
db -1 ;44
db -1 ;45
db -1 ;46
db -1 ;47
db -1 ;48
db -1 ;49
db -1 ;4a
db -1 ;4b
db -1 ;4c
db -1 ;4d
db -1 ;4e
db -1 ;4f
db 2 ;50 n/a
db 2 ;51 n/a
db 2 ;52 n/a
db 2 ;53 n/a
db 2 ;54 n/a
db 2 ;55 n/a
db 2 ;56 n/a
db 2 ;57 n/a
db 2 ;58 n/a
db 2 ;59 n/a
db 2 ;5a n/a
db 2 ;5b n/a
db 2 ;5c n/a
db 2 ;5d n/a
db 2 ;5e n/a
db 2 ;5f n/a
db -1 ;60
db -1 ;61
db -1 ;62
db -1 ;63
db -1 ;64
db -1 ;65
db -1 ;66
db -1 ;67
db -1 ;68
db -1 ;69
db -1 ;6a
db -1 ;6b
db -1 ;6c n/a
db -1 ;6d n/a
db -1 ;6e
db -1 ;6f
db -1 ;70 n/a
db -1 ;71 n/a
db -1 ;72 n/a
db -1 ;73 n/a
db -1 ;74
db -1 ;75
db -1 ;76
db 2 ;77
db 2 ;78 n/a
db 2 ;79 n/a
db 2 ;7a n/a
db 2 ;7b n/a
db 2 ;7c n/a
db 2 ;7d n/a
db -1 ;7e
db -1 ;7f
db 6 ;80
db 6 ;81
db 6 ;82
db 6 ;83
db 6 ;84
db 6 ;85
db 6 ;86
db 6 ;87
db 6 ;88
db 6 ;89
db 6 ;8a
db 6 ;8b
db 6 ;8c
db 6 ;8d
db 6 ;8e
db 6 ;8f
db -1 ;90
db -1 ;91
db -1 ;92
db -1 ;93
db -1 ;94
db -1 ;95
db -1 ;96
db -1 ;97
db -1 ;98
db -1 ;99
db -1 ;9a
db -1 ;9b
db -1 ;9c
db -1 ;9d
db -1 ;9e
db -1 ;9f
db 2 ;a0
db 2 ;a1
db 2 ;a2
db -1 ;a3
db -4 ;a4
db -1 ;a5
db 2 ;a6 n/a
db 2 ;a7 n/a
db 2 ;a8
db 2 ;a9
db 2 ;aa
db -1 ;ab
db -4 ;ac
db -1 ;ad
db 2 ;ae n/a
db -1 ;af
db -1 ;b0
db -1 ;b1
db -1 ;b2
db -1 ;b3
db -1 ;b4
db -1 ;b5
db -1 ;b6
db -1 ;b7
db -1 ;b8 n/a
db -1 ;b9 n/a
db -1 ;ba n/a
db -1 ;bb
db -1 ;bc
db -1 ;bd
db -1 ;be
db -1 ;bf
db -1 ;c0
db -1 ;c1
db 2 ;c2 n/a
db 2 ;c3 n/a
db 2 ;c4 n/a
db 2 ;c5 n/a
db 2 ;c6 n/a
db 2 ;c7 n/a
db 2 ;c8
db 2 ;c9
db 2 ;ca
db 2 ;cb
db 2 ;cc
db 2 ;cd
db 2 ;ce
db 2 ;cf
db -1 ;d0 n/a
db -1 ;d1
db -1 ;d2
db -1 ;d3
db -1 ;d4 n/a
db -1 ;d5
db -1 ;d6 n/a
db -1 ;d7 n/a
db -1 ;d8
db -1 ;d9
db -1 ;da n/a
db -1 ;db
db -1 ;dc
db -1 ;dd
db -1 ;de n/a
db -1 ;df
db 2 ;e0 n/a
db -1 ;e1
db -1 ;e2
db 2 ;e3 n/a
db 2 ;e4 n/a
db -1 ;e5
db 2 ;e6 n/a
db 2 ;e7 n/a
db -1 ;e8
db -1 ;e9
db 2 ;ea n/a
db -1 ;eb
db -1 ;ec
db -1 ;ed
db 2 ;ee n/a
db -1 ;ef
db 2 ;f0 n/a
db -1 ;f1
db -1 ;f2
db -1 ;f3
db 2 ;f4 n/a
db -1 ;f5
db 2 ;f6 n/a
db 2 ;f7 n/a
db -1 ;f8
db -1 ;f9
db -1 ;fa
db 2 ;fb n/a
db -1 ;fc
db -1 ;fd
db -1 ;fe
db 2 ;ff n/a


A small exception handler that uses these tables to skip the instruction that caused the error:
SehHandler PROC uses esi edi ebx ExceptionInfo:DWORD
local _prefix:DWORD
mov esi,ExceptionInfo
assume esi:ptr EXCEPTION_POINTERS
mov esi,[esi].pExceptionRecord
assume esi:ptr EXCEPTION_RECORD
mov _prefix,0
.if (!([esi].ExceptionFlags&EXCEPTION_NONCONTINUABLE))
.while 1
mov eax,[esi].ExceptionAddress
invoke IsBadReadPtr,eax,5
.if eax
inc [esi].ExceptionAddress
.break
.else
mov eax,[esi].ExceptionAddress
inc [esi].ExceptionAddress
.continue .if (byte ptr[eax]==0f0h)||(byte ptr[eax]==0f2h)||(byte ptr[eax]==0f3h)
.continue .if (byte ptr[eax]==064h)||(byte ptr[eax]==065h)
.if (byte ptr[eax]==066h)
or _prefix,1
.continue
.elseif (byte ptr[eax]==067h)
or _prefix,2
.continue
.endif
mov al,[eax]
lea ebx,opc_table
xlat
mov edx,_prefix
.if al<80h
movzx eax,al
dec eax
.if eax>=3
.if _prefix&2
dec eax
dec eax
.endif
.endif
add [esi].ExceptionAddress,eax
.break
.elseif al==-1
mov eax,[esi].ExceptionAddress
call modrm
.elseif al==-3
mov eax,[esi].ExceptionAddress
.if _prefix&1
add [esi].ExceptionAddress,2
.else
add [esi].ExceptionAddress,4
.endif
call modrm
.elseif al==-4
mov eax,[esi].ExceptionAddress
inc [esi].ExceptionAddress
call modrm
.elseif al==-2
mov eax,[esi].ExceptionAddress
inc [esi].ExceptionAddress
mov al,[eax]
lea ebx,opc_0f
xlat
.if al<80h
movzx eax,al
dec eax
dec eax
.if eax>=3
.if _prefix&2
dec eax
dec eax
.endif
.endif
add [esi].ExceptionAddress,eax
.break
.elseif al==-1
mov eax,[esi].ExceptionAddress
call modrm
.elseif al==-3
mov eax,[esi].ExceptionAddress
.if _prefix&1
add [esi].ExceptionAddress,2
.else
add [esi].ExceptionAddress,4
.endif
call modrm
.elseif al==-4
mov eax,[esi].ExceptionAddress
inc [esi].ExceptionAddress
call modrm
.endif
.endif
.break
.endif
.endw
mov eax,[esi].ExceptionAddress
mov esi,lParam
assume esi:ptr EXCEPTION_POINTERS
mov esi,[esi].ContextRecord
assume esi:ptr CONTEXT
mov [esi].regEip,eax
mov eax,EXCEPTION_CONTINUE_EXECUTION
.else
mov eax,EXCEPTION_CONTINUE_SEARCH
.endif
assume esi:nothing
ret
SehHandler ENDP

modrm: assume esi:ptr EXCEPTION_RECORD
mov al,[eax]
inc [esi].ExceptionAddress
mov ah,al
and ax,0c00fh
.if al==4
inc [esi].ExceptionAddress
.elseif ax==5
.if dl&2
add [esi].ExceptionAddress,2
.else
add [esi].ExceptionAddress,4
.endif
.endif
.if ah==40h
inc [esi].ExceptionAddress
.elseif ah==80h
.if dl&2
add [esi].ExceptionAddress,2
.else
add [esi].ExceptionAddress,4
.endif
.endif
assume esi:nothing
ret


Using a code like this:
xor eax,eax
mov ax,word ptr[eax+7]
int 3


Will determine the procedure to skip 2 instructions,

[11:47] <Hub-Security> BIG FUCKING ERROR C0000005
ExceptionCode: EXCEPTION_ACCESS_VIOLATION
Address: 034C1132
Cause: Read from address: 00000007
EAX=00000000 EBX=00000000 ECX=0000007F EDX=00456E61
ESI=01090000 EDI=034C0000 EBP=0012FC48 ESP=0012FC48
DR0=B996CDA8 DR1=B996CD94 DR2=00000010 DR3=0012F860
DR6=30010101 DR7=00000000 FS=00000038 GS=00000000
CS=0000001B DS=00000023 ES=00000023 SS=00000023
EIP=034C1132 EFlags=00000246

[EAX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EBX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[ECX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EDX]:  55  8B  EC  83  C4  FC  56  57  53  8B  45  08  66  F7  40  09  00  08  75  09  33  C0  5B  5F  5E  C9  C2  1C  00  68  00  40
[ESI]:  00  00  00  00  00  00  00  00  00  89  FF  FF  FF  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
[EDI]:  4D  5A  90  00  03  00  00  00  04  00  00  00  FF  FF  00  00  B8  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
[EBP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[ESP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[EIP]:  66  8B  40  07  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6

Module: HeXHub.exe
Attempting to recover from error...

[11:47] <Hub-Security> BIG FUCKING ERROR 80000003
ExceptionCode: EXCEPTION_BREAKPOINT
Address: 034C1136
Parameters: 00000000, 0000007F, 00456E61
EAX=00000000 EBX=00000000 ECX=0000007F EDX=00456E61
ESI=01090000 EDI=034C0000 EBP=0012FC48 ESP=0012FC48
DR0=00000000 DR1=81B84500 DR2=BFE10BCD DR3=00000101
DR6=034C0023 DR7=00000000 FS=00000038 GS=00000000
CS=0000001B DS=00000023 ES=00000023 SS=00000023
EIP=034C1136 EFlags=00000246

[EAX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EBX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[ECX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EDX]:  55  8B  EC  83  C4  FC  56  57  53  8B  45  08  66  F7  40  09  00  08  75  09  33  C0  5B  5F  5E  C9  C2  1C  00  68  00  40
[ESI]:  00  00  00  00  00  00  00  00  00  89  FF  FF  FF  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
[EDI]:  4D  5A  90  00  03  00  00  00  04  00  00  00  FF  FF  00  00  B8  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
[EBP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[ESP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[EIP]:  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6  10  4C  03  FF

Module: HeXHub.exe
Attempting to recover from error...


First one:
   mov   ax,word ptr[eax+7] -> 66  8B  40  07
   [EIP]:  66  8B  40  07  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6
These bytes being skipped,
   int 3 -> CC
   [EIP]:  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6  10  4C  03  FF
One more byte skipped.

Tedd

If there was an exception that means something was wrong. Is ignoring that instruction and just blindly continuing really a good idea? It's likely to only cause even more exception conditions (which will also be ignored?)
Exceptions should be handled to either fix what went wrong (so you can then re-execute the faulting instruction), or should fail completely (indicating what the error was; continuing could only do even more damage.)
(And in a server this shouts EXPLOIT!!)
No snowflake in an avalanche feels responsible.

ToutEnMasm

There is only one case in which you can continue , it's on "debugbreak" or int 3 (add two to eip).
In some case,you can continue in an another proc ,but it's not very useful (program is stopped but you can used the menu).

TNick

I do agree with Ted and ToutEnMasm, but, still, thanks for sharing your work!

Nick

Vektor

Quote from: Tedd on December 11, 2007, 01:00:41 PM
If there was an exception that means something was wrong. Is ignoring that instruction and just blindly continuing really a good idea? It's likely to only cause even more exception conditions (which will also be ignored?)
Exceptions should be handled to either fix what went wrong (so you can then re-execute the faulting instruction), or should fail completely (indicating what the error was; continuing could only do even more damage.)

Some programs cannot just be closed. If a thread of a server fails for a reason, other threads can keep the server up so the best thing to do is to skip all the instructions until the faulting procedure exits or the thread terminates (the main reason i did this was to skip faulting procedures in plugins until they return). Fixing the error may not always be possible and returning to same address all the time doesn't really solve anything.

Quote from: Tedd on December 11, 2007, 01:00:41 PM
(And in a server this shouts EXPLOIT!!)
If there is an error that can be exploited in a server, exception handling matters less.

Quote from: ToutEnMasm on December 11, 2007, 02:23:43 PM
There is only one case in which you can continue , it's on "debugbreak" or int 3 (add two to eip).
In some case,you can continue in an another proc ,but it's not very useful (program is stopped but you can used the menu).
What if a plugin uses a repne scasb to search for something in a buffer that had been freed by another thread ? There can be many continuable situations, not just an int 3.

Tedd

Sorry, but that's just ridiculous. You're not just hiding problems, you're causing them!!
Each instruction is written (by human or compiler) with the particular assumption that the one before it was executed successfully. If you start skipping instructions, the assumed state of the system is incorrect and any instructions following will be working under the false assumption that they're in the right place -- you may as well just execute random instructions. Variables assumed to be in registers will not be, counters won't be updated, files won't be written or even opened... and no-one will know about it.
An exception indicates a critical error condition - that means you can't just ignore it and it will go away. The most likely result will be that you ignore the faulting instruction, only to be hit by the very next faulting instruction, which will cause the next one to fault... repeat ad nauseum -- consider how much this will slow the server right down (exceptions are quite heavy - 50 exceptions per second is going to kill you.)
Even for a 'simple' memory access fault the result is a disaster: you try to access a byte in a buffer that isn't there/owned/allowed -- EXCEPTION!! -- you ignore it and carry on, access the next byte, which also isn't there -- EXCEPTION!! -- ignore it, next byte -- EXCEPTION!! -- ignore, next, -- EXCEPTION!! -- ignore -- EXCEPTION!! EXCEPTION!! EXCEPTION!! All the way to the end of the buffer.. oh wait, it's a null-terminated string, that means we continue until we get a zero byte -- small problem, we never get ANY bytes because every time we try to read one it's ignored. So actually the thread would just continue through memory causing an exception on EVERY read, until hopefully at some point it does hit a readable area and there happens to be a zero in there somewhere. For the safety of your server and every other thread on it, the only sensible thing to do is kill that thread as soon as it causes the first exception.
The only sensible thing to do in ANY situation where a thread causes an exception (and you can't/won't fix it) is to kill the thread.
Let's say I'm developing a plugin for your server, of course I'm going to test it to make sure it works, etc. So I test it and it seems to work fine, doesn't cause any exceptions, everything's great. But.. it's not, is it - because your server is eating all of the exceptions. Nevermind 'rescuing' running threads (which you're really not,) how is anyone to check their plugin works correctly if all the errors are hidden? As it turns out, I was just trying to access a null pointer - silly mistake, easily fixed.. well, it would be if I knew about it. Whereas, if your server did throw/report exceptions then I could see my mistake and fix it in 5 minutes. Exceptions indicate badly written/thought-out code, the code should be fixed, not allowed to blindly run.


Quote from: Vektor on December 11, 2007, 07:04:10 PM
If a thread of a server fails for a reason, other threads can keep the server up so the best thing to do is to skip all the instructions until the faulting procedure exits or the thread terminates (the main reason i did this was to skip faulting procedures in plugins until they return).
If a thread of a server fails for a reason, KILL THE THREAD. All of the other threads continue and the rest of the server is fine. The WORST thing to do is skip all faulting instructions and allow that thread to continue like nothing happened - the thread is misbehaving and unpredictable, it should be killed to avoid causing any problems for either the server itself or any clients it's acting for.

Quote
If there is an error that can be exploited in a server, exception handling matters less.
And what if the error is caused precisely by the fact that you're ignoring exceptions?? I expect doing so could only lead to more exploit possibilities. Saying that it's the least of your worries is a little misguided.

Quote
What if a plugin uses a repne scasb to search for something in a buffer that had been freed by another thread ? There can be many continuable situations, not just an int 3.
There can be a few continuable situations (ones that don't immediately cause further exceptions), and even fewer of those where it's actually sensible to still continue. In any case, does that mean you should still accept every other exception condition, just because there are 'some' that may be okay??
If a plugin uses scasb to search a buffer and that buffer has been freed, the thread should have checked and locked the buffer before even attempting to access it -- again, the code should be fixed, not allowed to blindly continue. Equally, if int3 is getting executed in your code then something isn't quite right, it should only be used for padding or debugging. In the case of padding, then you're executing code where you really shouldn't be, and for debugging the debugger will catch them first, if you hard-coded them for debugging then they should've been removed before releasing the code.


Not to piddle on your idea and hard work, but time and effort spent on a stupid idea doesn't make it any less of a stupid idea.
No snowflake in an avalanche feels responsible.

ToutEnMasm

I agree with tedd.
SEH are useful when writing code,they are more faster than the use of a debugger,but that all.
A debugger can detect more defauts than the SEH,(wrong handle for example) and offer more functions for debugging.

I joined an example of SEH CODE who can find the line and the name of the source code in case of exception.He use the dbghelp.dll and run under XP.He can read the stack for errors out of the code source.
Some modifies can be made in the stack reading method (byte by byte not very faster)
The sended message is for an editor,don't take care of it.
He works and he is useful.



[attachment deleted by admin]

Vektor

Quote from: Tedd on December 12, 2007, 01:03:09 PM
Let's say I'm developing a plugin for your server, of course I'm going to test it to make sure it works, etc. So I test it and it seems to work fine, doesn't cause any exceptions, everything's great. But.. it's not, is it - because your server is eating all of the exceptions. Nevermind 'rescuing' running threads (which you're really not,) how is anyone to check their plugin works correctly if all the errors are hidden? As it turns out, I was just trying to access a null pointer - silly mistake, easily fixed.. well, it would be if I knew about it. Whereas, if your server did throw/report exceptions then I could see my mistake and fix it in 5 minutes. Exceptions indicate badly written/thought-out code, the code should be fixed, not allowed to blindly run.

Yes, you're right, hiding the exception is stupid.
The code i posted doesn't report anything, it is an example for something else than reporting. I wrote it on this forum and i never used it. But as i've shown in my post, my implementation that i actually use is reporting all the exceptions.

Quote from: Vektor on December 11, 2007, 11:08:12 AM

[11:47] <Hub-Security> BIG FUCKING ERROR C0000005
ExceptionCode: EXCEPTION_ACCESS_VIOLATION
Address: 034C1132
Cause: Read from address: 00000007
EAX=00000000 EBX=00000000 ECX=0000007F EDX=00456E61
ESI=01090000 EDI=034C0000 EBP=0012FC48 ESP=0012FC48
DR0=B996CDA8 DR1=B996CD94 DR2=00000010 DR3=0012F860
DR6=30010101 DR7=00000000 FS=00000038 GS=00000000
CS=0000001B DS=00000023 ES=00000023 SS=00000023
EIP=034C1132 EFlags=00000246

[EAX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EBX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[ECX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EDX]:  55  8B  EC  83  C4  FC  56  57  53  8B  45  08  66  F7  40  09  00  08  75  09  33  C0  5B  5F  5E  C9  C2  1C  00  68  00  40
[ESI]:  00  00  00  00  00  00  00  00  00  89  FF  FF  FF  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
[EDI]:  4D  5A  90  00  03  00  00  00  04  00  00  00  FF  FF  00  00  B8  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
[EBP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[ESP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[EIP]:  66  8B  40  07  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6

Module: HeXHub.exe
Attempting to recover from error...

[11:47] <Hub-Security> BIG FUCKING ERROR 80000003
ExceptionCode: EXCEPTION_BREAKPOINT
Address: 034C1136
Parameters: 00000000, 0000007F, 00456E61
EAX=00000000 EBX=00000000 ECX=0000007F EDX=00456E61
ESI=01090000 EDI=034C0000 EBP=0012FC48 ESP=0012FC48
DR0=00000000 DR1=81B84500 DR2=BFE10BCD DR3=00000101
DR6=034C0023 DR7=00000000 FS=00000038 GS=00000000
CS=0000001B DS=00000023 ES=00000023 SS=00000023
EIP=034C1136 EFlags=00000246

[EAX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EBX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[ECX]: N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
[EDX]:  55  8B  EC  83  C4  FC  56  57  53  8B  45  08  66  F7  40  09  00  08  75  09  33  C0  5B  5F  5E  C9  C2  1C  00  68  00  40
[ESI]:  00  00  00  00  00  00  00  00  00  89  FF  FF  FF  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
[EDI]:  4D  5A  90  00  03  00  00  00  04  00  00  00  FF  FF  00  00  B8  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
[EBP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[ESP]:  B0  FC  12  00  7E  1F  45  00  FE  02  09  01  00  00  09  01  E2  27  45  00  98  5B  7A  00  11  01  00  00  DA  16  08  00
[EIP]:  CC  FF  75  08  8F  05  04  30  4C  03  68  DC  10  4C  03  FF  15  04  30  4C  03  A3  10  30  4C  03  68  E6  10  4C  03  FF

Module: HeXHub.exe
Attempting to recover from error...


After later tests with a plugin that is known to have many bugs, the result was a 70 mb log file, so skipping indefinitely is not a good idea :bg
I do my best to prevent server downtime until an error gets reported and fixed and i was thinking that skipping an instruction may prevent a plugin that does something less important for the server to close it because of an error.
Now i changed it to terminate a thread that causes 3 consecutive exceptions (3 is the default, and the admins can change it). This might give more information about errors that can help plugin developers to fix them no matter what programming language they use. I'll see in the next days if this is a good idea or not.
BTW i have a few int 3's in my code in some places that normally should not be reached (like a plugin function removes wrong number of parameters from stack on return), and a debugger like Softice will catch them before the exception handler is executed.

Nordwind64

Thank you for sharing!  :thumbu
I use the table in a format friendlier way, maybe someone have use for it.

opc_table     db -1,-1,-1,-1,-1,5,1,1,-1,-1,-1,-1,-1,5,1,-2,-1,-1,-1,-1,-1,5,1,1,-1,-1,-1,-1,-1,5,1,1
              db  -1,-1,-1,-1,-1,5,1,1,-1,-1,-1,-1,-1,5,1,1,-1,-1,-1,-1,-1,5,1,1,-1,-1,-1,-1,-1,5,1,1
              db  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
              db  1,1,-1,-1,1,1,1,1,5,-3,2,-4,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
              db  -4,-3,-4,-4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1
              db  5,5,5,5,1,1,1,1,2,5,1,1,1,1,1,1,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5
              db  -4,-4,3,1,-1,-1,-4,-3,4,1,3,1,1,2,1,1,2,-1,-1,-1,2,2,1,1,-1,-1,-1,-1,-1,-1,-1,-1
              db  2,2,2,2,2,2,2,2,5,5,7,2,1,1,1,1,1,1,1,1,1,1,-4,-1,1,1,1,1,1,1,-1,-1

opc_0f       db -1,-1,-1,-1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
              db  3,3,3,3,3,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
              db  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
              db  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,2,2,2,2,2,2,-1,-1
              db  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
              db  2,2,2,-1,-4,-1,2,2,2,2,2,-1,-4,-1,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
              db  -1,-1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
              db  2,-1,-1,2,2,-1,2,2,-1,-1,2,-1,-1,-1,2,-1,2,-1,-1,-1,2,-1,2,2,-1,-1,-1,2,-1,-1,-1,2
Greetings, Nordwind.
Windows 7 (64Bit), JWASM/PoLink