Сейчас на форуме: tyns777, JustLife, zds, 2nd, morgot, Rio, CDK123, tihiy_grom (+4 невидимых)

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

Ранг: 88.3 (постоянный), 3thx
Активность: 0.040
Статус: Участник

Создано: 01 февраля 2009 02:06
· Личное сообщение · #1

Windows как то по разному обрабатывает исключения в коде, в зависимости от того на каком стеке возникает исключение, может кто нибудь знает точный алгоритм, вот например результаты опытов (код который генерирует исключение и SEH находятся в коде программы):
1. SEH + исключение в главном стеке программы - обрабатывается нормально
2. SEH + исключение в треде (стек треда) - обрабатывается нормально
3. SEH + исключение в callback таймера (стек не понятной чей, наверное kernel) - НЕ обрабатывается
4. SEH + исключение, код выполняется на стеке (памяти) выделеным VirtualAlloc - НЕ обрабатывается
5. SEH + исключение, код выполняется на стеке выделеным HeapCreate/HeapAlloc - НЕ обрабатывается

Как например можно создать такой же стек как и у треда (или главной программы), может такой стек имеет какие нибудь "интересные" аттрибуты в отличие от стека случаев 4, 5?

Почему же исключения не обрабатываются в 3,4,5 случаях?




Ранг: 116.6 (ветеран), 8thx
Активность: 0.050
Статус: Участник

Создано: 01 февраля 2009 07:03 · Поправил: dermatolog
· Личное сообщение · #2

Прога скомпилена с использованием /SAFESEH?



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 01 февраля 2009 09:05
· Личное сообщение · #3

Исключение не обрабатывается только в одном случае - невалидный стек, тоесть страница адресуемая ss:esp не доступна для записи. Используй VEH.
> стек не понятной чей, наверное kernel
Каждый юзермодный поток имеет ядерный стек(DPC - стек), последний не зависит от юзермодного стека.
> Как например можно создать такой же стек как и у треда
ntdll!RtlCreateUserStack().
> Почему же исключения не обрабатываются в 3,4,5 случаях?
Обрабатываются.



Ранг: 88.3 (постоянный), 3thx
Активность: 0.040
Статус: Участник

Создано: 01 февраля 2009 11:15
· Личное сообщение · #4

dermatolog пишет:
Прога скомпилена с использованием /SAFESEH?

Нет, да это даже не важно как скомпилирована... Допустим в случаях 3,4,5 я трассировал исключение, где же именно оно не обрабатывается, дошел до кода где то в недрах ntdll, обработчик проверяет адрес стека на котором было вызвано исключение, так вот в случаях 3,4,5 обработчик перебирает все стеки процесса (точнее не все стеки а просто проверяет входит ли данный стек в стек процесса) и понимает что исключение выполнено на "не зарегистрированном" стеке, и просто не обрабатывает его.

А в случае 2, обработчик проверяет находится ли стек в стеке программы или стек треда.

Так почему же обработчик не принимает стек созданный HeapCreate/HeapAlloc?

Clerk пишет:
Исключение не обрабатывается только в одном случае - невалидный стек, тоесть страница адресуемая ss:esp не доступна для записи.

Стек валидный, например же в 5 случае он вообще создан с помощью HeapCreate/HeapAlloc, запись разрешена...

Clerk пишет:
Используй VEH.

Да не в этом дело

Clerk пишет:
ntdll!RtlCreateUserStack().

Ага, спасибо, попробую!

Clerk пишет:
Обрабатываются.

Вот пример в аттаче (исходники и бинарник), если убрать mov esp, d то все нормально, а если стек поменять - то второе сообщение не показывается... прога вылетает на исключении. Не обрабатывается....


64a6_01.02.2009_CRACKLAB.rU.tgz - QueryStack.zip



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 01 февраля 2009 13:01 · Поправил: Clerk
· Личное сообщение · #5

Enigma
Всё понятно. В начале RtlDispatchException() выполняется проверка на принадлежность фрейма стеку, тоесть проверяется диапазон. Это границы стека определённые в TEB(TIB, поля StackBase и StackLimit). Если фрейм вне этого диапазона, то далее структурная обработка исключения не исполняется диспетчером. Вот код:
Code:
  1. RtldispatchException:
  2. [...]
  3. 7C9377EB                            call ntdll._RtlpGetStackLimits@8
  4. 7C9377F0                            call ntdll._RtlpGetRegistrationHead@0
  5. 7C9377F5                            and dword ptr ss:[ebp+8],0
  6. 7C9377F9                            mov ebx,eax
  7. 7C9377FB                            cmp ebx,-1
  8. 7C9377FE                            je ntdll.7C937893
  9. 7C937804                            push edi
  10. 7C937805                            cmp ebx,dword ptr ss:[ebp-8]
  11. 7C937808                            jb ntdll.7C92AA2B
  12. 7C93780E                            lea eax,dword ptr ds:[ebx+8]
  13. 7C937811                            cmp eax,dword ptr ss:[ebp-C]
  14. 7C937814                            ja ntdll.7C92AA2B   ;<- не в диапазоне стека, возвращает далее ноль.

Перед сменой стека загрузи в TIB его базу и предел.



Ранг: 88.3 (постоянный), 3thx
Активность: 0.040
Статус: Участник

Создано: 01 февраля 2009 13:47
· Личное сообщение · #6

Clerk пишет:
Перед сменой стека загрузи в TIB его базу и предел.

Спасибо большое! Все точно так и есть!




Ранг: 104.9 (ветеран), 47thx
Активность: 0.040.02
Статус: Участник

Создано: 01 февраля 2009 14:12
· Личное сообщение · #7

Enigma Protector?




Ранг: 116.6 (ветеран), 8thx
Активность: 0.050
Статус: Участник

Создано: 01 февраля 2009 14:34
· Личное сообщение · #8

ManHunter пишет:
Enigma Protector?

А по нику, асму в дельфях и характеру вопроса разве не понятно? )




Ранг: 105.9 (ветеран)
Активность: 0.060
Статус: Участник

Создано: 02 февраля 2009 12:11
· Личное сообщение · #9

Clerk пишет:
Исключение не обрабатывается только в одном случае - невалидный стек, тоесть страница адресуемая ss:esp не доступна для записи. Используй VEH

VEH - точно так же не отработает при невалидном esp.




Ранг: 126.7 (ветеран)
Активность: 0.140
Статус: Участник
#CCh

Создано: 02 февраля 2009 12:33
· Личное сообщение · #10

Clerk пишет:
Исключение не обрабатывается только в одном случае - невалидный стек

Ну еще если включен флаг LoadConfig, а адреса обработчика нет в таблице.

-----
invoke OpenFire




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 02 февраля 2009 15:05
· Личное сообщение · #11

seeq
Ice-T
Вы заблуждаетесь. Обьясню. Я уже много раз писал про это, тут например:
wasm.ru/forum/viewtopic.php?id=29865&p=1
wasm.ru/forum/viewtopic.php?id=30212
wasm.ru/forum/viewtopic.php?id=29537&p=2 ,#35
"Еслючение не обрабатывается" - под этим понимается что при возникновении исключения в потоке, ядро не может выполнить его разворачивание в юзермоде. Тоесть при заполнении стекового фрейма информацией(EXCEPTION_POINTERS) возникает исключение в ядерном диспетчере исключений. Ядро не может восстановить стек потока, поэтому прибивается такой поток, да есчо и процесс, к которуму этот поток принадлежит. В любых остальных случаях будет вызван юзермодный диспетчер исключений (KiUserExceptionDispatcher), что он выполнит имеет малое значение. Так этот диспетчер находится в ntdll, следствием является то, что этот код свободно может модифицировать кто угодно. Например я часто исполняю "сырую" обработку исключения, прото выполнив редирект диспетчера исключений на свой(например сплайсингом).
Вот кусок живого ядра, который завершает процесс при подобном исключении, медитируйте на нём:
Code:
  1. 0044B7B0                            mov esp,dword ptr ss:[ebp-18]
  2. 0044B7B3                            cmp dword ptr ss:[ebp-3A0],C00000FD
  3. 0044B7BD                            jnz short ntoskrnl.0044B7EA
  4. 0044B7BF                            mov edi,dword ptr ss:[ebp-2EC]
  5. 0044B7C5                            mov eax,dword ptr ds:[edi+C]
  6. 0044B7C8                            mov dword ptr ss:[ebp-394],eax
  7. 0044B7CE                            push 14
  8. 0044B7D0                            pop ecx
  9. 0044B7D1                            lea esi,dword ptr ss:[ebp-3A0]
  10. 0044B7D7                            rep movs dword ptr es:[edi],dword ptr ds:[esi]
  11. 0044B7D9                            or dword ptr ss:[ebp-4],FFFFFFFF
  12. 0044B7DD                            mov ebx,dword ptr ss:[ebp-2F8]
  13. 0044B7E3                            xor edi,edi
  14. 0044B7E5                            jmp ntoskrnl.0042B722
  15. 0044B7EA                            or dword ptr ss:[ebp-4],FFFFFFFF
  16. 0044B7EE                            mov ebx,dword ptr ss:[ebp-2F8]
  17. 0044B7F4                            xor edi,edi
  18. 0044B7F6                            mov esi,dword ptr ss:[ebp-2EC]
  19. 0044B7FC                            push 1
  20. 0044B7FE                            push 1
  21. 0044B800                            push esi
  22. 0044B801                            call ntoskrnl._DbgkForwardException@12
  23. 0044B806                            test al,al
  24. 0044B808                            jnz ntoskrnl.004263F3
  25. 0044B80E                            push 1
  26. 0044B810                            push edi
  27. 0044B811                            push esi
  28. 0044B812                            call ntoskrnl._DbgkForwardException@12
  29. 0044B817                            test al,al
  30. 0044B819                            jnz ntoskrnl.004263F3
  31. 0044B81F                            push dword ptr ds:[esi]
  32. 0044B821                            push -1
  33. 0044B823                            call ntoskrnl.ZwTerminateProcess
  34. 0044B828                            push edi
  35. 0044B829                            push ebx
  36. 0044B82A                            push dword ptr ds:[esi+C]
  37. 0044B82D                            push dword ptr ds:[esi]
  38. 0044B82F                            push 8E
  39. 0044B834                            call ntoskrnl.KeBugCheckEx
  40. 0044B839                            int3

Этот структурный обработчик исключения, который регистрируется в самом начале KiDispatchException(), при заполнении структур, например CONTEXT изза невалидного стека возникает исключение и управление получает этот код.
Например:
Code:
  1. Mov Esp,-1
  2. Push Eax

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


 eXeL@B —› Программирование —› Стек и обработка исключений...
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати