Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

SEH. Проблемы с установкой собственного обработчика

465
23 февраля 2013 года
QWERYTY
595 / / 25.03.2012
Код:
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
SYSTEM_INFO SI;
LPVOID MemAddr;
DWORD _memaddr;
DWORD  scratch;


EXCEPTION_DISPOSITION __cdecl _except_handler(_EXCEPTION_RECORD * ExceptionRecord, LPVOID EstablisherFrame, _CONTEXT * ContextRecord, LPVOID DispatcherContext)
{

    ShowMessage("111");

    // Изменяем значение регистра EAX в context record таким образом, чтобы оно
    // указывало на какое-либо, доступное для записи место в памяти.
    // ContextRecord->Eax = (DWORD)&scratch;

    // Просим ОС еще раз попытаться выполнить вызвавшую исключение инструкцию.
    return ExceptionContinueExecution;
}




//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  Memo1->Clear();
  GetSystemInfo(&SI);
  MemAddr = VirtualAlloc(NULL, SI.dwPageSize * 10, MEM_COMMIT, PAGE_NOACCESS);
  _memaddr = DWORD(MemAddr);
  Edit1->Text = IntToHex(int(_memaddr), 8);

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   __asm
   {
      mov     eax,  _memaddr      // Передаём указатель на начало региона в который нельзя писать.
      mov     [eax], 1                     // Чтобы преднамеренно вызвать исключение
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
  DWORD handler = DWORD(_except_handler);

  __asm
  {                      // Создаем структуру EXCEPTION_REGISTRATION:
     push    handler        // Адрес функции обработчика исключений.
     push    FS:[0]            // Адрес предыдущего EXECEPTION_REGISTRATION.
     mov     FS:[0], ESP    // Добавляем в связанный список EXECEPTION_REGISTRATION.
  }
}
//---------------------------------------------------------------------------
Вот собственно весь код маленькой тестовой программы. Изначально делал на делфи но не получалось. Потом решил повторить примеры с интернета на с++

Кнопка 1 работает, исключение вызывается, а вот кнопка 2 работать не хочет.
Обработчик исключений добавляется в цепочку, но после этого возникает исключение.

Т.е. при нажатии на кнопку 2 я вижу сообщение из моей функции, хотя по логике на этот момент не должен. Причём(после ряда экспериментов) установленно что сообщение появляется всегда 2 раза . Это поведение мне показалось странным ибо в делфи оно появляется вечно. Если не брать в расчёт странность самого факта появления исключения то в остальном в делфи мне кажется всё логичным, ведь причину исключения никто не устраняет, а в с++ я никак не пойму, будто после двух попыток проблема как то разрешается. Сообщения не выводятся и программа продолжает функцианировать.

И ещё одна странность, после всего этого гемороя при нажатии кнопки 1 я вижу стандартное окно с сообщением об ошибке вместо моего. Получается что мой обработчик ставится в цепочку и тут же удаляется. Вопрос сформулировать сложно в пару строк(по тому что их много), просто прокоментируйте если увидите ошибку, в ассемблере может не так сейчас нужно делать, или может есть какие ограничения о которых я не знаю


Win XP SP3, RAD Studio 2010
327
23 февраля 2013 года
UserNet2008
748 / / 03.04.2010
Как вариант
С++ Assembler code вызывать, через функцию.
465
23 февраля 2013 года
QWERYTY
595 / / 25.03.2012
А можно идею по подробней? Какой ассемблер код и какую функцию?

Задача я надеюсь ясна? Перехват Access violation
327
01 марта 2013 года
UserNet2008
748 / / 03.04.2010
Код:
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
SYSTEM_INFO SI;
LPVOID MemAddr;
DWORD _memaddr;
DWORD  scratch;

DWORD handler; // глобальная переменная
Для начала сделаем handler глобальной переменной.
Меня интересует, что говорит компилятор думаю, что ошибок нет, а предупреждения есть или тоже нет.
Дело в том, что при использования Assembler code компилятор может не правильно его понимать.
Поэтому в некоторых случаях применяют функцию или процедуру(второй вариант под ?):
Объявляете функцию пишите там нужный вам Assembler code и возвращаете значения посредством функции.
Примерно так.

Это может быть и не по теме
465
01 марта 2013 года
QWERYTY
595 / / 25.03.2012
При компиляции ощибок и предупреждений нет.
Сделал переменную глобальной. Если выполнить только 1-ю строчку ассемблерного кода то я вижу сообщение которое запрограммировал в функции обработчике исключений. Если 2-ю то получаю Access violation. Если 2-ю и 3-ю то Access violation и процесс уже не может после этого работать. В студийном отладчике при этом везде вопросики и я не знаю что это значит(ну идут адреса, а рядом с ними вот так - ??????). 3-я строчка отдельно работает без всяких напрягов.

В ассемблере не шарю но во всех материалах которые мне попадались код такой или примерно такой. Но в любом случае ни один не работает
465
01 марта 2013 года
QWERYTY
595 / / 25.03.2012
Кстати если собрать проект в debug конфигурации то при выполнении 1-й и 2-й строчки ассемблерного кода получаю сообщение:
Privileged instruction.
327
01 марта 2013 года
UserNet2008
748 / / 03.04.2010
Ладно
Раз компилятор молчит, вот здесь может и собака и зарыта.
Давайте так Вы пишите 1-ю строчку ассемблерного кода:
Это так
 
Код:
push    handler
Теперь _except_handler делаем глобальной переменной

 
Код:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 handler = (_except_handler);
Просьба пишите более ясно у меня есть проблемы с Русским диалектом.

C++ Builder - Не управляемая платформа не в обиду будет сказано (Я с Builder C++ как черт из табакерки у Builder нормальна только JAVA - это мой выбор)
465
01 марта 2013 года
QWERYTY
595 / / 25.03.2012
Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
SYSTEM_INFO SI;
LPVOID MemAddr;
DWORD _memaddr, Curr_SEH;

DWORD handler;



EXCEPTION_DISPOSITION __cdecl _except_handler(_EXCEPTION_RECORD * ExceptionRecord, LPVOID EstablisherFrame, _CONTEXT * ContextRecord, LPVOID DispatcherContext)
{

    ShowMessage("111");

    // Изменяем значение регистра EAX в context record таким образом, чтобы оно
    // указывало на какое-либо, доступное для записи место в памяти.
   // ContextRecord->Eax = (DWORD)&scratch;

    // Просим ОС еще раз попытаться выполнить вызвавшую исключение инструкцию.
    return ExceptionContinueExecution;
}




//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  Memo1->Clear();
  GetSystemInfo(&SI);
  MemAddr = VirtualAlloc(NULL, SI.dwPageSize * 10, MEM_COMMIT, PAGE_READWRITE);
  _memaddr = DWORD(MemAddr);
  Edit1->Text = IntToHex(int(_memaddr), 8);



}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
   *(PDWORD)_memaddr = 1;  // Преднамеренно вызываем исключение
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   handler = (_except_handler); // вот эта строчка не канает, пояснения ниже

   __asm {

         push    handler
        // push    FS:[0]
        // mov     FS:[0], ESP

   }


}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button2Click(TObject *Sender)
{
   DWORD lpflOldProtect;
   VirtualProtect(MemAddr, SI.dwPageSize * 10, PAGE_READONLY, &lpflOldProtect);
}
//---------------------------------------------------------------------------
Вот весь код. При компиляции вот такая ощибка:

[BCC32 Error] Unit1.cpp(61): E2034 Cannot convert '_EXCEPTION_DISPOSITION (*)(_EXCEPTION_RECORD *,void *,_CONTEXT *,void *)' to 'unsigned long'
Full parser context
Unit1.cpp(60): parsing: void _fastcall TForm1::Button1Click(TObject *)

Насчёт буилдера не могу ничего сказать т.к. использую иключительно делфи. так что возможно что вы правы на все 110%
327
01 марта 2013 года
UserNet2008
748 / / 03.04.2010
Скажите, а что должно произойти?
Не очень понимаю концепцию программы
465
01 марта 2013 года
QWERYTY
595 / / 25.03.2012
Блин, Это тестовая программа, а вообще мне нужно будет это написать в длл(причём на делфи).

Суть программы в том чтобы перехватывать запись по определённым адресам. Для этого я планирую поставить этому региону атрибут PAGE_NOACCESS, и в подменённой функции обработчике ошибок типа Access violation менять его обратно на PAGE_READWRITE, возвращать ExceptionContinueExecution для того чтоб процесс всётаки записал данные. Вот собственно и весь замысел.

Если у вас есть какие нибудь идеи по этому поводу можете поделиться, буду только рад. Но пока это видится чуть ли не единственным решением.


Сёдня и завтра буду обмывать новую машину купленную другом, по этому не смогу быстро реагировать на сообщения.
Но тема для меня очень важная, Это некая "точка останова" в написании программы :)
327
09 марта 2013 года
UserNet2008
748 / / 03.04.2010
Цитата:
Если у вас есть какие нибудь идеи по этому поводу можете поделиться, буду только рад. Но пока это видится чуть ли не единственным решением.


Если ваш exe-файл не связал с какой-то игрой(но это не факт), то его можно запустить через IDA. В IDA можно увидеть Assembler code который можно потом вставить в вашу программу.

465
09 марта 2013 года
QWERYTY
595 / / 25.03.2012
Спасибо что хотели помочь, но я уже сделал функцию потока которая в бесконечном цикле читает и обрабатывает данные. Поставил паузу в 1 милисекунду в работе такого потока, вроде пашет, события не пропускает. С каждым новым открываемым окном стартует поток за ним следящий. Систему при открытых 4 окнах не сильно грузит, а больше врядля понадобится

Пока больше не могу на это тратить время(и ваше не хотел бы), и вопрос можно считать закрытым.
327
09 марта 2013 года
UserNet2008
748 / / 03.04.2010
Цитата:
сделал функцию потока которая в бесконечном цикле читает и обрабатывает данные


В профессиональном программировании надо избегать такие инструкции как бесконечный цикл.
Это может работать на вашем компе, а на другом просто "зависнет".
Для этого есть пользовательские события.

465
09 марта 2013 года
QWERYTY
595 / / 25.03.2012
Всё верно говорите. Но программа предпологается исключительно для личного использования на определённой операционке.

А проблема как раз в том что я не смог заполучить событие.

А IDA как вообще может помоч? Там адреса по которым нужно считывать всегда разные. Ну т.е. открывается окно и программа выводит данные полученые из интернет в окно, и за одно заполняет эту строку(которую я читаю). Закрываем\открываем окно и адрес строки другой.
Я может просто не понимаю вашу идею, если не сильно обременит прокоментируйте по подробней. Какой ассемблер код нужно извлеч, куда вставить, и т.д.
327
10 марта 2013 года
UserNet2008
748 / / 03.04.2010
Цитата:
Ну т.е. открывается окно и программа выводит данные полученые из интернет в окно, и за одно заполняет эту строку(которую я читаю)


Из интернета тут IDA не при делах (хотя ?)
Если exe-файл выходит в NET, если я не ошибаюсь можно тоже отследить.
Насчет адресов они всегда будут разные при любых условиях.

Цитата:
А проблема как раз в том что я не смог заполучить событие.


Вот об этом и стоит говорить будем голову ломать двоём.
Не бывает события которые программисты не придумали.

Правда скажу до next выводных.
Не знаю, почему с телефона, не могу ответь.

Напишите на Личную Почту:
Что и как и как вам надо. Так проще и без дураков или полет на пальцах.

465
10 марта 2013 года
QWERYTY
595 / / 25.03.2012
"Если exe-файл выходит в NET, если я не ошибаюсь можно тоже отследить."

Там не так всё просто. Там идёт передача пакетами зашифрованными, т.е. нет информации для какого окна пришли данные
465
12 марта 2013 года
QWERYTY
595 / / 25.03.2012
Вопрос был на с++, но пофиг.
На момент когда я задавал вопрос я просто не знал что мне нужно работатиь с VEH. VEH оказался куда более мощьным механизмом работы с исключениями. Вот прстой пример на делфи как обрабатывать исключения глобально для всего процесса:
Данный пример демонстрирует перехват Access violation.


Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;


function AddVectoredExceptionHandler(FirstHandler: CARDINAL; VectoredHandler: POINTER): POINTER; stdcall; external 'Kernel32.dll' name 'AddVectoredExceptionHandler';


type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;




type
  PEXCEPTION_RECORD = ^EXCEPTION_RECORD;
  EXCEPTION_RECORD = packed record
                     ExceptionCode: CARDINAL;
                     ExceptionFlags: CARDINAL;
                     ExceptionRecord: PEXCEPTION_RECORD;
                     ExceptionAddress: POINTER;
                     NumberParameters: CARDINAL;
                     ExceptionInformation: ULONG_PTR;
                     end;



type
  PEXCEPTION_POINTERS = ^EXCEPTION_POINTERS;
  EXCEPTION_POINTERS = packed record
                       ExceptionRecord: PEXCEPTION_RECORD;
                       ContextRecord: PCONTEXT;
                       end;




const
  CALL_LAST = 0;
  CALL_FIRST = 1;
  EXCEPTION_CONTINUE_SEARCH = $0;
  EXCEPTION_EXECUTE_HANDLER = $1;
  EXCEPTION_CONTINUE_EXECUTION = $FFFFFFFF;




var
  Form1: TForm1;
  SI: SYSTEM_INFO;
  MemAddr: POINTER;
  lpflOldProtect: CARDINAL;





implementation

{$R *.dfm}



  // ОБРАБОТЧИК ИСКЛЮЧЕНИЙ ПОВЕРХ СИСТЕМНОГО
function MyVectoredHandler(ExceptionInfo: PEXCEPTION_POINTERS): INTEGER; stdcall;
begin
   if ExceptionInfo.ExceptionRecord.ExceptionCode = EXCEPTION_ACCESS_VIOLATION then
   begin
      ShowMessage('Произошло исключение. ExceptionCode = EXCEPTION_ACCESS_VIOLATION');
      VirtualProtect(MemAddr, SI.dwPageSize * 10, PAGE_READWRITE, @lpflOldProtect);
      result := EXCEPTION_CONTINUE_EXECUTION;
      end
   else
   result := EXCEPTION_CONTINUE_SEARCH;
end;





procedure TForm1.Button1Click(Sender: TObject);
var
PrevHandler: POINTER;
begin
   PrevHandler := AddVectoredExceptionHandler(CALL_FIRST, Addr(MyVectoredHandler));
end;



procedure TForm1.Button2Click(Sender: TObject);
begin
   VirtualProtect(MemAddr, SI.dwPageSize * 10, PAGE_READONLY, Addr(lpflOldProtect));

end;


  // КНОПКА ВЫЗЫВАЮЩАЯ ИСКЛЮЧЕНИЕ
procedure TForm1.Button3Click(Sender: TObject);
var
A: PAnsiChar;
begin
   A := MemAddr;
   A^ := 'S';

end;



procedure TForm1.FormCreate(Sender: TObject);
begin
   Memo1.Clear;
   GetSystemInfo(SI);
   MemAddr := VirtualAlloc(NIL, SI.dwPageSize * 10, MEM_COMMIT, PAGE_READWRITE);
   Edit1.Text := IntToHex(CARDINAL(MemAddr), 8);
end;



procedure TForm1.FormDestroy(Sender: TObject);
begin
   VirtualFree(MemAddr, SI.dwPageSize * 10, 0);
end;



end.
Для новичков попавших на эту страницу из поисковика:

Не вздумайте лепить этот код куда попало. Если не вы вызываете Access violation, то перехватывать его бессмыслено, всё равно либо сообщение об ощибке, либо разрушение процесса(если вы в этом обработчике сообщите что исключение обработано)
327
16 марта 2013 года
UserNet2008
748 / / 03.04.2010
,Пользуюсь случаем послал вам два сообщения.
Одно давно(1.02.2013), а одно вчера(15,03,2013)
Не могу понять в чем проблема.

Появилась пару-треек месяцев назад.
У меня есть проблемы я не могу зайти на этот сайт с телефона(точнее на определенные ветки, если точнее ветка форум)
Например выбираю ветку "Общалка"
Выдаёт древо тем, а вот ветку выбрать не могу пишет СТРАНИЦА не найдена или удалена и всякую лабудень.

Раньше работала.
Думаю есть не адекватный Java-скрипт для Android
465
16 марта 2013 года
QWERYTY
595 / / 25.03.2012
Да, принял и обработал :)

Сейчас можете писать? Почта к сожалению для меня не очень удобна. Всё открывается по пол часа, с курсором что якобы грузится, при этом индикаторы интернет подключения не горят. Сообщение отправляю, а мне пишут что надо выбрать хотябы одного кому отправлять, при этом всё заполненно. Не знаю как у других, но лично у меня на этом сайте проблемы с почтой.
Может в настройках браузера что не так, но я не собираюсь их менять ради одного сайта.


Если писать можете давайте тут переписываться
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог