Сейчас на форуме: Rio, tyns777, zombi-vadim (+7 невидимых)

 eXeL@B —› Программирование —› SEH - исключение в C++
Посл.ответ Сообщение

Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 15 декабря 2014 18:03 · Поправил: ksol
· Личное сообщение · #1

Может кто знает и скажет почему в следующей программе структура scopetable,
описывающая __try-блок, вычисляется только для последнего фрейма (c i = 3).
Подстановка в оператор if() другое значение i ведет к незапланированному исключению.
И другой вопрос: чем вызвана разница адресов в 5 байтов между обработчиками
handler и _except_handler3?
Заранее благодарю за ответ!
--------------------------------------
Вот копия результата с консоли:
_except_handler3: 411087
i = 0
CurrentSEH: 12fe68, PrevSEH: 12ff58
Handler: 41108c, scopetable: a1820c0d
trylevel: 2
i = 1
CurrentSEH: 12ff58, PrevSEH: 12ffa8
Handler: 41108c, scopetable: a1820cf5
trylevel: 0
i = 2
CurrentSEH: 12ffa8, PrevSEH: 12ffe0
Handler: 41108c, scopetable: a1820cad
trylevel: 0
i = 3
CurrentSEH: 12ffe0, PrevSEH: ffffffff
Handler: 7c8399f3, scopetable: 7c816d58
trylevel: 0
previousTryLevel: ffffffff
lpfnFilter: 7c843612, lpfnHandler: 7c843628

Code:
  1.  
  2. //------------------------------------------------
  3. struct _EXCEPTION_REGISTRATION;
  4. typedef _EXCEPTION_REGISTRATION* PEXCEPTION_REGISTRATION;
  5. extern "C" int _except_handler3(PEXCEPTION_RECORD,
  6.    PEXCEPTION_REGISTRATION, PCONTEXT,void*);
  7. typedef struct _SCOPETABLE {
  8.  DWORD previousTryLevel;
  9.  DWORD *lpfnFilter;
  10.  DWORD *lpfnHandler;
  11. } SCOPETABLE, *PSCOPETABLE;
  12. struct _EXCEPTION_REGISTRATION {
  13.  PEXCEPTION_REGISTRATION prev;
  14.  DWORD handler;
  15.  PSCOPETABLE scopetable;
  16.  int trylevel;
  17.  int _ebp;
  18. };
  19. //------------------------------------------------  
  20. void ShowSEH(void)
  21. {
  22.  PEXCEPTION_REGISTRATION pVCExcRec;
  23.  PSCOPETABLE scope1;
  24.  DWORD prevTryLevel;
  25.  int i = 0;
  26.  printf("_except_handler3: %x\n", _except_handler3);
  27.  __asm mov eax, fs:[0]
  28.  __asm mov [pVCExcRec], eax
  29.  while(0xffffffff != (unsigned)pVCExcRec)
  30.  {
  31.   scope1 = pVCExcRec->scopetable;
  32.   printf("\ti = %d\n",i);
  33.   printf("CurrentSEH: %x, PrevSEH: %x\n",
  34.            pVCExcRec, pVCExcRec->prev);
  35.   printf("Handler: %x, scopetable: %x\n",pVCExcRec->handler,
  36.                  scope1);
  37.   printf("trylevel: %d\n", pVCExcRec->trylevel);
  38.   if(== 3){
  39.            prevTryLevel = scope1->previousTryLevel;
  40.   printf("previousTryLevel: %x\n", prevTryLevel);
  41.   printf("lpfnFilter: %x, lpfnHandler: %x\n", scope1->lpfnFilter, 
  42.                    scope1->lpfnHandler);
  43.   }
  44.   pVCExcRec = (PEXCEPTION_REGISTRATION)(pVCExcRec->prev);
  45.   i++;
  46.  }
  47. }
  48. //------------------------------------------------
  49.  
  50. void Function1(void)
  51. {
  52.  __try
  53.  {
  54.   __try
  55.    {
  56.      __try
  57.           {
  58.            ShowSEH();
  59.           }
  60.           __except(EXCEPTION_CONTINUE_SEARCH) 
  61.           { }
  62.    }
  63.    __except(EXCEPTION_CONTINUE_SEARCH) 
  64.    { }
  65.  }
  66.  __except(EXCEPTION_CONTINUE_SEARCH) 
  67.  { }
  68. }
  69. //------------------------------------------------
  70. int main()
  71. {
  72.  __try
  73.  {
  74.    Function1();
  75.  }
  76.  __except(EXCEPTION_EXECUTE_HANDLER)
  77.  {
  78.   printf(" Exception in main()\n");
  79.  }
  80.  getch();
  81.  return 0;
  82.  
  83.  




Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 19 декабря 2014 11:39
· Личное сообщение · #2

Нашел сам ответ на 2-й вопрос, да, возможно, это связано и с моим 1-м вопросом:
Компилятор VS C++ 2008 использует не _except_handler3 , а _except_handler4.
Теперь мне надо либо как-то заставить компилятор использовать _except_handler3,
а если это не удастся, то надо будет менять структуру scopetable под обработчик _except_handler4.




Ранг: 622.6 (!), 521thx
Активность: 0.330.89
Статус: Участник
_Вечный_Студент_

Создано: 19 декабря 2014 17:16
· Личное сообщение · #3

Если не секрет: для чего все это? Какой в этом практический смысл?
В моем вопросе нет иронии, просто хочу понять чего вы пытаетесь достичь.

-----
Give me a HANDLE and I will move the Earth.




Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 20 декабря 2014 15:39
· Личное сообщение · #4

Исключения вовсю применяются в антиотладке, и как-то они меня заинтересовали.
А сравнительно недавно наткнулся на статью Matt Pietrek'a "A Crash Course on the Depth...",
и вот приведенная выше программа - это его пример в несколько приглаженном виде.
Теперь мне понятно, что теперь Microsoft значительно усложнило обработку исключений
на внутреннем уровне, введя в обиход функцию _except_handler4 c ее прологами и эпилогами.
Желание запустить эту программу у меня осталось, но отключить использование _except_handler4
опциями типа /safeseh:no не удается.




Ранг: 622.6 (!), 521thx
Активность: 0.330.89
Статус: Участник
_Вечный_Студент_

Создано: 20 декабря 2014 22:16
· Личное сообщение · #5

Статья Петрика пожалуй лучшая по теме, да вот беда - написана она очень давно, почти 18 лет назад.
С тех пор, понятное дело, многое изменилось.
Я когда-то копал эту тему, статью Петрика выучил чуть не наизусть и задавал вопросы вот здесь: https://exelab.ru/f/action=vthread&forum=5&topic=20420&page=0#4
Если интересно, гляньте, там есть несколько толковых ссылок, которые могут быть вам полезными.

-----
Give me a HANDLE and I will move the Earth.




Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 21 декабря 2014 15:14 · Поправил: ksol
· Личное сообщение · #6

Спасибо, plutos, посмотрю. Мне удалось переключить программу на использование _except_handler3.
Результат ниже. Как видно, программа непосредственно использует фреймы 0 и 1, а два последних -
система, наверное, использует для своих нужд. В фрейме 2 система опять вернулась к _except_handler4,
а в последнем фрейме в качестве обработчика используется функция из пространства kernel32.dll,
хотя и по правилам EH3.
_except_handler3: 411087
i = 0
CurrentSEH: 12fe6c, PrevSEH: 12ff58
Handler: 411087, scopetable: 416b60
trylevel: 2
previousTryLevel: ffffffff
lpfnFilter: 413a90, lpfnHandler: 413a9e
i = 1
CurrentSEH: 12ff58, PrevSEH: 12ffa8
Handler: 411087, scopetable: 416b98
trylevel: 0
previousTryLevel: ffffffff
lpfnFilter: 411835, lpfnHandler: 41183b
i = 2
CurrentSEH: 12ffa8, PrevSEH: 12ffe0
Handler: 41108c, scopetable: 15de6cb9
trylevel: 0
i = 3
CurrentSEH: 12ffe0, PrevSEH: ffffffff
Handler: 7c8399f3, scopetable: 7c816d58
trylevel: 0
previousTryLevel: ffffffff
lpfnFilter: 7c843612, lpfnHandler: 7c843628



Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 04 января 2015 17:59
· Личное сообщение · #7

Совсем застрял на определении адреса обработчика SEH4 (в приведенном мной результате
это когда i = 2) -- может кто что-нибудь подскажет?!
Для SEH4 адрес таблицы scopetable кодируется, и при каждом запуске программы он другой.
Начальный этот адрес XOR - ится с __security_cookie, но воспользоваться в коде си этой
переменной мне не удается.
Компилятор MSVC признаёт эту __security_cookie, если сделать следующее:
вначале закомментировать ее, установить в коде точку останова, запустить программу
в MSVC, затем раскомментировать ее. Тогда при подводе к ней указателя мыши,
компилятор узнает ее и выдает какое-то значение. А вот включить в код
эту __security_cookie никак не удаётся.




Ранг: 622.6 (!), 521thx
Активность: 0.330.89
Статус: Участник
_Вечный_Студент_

Создано: 04 января 2015 20:40
· Личное сообщение · #8

Как я уже писал выше, с этой темой разбирался очень давно и детали потускнели в памяти.
Гляньте по вот этим ссылкам, может прояснит что-нибудь, хотя не гарантирую.

http://blogs.msdn.com/b/vcblog/archive/2009/03/19/gs.aspx
http://blogs.technet.com/b/srd/archive/2009/03/16/gs-cookie-protection-effectiveness-and-limitations.aspx

-----
Give me a HANDLE and I will move the Earth.




Ранг: 0.0 (гость)
Активность: 0.250
Статус: Участник

Создано: 05 января 2015 02:01
· Личное сообщение · #9

ksol пишет: Исключения вовсю применяются в антиотладке, и как-то они меня заинтересовали.

Сплоеты вообще интересная штука.
Есть же нормальные маны по написанию сплоетов, зачем ходить вокруг да около.
exploit-writing-tutorial




Ранг: 568.2 (!), 465thx
Активность: 0.550.57
Статус: Участник
оптимист

Создано: 05 января 2015 03:08
· Личное сообщение · #10

ksol пишет:
safeseh

так вроде таблица исключений хранится в Load Config Directory? и при обработке исключения системная функция проверяет есть ли SEH в этой таблице......

-----
Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли.




Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 05 января 2015 18:28
· Личное сообщение · #11

To plutos и F_a_u_s_t - прошёлся я по указанным ссылкам - вроде всё не то, хотя и близко.
Мне не нужно переполнять буфер, мне бы хотелось в данный момент прочитать только
поля структуры scopetable для SEH4. Да, вверху там приведены структуры для SEH3, для
SEH4 их надо немного подправить.
ClockMan - Вас я совсем не понял.



Ранг: 0.0 (гость)
Активность: 0.250
Статус: Участник

Создано: 06 января 2015 14:28
· Личное сообщение · #12

ksol пишет: вроде всё не то

Там точно есть то что вам нужно, но раз не нравится, то попытка номер два.
exceptional-behavior-windows-81-x64-seh
Exceptional Behavior - x64 Structured Exception Handling

| Сообщение посчитали полезным: ksol

Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 06 января 2015 17:45
· Личное сообщение · #13

F_a_u_s_t спасибо! Ваше 1-е предложение ближе - там есть SEH4.
Я посмотрел свою программу в OllyDbg и нашел интересный момент:
Оказывается даже при компиляции с опцией /GS в функции ShowSEH(),
из которой я пытаюсь достать scopetable для SEH4, находится __SEH_prolog3.
А в двух других функциях стоят __SEH_prolog4. Остается теперь уничтожить
ShowSEH(), а её тело вставить в другую, например, в Function1().



Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 07 января 2015 16:41
· Личное сообщение · #14

Нет, не получилось ничего нового! Всё по-прежнему: результат нулевой.



Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 12 января 2015 18:50
· Личное сообщение · #15

Сделал! Адрес __security_cookie взял из __SEH_prolog4, он оказался 0х417000.
После этого XOR с __security_cookie даёт реальный адрес таблицы scopetable,
а дальше уже делается как для незащищённой SEH. Вот результат для двух
режимов компиляции:
Незащищённый, опция /GS-
_except_handler3: 411087
_except_handler4: 41108c
i = 0
CurrentSEH: 12fe6c, PrevSEH: 12ff58
handler: 411087 trylevel: 2
Handler => _except_handler3
scopetable: 416b50
previousTryLevel: ffffffff
lpfnFilter: 41178a, lpfnHandler: 41178d
i = 1
CurrentSEH: 12ff58, PrevSEH: 12ffa8
handler: 411087 trylevel: 0
Handler => _except_handler3
scopetable: 416b90
previousTryLevel: ffffffff
lpfnFilter: 411855, lpfnHandler: 41185b
i = 2
CurrentSEH: 12ffa8, PrevSEH: 12ffe0
handler: 41108c trylevel: 0
Handler => _except_handler4
e4scopetable = 416bb0
scope4 = 416bc0
previousTryLevel: fffffffe
lpfnFilter: 411eed, lpfnHandler: 411f08
i = 3
CurrentSEH: 12ffe0, PrevSEH: ffffffff
handler: 7c8399f3 trylevel: 0
Handler => _except_handler3
scopetable: 7c816d58
previousTryLevel: ffffffff
lpfnFilter: 7c843612, lpfnHandler: 7c843628
Защищённый, опция /GS
_except_handler3: 411087
_except_handler4: 41108c
i = 0
CurrentSEH: 12fe68, PrevSEH: 12ff58
handler: 41108c trylevel: 2
Handler => _except_handler4
e4scopetable = 416b50
scope4 = 416b60
previousTryLevel: fffffffe
lpfnFilter: 411797, lpfnHandler: 41179a
i = 1
CurrentSEH: 12ff58, PrevSEH: 12ffa8
handler: 41108c trylevel: 0
Handler => _except_handler4
e4scopetable = 416b90
scope4 = 416ba0
previousTryLevel: fffffffe
lpfnFilter: 411862, lpfnHandler: 411868
i = 2
CurrentSEH: 12ffa8, PrevSEH: 12ffe0
handler: 41108c trylevel: 0
Handler => _except_handler4
e4scopetable = 416bb0
scope4 = 416bc0
previousTryLevel: fffffffe
lpfnFilter: 411eed, lpfnHandler: 411f08
i = 3
CurrentSEH: 12ffe0, PrevSEH: ffffffff
handler: 7c8399f3 trylevel: 0
Handler => _except_handler3
scopetable: 7c816d58
previousTryLevel: ffffffff
lpfnFilter: 7c843612, lpfnHandler: 7c843628




Ранг: 622.6 (!), 521thx
Активность: 0.330.89
Статус: Участник
_Вечный_Студент_

Создано: 13 января 2015 01:30
· Личное сообщение · #16

Можно выложить сам код? Или в личный ящик.
Хотелось бы глянуть.

-----
Give me a HANDLE and I will move the Earth.




Ранг: 102.0 (ветеран), 18thx
Активность: 0.070.02
Статус: Участник

Создано: 13 января 2015 16:42 · Поправил: ksol
· Личное сообщение · #17

Пожалуйста, вот код:
Code:
  1. //------------ prg14.cpp ----------------------
  2. #include <stdio.h>
  3. #include <conio.h>
  4. #include <windows.h>
  5. //-------------------------- EH3 ----------------------
  6. struct _EXCEPTION_REGISTRATION;
  7. typedef _EXCEPTION_REGISTRATION* PEXCEPTION_REGISTRATION;
  8. extern "C" int _except_handler3(PEXCEPTION_RECORD,
  9.    PEXCEPTION_REGISTRATION, PCONTEXT,void*);
  10. extern "C" int _except_handler4(PEXCEPTION_RECORD,
  11.    PEXCEPTION_REGISTRATION, PCONTEXT,void*);
  12. typedef struct _SCOPETABLE {
  13.  DWORD previousTryLevel;
  14.  DWORD *lpfnFilter;
  15.  DWORD *lpfnHandler;
  16. } SCOPETABLE, *PSCOPETABLE;
  17. struct _EXCEPTION_REGISTRATION {
  18.  PEXCEPTION_REGISTRATION prev;
  19.  PVOID handler;
  20.  PSCOPETABLE scopetable;
  21.  int trylevel;
  22.  int _ebp;
  23. };
  24. //-------------------------- EH4 ----------------------
  25. struct _EXCEPTION_REGISTRATION4;
  26. typedef _EXCEPTION_REGISTRATION4* PEXCEPTION_REGISTRATION4;
  27. typedef struct _SCOPETABLE4 {
  28.  DWORD previousTryLevel;
  29.  DWORD *lpfnFilter;
  30.  union {
  31.   DWORD *lpfnHandler;
  32.   DWORD *lpfnFinally;
  33.  };
  34. } SCOPETABLE4, *PSCOPETABLE4;
  35. typedef struct _E4SCOPETABLE {
  36.   DWORD GSCookieOffset;
  37.   DWORD GSCookieXOROffset;
  38.   DWORD EHCookieOffset;
  39.   DWORD EHCookieXOROffset;
  40.   SCOPETABLE4 scopetable4[];
  41. } E4SCOPETABLE, *PE4SCOPETABLE;
  42. struct _EXCEPTION_REGISTRATION4 {
  43.  PEXCEPTION_REGISTRATION4 prev;
  44.  PVOID handler;
  45.  union {
  46.  PSCOPETABLE scopetable;
  47.  PE4SCOPETABLE e4scopetable;
  48.  };
  49.  int trylevel;
  50.  int _ebp;
  51. };
  52. //------------------------------------------------
  53.  void ShowSEH(void)
  54. {
  55.  PEXCEPTION_REGISTRATION4 pVCExcRec;
  56.  PSCOPETABLE scope1;
  57.  PSCOPETABLE4 scope4;
  58.  PE4SCOPETABLE e4scope;
  59.  DWORD Handler,prevTryLevel,sk;
  60.  int i = 0;
  61.  printf("_except_handler3: %x\n", _except_handler3);
  62.  printf("_except_handler4: %x\n", _except_handler4);
  63.  __asm mov eax, fs:[0]
  64.  __asm mov [pVCExcRec], eax
  65.  while(0xffffffff != (unsigned)pVCExcRec)
  66.  {
  67.   Handler = (DWORD)pVCExcRec->handler;
  68.   printf("\ti = %d\n",i);
  69.   printf("CurrentSEH: %x, PrevSEH: %x\n",pVCExcRec, pVCExcRec->prev);
  70.   printf("handler: %x trylevel: %x\n",Handler,pVCExcRec->trylevel);
  71. //----- _except_handler3 ------//
  72.   if(Handler != (DWORD)_except_handler4)
  73.    {
  74.           printf("Handler => _except_handler3\n" );
  75.      scope1 = pVCExcRec->scopetable;
  76.      printf("scopetable: %x\n",scope1);
  77.      prevTryLevel = scope1->previousTryLevel;
  78.      printf("previousTryLevel: %x\n", prevTryLevel);
  79.      printf("lpfnFilter: %x, lpfnHandler: %x\n", scope1->lpfnFilter, 
  80.                    scope1->lpfnHandler);
  81.     } 
  82. //----- _except_handler4 ------//   
  83.   if(Handler == (DWORD)_except_handler4)
  84.   { 
  85.    printf("Handler => _except_handler4\n" );
  86.    e4scope = pVCExcRec->e4scopetable;
  87.    __asm mov eax, 0x417000
  88.    __asm mov eax,[eax]
  89.    __asm mov [sk], eax
  90.    ((DWORD_PTR&)e4scope) ^= sk;
  91.    printf("e4scopetable = %x\n",e4scope);
  92.    scope4 = e4scope->scopetable4;
  93.    printf("scope4 = %x\n",scope4);
  94.    prevTryLevel = scope4->previousTryLevel;
  95.    printf("previousTryLevel: %x\n", prevTryLevel);
  96.    printf("lpfnFilter: %x, lpfnHandler: %x\n", scope4->lpfnFilter, 
  97.                    scope4->lpfnHandler);
  98.   }  
  99.   pVCExcRec = (PEXCEPTION_REGISTRATION4)(pVCExcRec->prev);
  100.   i++;
  101.  }
  102. }
  103. //------------------------------------------------
  104. void Console1(void)
  105. {
  106.  HANDLE hStdInputHandle, hStdOutputHandle;
  107.  COORD dummy;
  108.  FreeConsole();
  109.  AllocConsole();
  110.  SetConsoleTitle("SEH:/GS");
  111.  hStdInputHandle = GetStdHandle(STD_INPUT_HANDLE);
  112.  hStdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  113.  SetConsoleDisplayMode( hStdOutputHandle,
  114.                    CONSOLE_WINDOWED_MODE,&dummy);
  115. }
  116. //------------------------------------------------
  117. void Function1(void)
  118. {
  119.  __try
  120.  {
  121.   __try
  122.    {
  123.      __try
  124.           {
  125.             ShowSEH();
  126.           }
  127.           __except(EXCEPTION_CONTINUE_SEARCH) 
  128.           { }
  129.    }
  130.    __except(EXCEPTION_CONTINUE_SEARCH) 
  131.    { }
  132.  }
  133.  __except(EXCEPTION_CONTINUE_SEARCH) 
  134.  { }
  135. }
  136. //------------------------------------------------
  137. int main()
  138. {
  139.   Console1();
  140.  __try
  141.  {
  142.    Function1();
  143.  }
  144.  __except(EXCEPTION_EXECUTE_HANDLER)
  145.  {
  146.   printf(" Exception in main()\n");
  147.  }
  148.  getch();
  149.  return 0;
  150. }


| Сообщение посчитали полезным: plutos
 eXeL@B —› Программирование —› SEH - исключение в C++
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати