Перейти к содержанию

Как на ассемблере обработать исключение


Рекомендуемые сообщения

Я ни разу не делал обработку исключений (SEH) на Ассемблере. Xipho, может быть ты делал и знаешь быстрое решение? Я знаю есть мануалы, но пока мне их некогда читать.

Вот пример АА на CE (в комментариях указано где нужно обработать SEH):

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(_cmpString)
label(_valueString)
label(_pValueString)
label(_pCmpString)

newmem:
pushfd
pushad
push ecx //+44(4 + 4*9 + 4) или 11 двордов
lea eax, [esp+4*B+0ac]
lea ebx,[_cmpString]
mov [_pCmpString], ebx
lea ebx,[_pCmpString]
// прооверка строки "GetPlayerFaction" по [esp+ac]
cld
mov ecx,#16
lds esi,[eax] //<<< здесь нужна обработка исключения в случае если по eax нет указателя на строку
les edi,[ebx]
cmpsb

jnz short originalcode
// если строки совпали, то записать по [esp] "999999"
lea ebx,[_valueString]
mov [_pValueString], ebx
lea ebx,[_pValueString]
mov ecx,7
lds esi,[ebx]
les edi,[esp] //<<< здесь нужна обработка исключения в случае если по esp нет указателя на строку
cld
rep movsb

originalcode:
pop ecx
popad
popfd

mov eax,[ecx]
mov edx,7EFEFEFF
jmp returnhere

db 90 90 90 90 90

_pCmpString:
dd 0
_pValueString:
dd 0

_cmpString: //"GetPlayerFaction"
db 47 65 74 50 6C 61 79 65 72 46 61 63 74 69 6F 6E 00

_valueString: // "999999"
db 39 39 39 39 39 39 00


"SpazGame.exe"+157790:
jmp newmem
nop
nop
returnhere:


[DISABLE]
"SpazGame.exe"+157790:
mov eax,[ecx]
mov edx,7EFEFEFF

dealloc(newmem)

Есть ещё один вариант "не париться" с ассемблером, а сделать dll-инжект на языке высокого уровня с обработкой исключений в секциях try ... catch. Но всё-таки может быть кто-то в курсе обработки на ассемблере?

Ссылка на комментарий
Поделиться на другие сайты

Статья Джереми Гордона

Макрос для облегчения обработки исключительных ситуаций. При использовании в СЕ вряд ли пригодится, но, на всякий:


@TRY_BEGIN MACRO Handler
Pushad ;сохраняем текущее состояние
Mov esi, offset Handler ; Адрес нового исключения
push esi ; сохраняем старое исключение
push dword ptr fs: [0] ;устанавливаем новый Handler
Mov dword ptr fs: [0], esp
ENDM
@TRY_EXCEPT MACRO Handler
Jmp NoException&Handler ;исключений нет, делаем переход
Handler: Mov esp, [esp + 8] ;исключение есть, получаем старое значение ESP
pop dword ptr fs: [0] ;востанавливаем старое исключение
add esp, 4 ; значение ESP перед тем, как SEH был установлен
Popad ; востанавливаем старое состояние
ENDM
@TRY_END MACRO Handler
Jmp ExceptionHandled&Handler ; исключение было обработано
@TRY_EXCEPT
NoException&Handler: ;исключений нет
pop dword ptr fs: [0] ;востанавливаем старое исключение
add esp, 32 + 4 ; значение ESP перед тем, как SEH был установлен
32 для pushad и 4 для смещения Handler (состояние не восстанавливается)
ExceptionHandled&Handler:
; исключение было обработано, или его вообще не было
ENDM

Вышеописанный макрос используется так:

@TRY_BEGIN HandlerName 
; Код в этом месте будет проверен на исключения.
@TRY_EXCEPT HandlerName
; Код в этом месте будет выполнен, если исключение произойдет.
@TRY_END HandlerName
; Нормальное выполнение

Пример программы:

Чтобы откомпилировать эту программу, Вам потребуется 32 бит. Turbo Assembler

TASM32 /ml SEH

TLINK32 SEH, SEH, , IMPORT32.LIB

.386p
.model flat, stdcall
EXTRN ExitProcess:PROC
EXTRN MessageBoxA:PROC
; Определяем @TRY_BEGIN, @TRY_EXCEPT и @TRY_END макрос здесь
.data
SzCaption Db ' SEH на Ассме ', 0
SzException Db ' Исключение было обработано!! ', 0dh, 0ah
Db ' Нажмите ОК для завершения ', 0
SzNoException Db ' Исключений нет ', 0
.code
WinMain:
@TRY_BEGIN Zero_Address_Access
Mov Ebx, 0 ; подготовка для записи в адрес 0
Mov [Ebx], ebx ; пишим, по адресу 0 (нарушение доступа)
@TRY_EXCEPT Zero_Address_Access
; этот код выполнится, если исключение произойдет.
call MessageBoxA, 0, offset szException, offset szCaption, 0
Jmp ExitProgram
@TRY_END Zero_Address_Access
; нормальное выполнение
ExitProgram:
call MessageBoxA, 0, offset szNoException, offset szCaption, 0
call ExitProcess, 0
END WinMain

PS. Применение этого макроса - самый простейший способ )) Жаль, что его нельзя применить в автоассемблере СЕ ) Впрочем, если постараться, то можно попробовать что-то подобное сделать. Надо подумать.

Ссылка на комментарий
Поделиться на другие сайты

Я вот всё равно не пойму, когда исключение срабатывает при обращении к несуществующему адресу, то как определяется чему должен установиться EIP? Есть быстрый ответ?

Ссылка на комментарий
Поделиться на другие сайты

Отрывок из статьи, ссылку на которую давал выше:

внутрипоточный обработчик исключений

Этот тип обработчиков обычно используется для защиты некоторых локальных областей кода и устанавливается путем изменения значения, сохраненного системой в памяти по адресу FS:[0]. Каждый поток в вашей программе имеет свое уникальное значение в сегментном регистре FS, так что этот тип обработчиков исключений является поточно-зависимым. Он будет вызываться только в том случае, если исключение происходит во время выполнения кода, защищенного этим обработчиком.

Значение в FS - 16-разрядный селектор, который указывает на "Блок информации Потока" ("Thread Information Block", TIB), - структуру, которая содержит важную информацию о каждом потоке. Самое первое двойное слово (DWORD) в TIB указывает на структуру, которую мы будем называть - структурой "ERR".

Структура "ERR" состоит как минимум из двух двойных слов, как показано на следующей схеме:

1st dword +0 Указатель на следующую структуру ERR (расположенную выше по цепочке).

2nd dword +4 Указатель на имеющийся обработчик исключений.

Установка внутрипоточного обработчика исключений

Теперь мы можем увидеть, как просто можно установить этот тип обработчиков исключений:

Пример:

PUSH OFFSET HANDLER
PUSH FS:[0] ;Адрес следующей структуры ERR.
MOV FS:[0],ESP ;Помещаем в FS:[0] адрес только что созданной структуры ERR.
...
... ;Здесь находится защищенный обработчиком код.
...
POP FS:[0] ;Восстанавливаем в FS:[0] адрес предыдущей ERR, которая
;до этого была следующей в цепочке вверх после текущей ERR.
;Тем самым, мы удаляем текущий обработчик исключений.
ADD ESP, 4h ; Очищаем стек от остатков ненужной нам более структуры ERR.
RET
;***********************
HANDLER:
...
... ;Здесь находится код обработчика исключений.
...
MOV EAX,1 ;Возможные возвращаемые значения и их описание:
;eax=1 исключение не было обработано (система вызовет
;следующий по цепочке внутрипоточный обработчик);
;eax=0 перезагрузить контекст и продолжить выполнение
;программы.
RET

Из этого отрывка следует, что при обработке исключений система передает управление на адрес, указанный в обработчике исключений потока.

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.