SEH и антиотладка

Тема в разделе "WASM.WIN32", создана пользователем vg, 1 сен 2009.

  1. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Разбираюсь с работай SEH. Возник следующий вопрос. Правильно ли, что после работы следующего антиотладочного приёма из статьи Способы обхода отладчиков режима пользователя R4DX перестанет нормально работать SEH в данном процессе, т. к. нарушится цепочка SEH-фреймов - обработка всех исключений будет заканчиваться на ближайшем перезаписаном обработчике?
    Код (Text):
    1.     assume fs: nothing      ; Устанавливаем новый seh обработчик
    2.     push offset seh_handler ;
    3.     push dword ptr fs:[0]   ;
    4.     mov fs:[0],esp          ;
    5.  
    6.     call DebugBreak ;  
    7.     jmp exit        ; Если DebugBreak не вызвал ошибок, то мы здесь => нас отлаживают!!!; Выходим ;)
    8.  
    9. seh_handler:                                       ; Если мы здесь, то все ОК и нас не отлаживают!!!
    10.     mov esi,[esp+0ch]                            ; В esi указатель на CONTEXT
    11.     assume esi:PTR CONTEXT
    12.     mov [esi].regEip,offset WeArentBeingDebugged ; Устанавливаем новый eip и выходим
    13.     xor eax,eax
    14.     ret
    15. WeArentBeingDebugged: ; Здесь основная программа...
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    vg
    От отладчика зависит, опций его и пользователя. Ерунда вобщем, нормально нужно замер времени выполнить. Хочет того отладчик, или не хочит а доставлено сообщение ему будет, а это операция тяжёлая, много времени очень требует:
    Код (Text):
    1. IsDebugPortSet proc C
    2. Local CallCount:ULONG
    3. Local TimeOut:ULONG
    4.     assume fs:nothing
    5.     Int 2AH
    6.     mov ecx,eax
    7. @@:
    8.     Int 2AH
    9.     cmp eax,ecx
    10.     je @b
    11.     add eax,64*2
    12.  
    13.     mov CallCount,0
    14.     mov TimeOut,eax
    15.  
    16.     push ebp
    17.     Call Dt1
    18.     int 3
    19. Dt1:
    20.     Call Dt2
    21.     mov esp,dword ptr [esp + 4*2]
    22.     mov ebp,dword ptr [esp + 4*3]
    23.     mov dword ptr fs:[TEB.Tib.ExceptionList],esp
    24.     inc CallCount
    25.     Int 2AH
    26.     cmp TimeOut,eax
    27.     ja Gen
    28.     mov eax,CallCount
    29.     pop dword ptr fs:[TEB.Tib.ExceptionList]
    30.     cmp eax,1000H
    31.     setc al
    32.     add esp,4
    33.     movzx eax,al
    34.     ret
    35. Dt2:
    36.     push dword ptr fs:[TEB.Tib.ExceptionList]
    37. Gen:
    38.     mov dword ptr fs:[TEB.Tib.ExceptionList],esp
    39.     cli
    40. IsDebugPortSet endp
    41.  
    42. Пикод без оптимизации:
    43. db 055h, 08Bh, 0ECh, 083h, 0C4h, 0F8h, 0CDh, 02Ah, 08Bh, 0C8h
    44. db 0CDh, 02Ah, 03Bh, 0C1h, 074h, 0FAh, 005h, 080h, 000h, 000h
    45. db 000h, 0C7h, 045h, 0FCh, 000h, 000h, 000h, 000h, 089h, 045h
    46. db 0F8h, 055h, 0E8h, 001h, 000h, 000h, 000h, 0CCh, 0E8h, 033h
    47. db 000h, 000h, 000h, 08Bh, 064h, 024h, 008h, 08Bh, 06Ch, 024h
    48. db 00Ch, 064h, 089h, 025h, 000h, 000h, 000h, 000h, 0FFh, 045h
    49. db 0FCh, 0CDh, 02Ah, 039h, 045h, 0F8h, 077h, 021h, 08Bh, 045h
    50. db 0FCh, 064h, 08Fh, 005h, 000h, 000h, 000h, 000h, 03Dh, 000h
    51. db 010h, 000h, 000h, 00Fh, 092h, 0C0h, 083h, 0C4h, 004h, 00Fh
    52. db 0B6h, 0C0h, 0C9h, 0C3h, 064h, 0FFh, 035h, 000h, 000h, 000h
    53. db 000h, 064h, 089h, 025h, 000h, 000h, 000h, 000h, 0FAh
    P4, XPSP4, приоритет нормальный, аффинитет тоже, хотя это не важно. Отношение числа сепшенов без отладчика к числу под отладчиком примерно несколько сотен. Юзермодный дебуггер это не сможет обойти никак.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    *XPSP3
     
  4. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    vg
    Не совсем.
    Неточность 1: не в процессе, а в потоке – SEH-фреймы специфичны для потока (указатель на первый фрейм находится в структуре, специфичной для потока, все последующие фреймы располагаются в стеке потока).
    Неточность 2: ничего не нарушится. Код всего лишь добавляет ещё один SEH-фрейм, совершенно валидным способом, который используется в т.ч. и компиляторами. Потом, конечно, фрейм нужно убрать, а то и правда обработка нарушится, ага.

    Кстати говоря, данный приём полагается исключительно на неопытность пользователя, отлаживающего код – ожидается, что юзер кликнет в отладчике "go handled" (Shift+F9 в Olly).
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Sol_Ksacap
    Например указатель на следующий сех-фрейм замените на текущий, оля думает что это бесконечная цепочка сех фреймов и выпадает при первом исключении :)
     
  6. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Clerk
    Хм, любопытно. У нас почему-то не выпадает (просто пишет в статусной строке "Too long (Recursive?) SEH chain").

    vg
    Edit:
    >ожидается, что юзер кликнет в отладчике "go handled" (Shift+F9 в Olly)
    Следует читать 'ожидается, что юзер кликнет в отладчике "go handled" (F9 в Olly)'. Ибо "Shift+F9" это как раз правильное действие – "go unhandled", да.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Sol_Ksacap
    На сепшине отпадёт. Вобще юзермодным дебуггером нормальную антиотладку не обойти, в тойже оле столько нюансов, что нормально код который защищается отлаживать проблемно. Например точки останова про которые автор упамянул - оля их запоминает, а это значит что она их восстанавливает где не попадя. Классическая защита, которая реализована на основе всеюзабельных манав по распаковке вскрывается элементарно, чтото немного эффективное тут без ядерного дебуггера не обойтись. Теже сех-фреймы, механизм не системный, но почемуто отладчик следит за этим, тут и траблы возникают. Почитал статью по приведённой ссылке, улыбнуло:
    Автор почти понял, хотя затем совсем не туда полез в поисках решения. NtSetContextThread это один из трёх сервисов, которые загружают регистр флагов без корректировки TF. Незачем пытаться обнаружить трассировку, если можно выйти из под неё, например указанным сервисом, хотя не совсем удобно. После исполнения этого сервиса поток вернётся имея в контексте сброшенный TF, тоесть после вызова этого сервиса трассировочное исключение не возникнет и безразличен этот флажёк при входе в сервис. Конечно это должно вызываться как сервис, а не как винапи, в первом случае вызывается шлюз, во втором функционал высокоуровневый и контролировать его нельзя, тоесть там до входа в шлюз может быть взведён в контексте TF.
     
  8. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Замер времени выполнение кода - это не больше чем шаманство. Ну попала проверка в период активного свопа и все - приехали :))
    P.S. Про выполнение кода под виртуальными ОСями вообще молчу - там совсем другие "скорости".
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    Про выполнение любого из сервисов в ядре я вобще молчу(а безних тред ничто.). Ваша виртуальная машина г_о_в_н_о!
     
  10. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    dermatolog
    ну и что, что своп? несколько раз проверил - выкинул ошибочные замеры.
    скорость тоже меряется и масштабируется.
     
  11. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Clerk
    Я вас попрошу без перехода на личности, а то я тоже оскорбить могу - мало не покажется.

    GoldFinch
    Я как раз и писал что замер скорости кода чреват фалсами. Для троянов и прохей хрени это может и потянет с пивом, но в коммерческий софт я бы такое никогда не засунул.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    Вы виртуальные машины упомянули, а свою я обсудить не могу.. ибо не писал, тока вашу.
    GoldFinch
    Что проверил ?
     
  13. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Clerk
    Вы перепутали топики - здесь идет обсуждение исключительно вашего кодеса :)) И слово г_о_в_н_о больше подходит именно к тому, что вы тут предлагаете для vg.
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    Что именно ?

    Тогда не будим ничего обсуждать, используем IsDebuggerPresent() или как там она, налепим стопятцот циклов pushfd, добавим дебугпринтов и выкинем это фтопку..
     
  15. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Clerk
    Читаем еще раз:
    Замер времени выполнения кода - это не больше чем шаманство.

    На реальной системе количество циклов может плавать очень сильно и 0x1000 это совсем не показатель. Под варью к примеру получается порядка 0x400 без всякого дебага. Дальше тестируйте сами - у меня больше нет времени рассказывать что и как.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    Понятно. Предложите лучшее решение для обнаружения отладочного порта. Инфоклассы ProcessDebugPort и ProcessDebugObjectHandle не учитываем, так как есчо более не надёжно.
     
  17. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Clerk
    Так вот не падает же. Плагины убрали, Olly чистую запустили – всё равно не падает. Другое дело, что на нашей винде по умолчанию включена предварительная проверка цепочки SEH-фреймов [KEXECUTE_OPTIONS: KPROCESS.ExecuteOptions.DisableExceptionChainValidation == false, SetProcessDEPPolicy\NtSetInformationProcess] и эта самая проверка (да-да, всего лишь небольшой дополнительный цикл внутри RltDispatchException) не учитывает такого хитрого расклада и уходит в бесконечное закручивание на месте. Хех.

    Так, это мы к чему?.. Кто-нибудь с третьей сторороны может протестировать Olly на предмет её падения при выполнении следующего кода:
    Код (Text):
    1. nop
    2. mov eax, fs:[0]
    3. mov [eax], eax
    4. nop
    5. ud2
    6. nop
    7. nop
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Sol_Ksacap
    Падает я имел ввиду что процесс вылетает отлаживаемый, но никак не оля, впрочем без разницы.
    На счёт #15 есть несколько идей, не буду описывать тут, вобщем несколько событий доставляют сообщение на отладочный порт, доставка некоторых из них зависит от параметров сервисов, что теоретически должно привести к отношению, которое постоянно, в этом случае число вызовов не имеет значения.
     
  19. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Clerk
    О, ясно. Не рассматривали это как некий сорт антиотладки, поскольку в этом случае поведение под отладчиком (т.е падение программы) должно соответствовать поведению без оного. Базово – лишь экстравагантный способ самоубийства.
    Кстати. На нашей текущей системе (S2008 x64 SP1) не падает ничего, даже если отключить ранее упомянутую предпроверку seh-цепочек – просто идёт бесконечный цикл с вызовом одного и того же первого в цепочке хендлера (цепочка, собственно, при исполнении "mov eax,fs:[0] \ mov [eax],eax" превращается в петлю, да). Конечно, если хендлер вернёт что-нибудь отличное от 'ExceptionContinueSearch' и 'ExceptionNestedException', то цикл прервётся с последующим продолжением выполнения или же поднятием нового исключения, ага.
     
  20. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    У меня тоже все нормально. Отладчик 2 раза сообщает "Too long (Recursive?) SEH chain", а после ud2 процесс уходит в завис из-за зацикливания SEH.