format pe64 console
entry start
include 'win64ax.inc'
include 'equates\except64.inc'
;//-----------
section '.data' data readable writeable
a dq 0
b dq 0
c dq 0
aa dd 0
bb dd 0
rdAddr dq 0
szAccess db 'Access Violation!',0
szDivide db 'Divide by Zero!',0
buff dd 0
;//-----------
section '.code' code readable executable
start:
frame
invoke SetConsoleTitle,<'x64 SEH example',0>
invoke GetModuleHandle,0
xchg rdx,rax
;//----- Пытаемся прочитать адрес юзера ------------
cinvoke printf, <10,' Image base...: 0x%016I64x',\
10,' Read address.: 0x',0>,rdx
cinvoke scanf,<'%I64x',0>,rdAddr
or eax,eax
jnz @startSeh1
@err: cinvoke printf, <' Error!',0>
jmp @exit
;//**********************************************************************
;//********* БЛОК КОНТРОЛЯ ИСКЛЮЧЕНИЙ ***********************************
@startSeh1: mov rax,[rdAddr]
mov rdx,[rax]
@endSeh1: cinvoke printf, <' Value........: 0x%016I64x',10,0>,rdx
;//**********************************************************************
;//**********************************************************************
;//----- Умножение чисел с плавающей точкой -----------------------------
@next: cinvoke printf, <10,10,' MUL float value...',\
10,' ---------------------',\
10,' Input A float: ',0>
cinvoke scanf,<'%lf',0>,a
or eax,eax
jz @err
cinvoke printf, <' Input B float: ',0>
cinvoke scanf,<'%lf',0>,b
or eax,eax
jz @err
cinvoke printf, <' Result.......: ',0>
movsd xmm0,[a]
mulsd xmm0,[b]
movq rax,xmm0
cinvoke printf,<'%lf',0>,rax
;//----- Операция деления целых чисел -----------------------------------
cinvoke printf, <10,10,' DIV integer value...',\
10,' ---------------------',\
10,' Input A int..: ',0>
cinvoke scanf,<'%u',0>,aa
or eax,eax
jz @err
cinvoke printf, <' Input B int..: ',0>
cinvoke scanf,<'%u',0>,bb
or eax,eax
jz @err
cinvoke printf, <' Result.......: ',0>
;//**********************************************************************
;//********* БЛОК КОНТРОЛЯ ИСКЛЮЧЕНИЙ ***********************************
@startSeh2: xor rdx,rdx
mov eax,[aa]
div [bb]
xchg rbx,rdx
@endSeh2: cinvoke printf, <'%u.%u',0>,rax,rbx
;//**********************************************************************
;//**********************************************************************
@exit: cinvoke _getch
cinvoke exit,0
endf
;//--------------
section '.idata' import data readable
library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll'
include 'api\kernel32.inc'
include 'api\msvcrt.inc'
;//----- Секция исключений --------------------------------
;//----- Регистрируем её в каталоге РЕ под номером(3) -----
section '.pdata' data readable
data 3
;//---- RUNTIME_FUNCTION(1)
dd RVA @startSeh1
dd RVA @endSeh1
dd RVA @UnwindInfo
;//---- RUNTIME_FUNCTION(2)
dd RVA @startSeh2
dd RVA @endSeh2
dd RVA @UnwindInfo
align 16 ;//<--- Обязательное выравнивание структуры “UNWIND_INFO”
@UnwindInfo: ;//v------------ Флаг
db 9,0,0,0 ;// 9 = 00001.001b <----- Версия
dd RVA Handler
dd 0
end data
;//----- Секция под обработчик исключений -----------------------
;//----- Microsoft советует помещать код обработчика именно сюда,
;//----- хотя это вовсе не принципиально ------------------------
section '.xdata' code readable writeable executable
proc Handler
;// RCX = адрес структуры "EXCEPTION_RECORD64"
;// R8 = адрес структуры "CONTEXT64"
virtual at rcx
record EXCEPTION_RECORD64
end virtual
virtual at r8
context CONTEXT64
end virtual
align 16
PushNonVolReg
mov [context.Rip],@next ;// обновить RIP
mov r15,szAccess
mov r10d,[record.ExceptionCode]
cmp r10d,EXCEPTION_ACCESS_VIOLATION ;// проверить код-исключения
jz @f
mov [context.Rip],@exit ;// меняем RIP в зависимости от кода
mov r15,szDivide
@@: mov r11d,[record.ExceptionFlags] ;// собираем инфу для лога
mov r12, [record.ExceptionAddress]
mov r13, [context.Rcx]
mov r14, [context.Rdx]
mov rsi, [context.R8]
mov rdi, [context.R9]
cinvoke printf,<10,10,' ************** Attention! Exception Handler **************',\
10,10,' Except code...: 0x%08X --> %s',\
10,' Except flag...: 0x%08x',\
10,' Except addr...: 0x%016I64x',10,\
10,' RCX: 0x%016I64x',\
' R8: 0x%016I64x',\
10,' RDX: 0x%016I64x',\
' R9: 0x%016I64x',10,\
10,' **********************************************************',0>,\
r10,r15,r11,r12,r13,rsi,r14,rdi
PopNonVolReg
mov eax,EXCEPTION_CONTINUE_EXECUTION ;// команда диспетчеру «Всё ОК! Продолжить»
ret
endp
Комментарии
5