# PUSH -1/IRETD -> сброс SEH

Тема в разделе "WASM.RESEARCH", создана пользователем kaspersky, 17 май 2009.

  1. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    сейчас мыщъх тестирует один очень нехилый эмуль, вытаскивая из кладовых (под)сознания накопленные анти-отладочные трюки. вот сейчас откопал давно обнаруженный баг в w2k, до сих пор не исправленный на висле и юзаемый некоторыми защитами. короче, вот код, угадайте что он делает?

    xor eax, eax
    xor ebx, ebx
    dec ebx
    push offset handler
    push ebx
    mov fs:[eax], esp
    push ebx
    push cs
    push offset jump_to
    IRETD

    угадайте, что он делает? ответ - из-за бага в ядре винды, после выполнения IRETD установленная цепочка SEH обработчиков слетает нах и управление передается на дефлотный обработчик в KRN32 ну или на фильтр, установленный SetUnhandledExceptionFilter (если он есть)
     
  2. Clerk

    Clerk Забанен

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

    Add: XPSP3

    Кстати всем трюкам трюк: NtContinue(CONTEXT.regEFlags -> 0).

    Соединил
     
  3. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    Clerk
    > А в чём баг заключается ?
    закинуть готовый пример? баг заключается в... короче, значит, что мы делаем.
    1) устанавливаем свой SEH обработчик
    2) выполняем PUSH -1/push cs/push куда_прыгать/IRETD на r3
    3) запускаем это дело на выполнение. на чем запускаем не важно. тестировалось вплоть до вислы

    при выполнении IRETD установленный SEH _слетает_. в SEH chain видится только один обрабочтк и он указывает в ядро. соотвественно, программа падает с криком об пошаговом исключии, которое подавляется установкой фильтра необрабатываемых исключений, который по идее в данной ситуации вообще не должен получать управления.

    это дело хорошо отслеживается в ольге. до выполнения IRETD у нас была цепочка SEH, а после выполнения ее уже нет. если это не баг, то я не знаю.

    > Ну взводится TF, возникает трассировочное исключение,
    > управление диспетчер исключений пулучает.
    > Если сех-фрейм валидный
    валидный.

    > то структурный обработчик исключений вызывается.
    он не только не вызывается, то еще и SEH chain ре-иницилизиреутся и туда записывается единственный системный обработчик.
     
  4. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    У меня в опытах TF не взводится а вызывается дважды установленный "обычный" (т.е. "handler") обработчик:

    Handler got control! EFLAGS:00254616 EIP:00000000
    A.Handler got control! EFLAGS:00250646 EIP:7c9012b0

    В обработчике я просто пытаюсь передать управление на метку далее. Возможно CS тоже нужно править?

    Второй EIP вроде бы указывает в процедуру менеджера исключений:

    7C9012B0 66:F2:AF REPNE SCAS WORD PTR ES:[EDI]

    (не проверял внимательно!!!)
     
  5. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    ++ Также устанавливал UnhandledExceptionFilter - он вообще не вызывается.
     
  6. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Код (Text):
    1. .code
    2. ENTER_SEH macro
    3. Local Delta1, Delta2
    4.     assume fs:nothing
    5.     push ebp
    6.     Call Delta1
    7. Delta1:
    8.     add dword ptr [esp],(ExceptionExit_ - Delta1)
    9.     Call Delta2
    10. Delta2:
    11.     add dword ptr [esp],(MainExceptionHandler - Delta2)
    12.     push dword ptr fs:[TEB.Tib.ExceptionList]
    13.     mov dword ptr fs:[TEB.Tib.ExceptionList],esp
    14. endm
    15.  
    16. LEAVE_SEH macro
    17.     clc
    18. ExceptionExit_:
    19.     pop dword ptr fs:[TEB.Tib.ExceptionList]
    20.     lea esp,[esp + 4*3]
    21. endm
    22.  
    23. $PUSH_REF macro Variable
    24. Local dt_
    25.     Call dt_
    26. dt_:
    27.     add dword ptr [esp],(offset Variable - offset dt_)
    28. endm
    29.  
    30. MainExceptionHandler proc C
    31.     mov esp,dword ptr [esp + 8] ;(esp) -> ExceptionList
    32.     mov eax,STATUS_UNSUCCESSFUL
    33.     mov ebp,dword ptr [esp + 4*3]
    34.     stc
    35.     jmp dword ptr [esp + 4*2]
    36. MainExceptionHandler endp
    37.  
    38. Entry proc
    39.     ENTER_SEH
    40.     assume fs:nothing
    41.     push -1
    42.     push cs
    43.     $PUSH_REF Continue
    44.     Iretd
    45. Continue:
    46.     nop
    47.     nop
    48.     nop
    49.     LEAVE_SEH
    50.     Int 3
    51.     ret
    52. Entry endp
    53. end Entry
    Вот скомпиленый пример:
    Код (Text):
    1. Entry:
    2. db 08Bh, 064h, 024h, 008h, 0B8h, 001h, 000h, 000h, 0C0h, 08Bh
    3. db 06Ch, 024h, 00Ch, 0F9h, 0FFh, 064h, 024h, 008h, 055h, 0E8h
    4. db 000h, 000h, 000h, 000h, 081h, 004h, 024h, 035h, 000h, 000h
    5. db 000h, 0E8h, 000h, 000h, 000h, 000h, 081h, 004h, 024h, 0DCh
    6. db 0FFh, 0FFh, 0FFh, 064h, 0FFh, 035h, 000h, 000h, 000h, 000h
    7. db 064h, 089h, 025h, 000h, 000h, 000h, 000h, 06Ah, 0FFh, 00Eh
    8. db 0E8h, 000h, 000h, 000h, 000h, 081h, 004h, 024h, 008h, 000h
    9. db 000h, 000h, 0CFh, 090h, 090h, 090h, 0F8h, 064h, 08Fh, 005h
    10. db 000h, 000h, 000h, 000h, 08Dh, 064h, 024h, 00Ch, 0CCh, 0C3h
    Чтото я ничего не вижу ядерных адресов и тп. в юзермодном стеке..
     
  7. je_

    je_ New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    143
    всё из-за -1 в EFlags
    но не из-за Trap-flag, а Nested-task-flag
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    je_
    Что значит всё ?
    Обрабатывается исключение как и должно..
     
  9. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    У меня второй Exception был потому что флаг направления в первом случае получался как после STD (у меня debugout так сделан) после того как поправл - никаких mircales:

    Код (Text):
    1. .data
    2. MsgDefault db 'Normal execution...',0Dh,0Ah,0
    3. MsgUnHandledFilter db 'UNHANDLED execution...',0Dh,0Ah,0
    4. Msghandler db 'Handler got control! EFLAGS:???????? EIP:???????? CS:????????',0Dh,0Ah,0
    5. MsgEnd db '..End!',0Dh,0Ah,0
    6. MsgAfterException db 'After ...',0Dh,0Ah,0
    7. .code
    8.  
    9.   assume fs: nothing
    10.  
    11.   push offset @@MyUnHandledFilter
    12.   call SetUnhandledExceptionFilter
    13.  
    14.   xor eax, eax
    15.   xor ebx, ebx
    16.   dec ebx
    17.   push offset @@handler
    18.   push ebx
    19.   mov  fs:[eax],esp
    20.  
    21.   push ebx
    22.   push cs
    23.   push offset jump_to
    24.   IRETD  
    25.  
    26. jump_to:
    27.  
    28.   push offset MsgDefault
    29.   call Write_Log
    30.   jmp  Exit
    31.  
    32. @@AfterException:
    33.   cld
    34.   push offset MsgAfterException
    35.   call Write_Log
    36.  
    37. Exit:
    38.  
    39.   push offset MsgEnd
    40.   call Write_Log
    41.  
    42.   invoke CloseHandle,hFile
    43.   invoke ExitProcess,NULL
    44.  
    45. @@handler proc C pExcept: dword, pFrame: dword, pContext: dword, pDispatch: dword
    46.     PrintException pExcept
    47.   pushad
    48.   mov  edx, pContext
    49.   mov  eax,(CONTEXT ptr [edx]).regFlag
    50.   mov  edi,offset Msghandler+28
    51.   call HexChar
    52.   mov  edx, pContext
    53.   mov  eax,(CONTEXT ptr [edx]).regEip
    54.   mov  edi,offset Msghandler+41
    55.   call HexChar
    56.   mov  edx, pContext
    57.   mov  eax,(CONTEXT ptr [edx]).regCs
    58.   mov  edi,offset Msghandler+53
    59.   call HexChar
    60.  
    61.   push offset Msghandler
    62.   call Write_Log
    63.   mov edx, pContext
    64.   mov (CONTEXT ptr [edx]).regEip, offset @@AfterException
    65.   popad
    66.   mov eax, ExceptionContinueExecution
    67.   ret
    68. @@handler endp
    69.  
    70. @@MyUnHandledFilter proc C pExcept: dword, pFrame: dword, pContext: dword, pDispatch: dword
    71.     PrintException pExcept
    72. @@Halt:
    73.   push offset MsgUnHandledFilter
    74.   call Write_Log
    75.   jmp  @@Halt
    76.   mov edx, pContext
    77.   mov (CONTEXT ptr [edx]).regEip, offset @@AfterException
    78.   mov eax, ExceptionContinueExecution
    79.   ret
    80. @@MyUnHandledFilter endp
    Output:

    Handler got control! EFLAGS:00254616 EIP:00000000 CS:0000001b
    After ...
    ..End!
     
  10. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Miracles. Sorry.
     
  11. je_

    je_ New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    143
    это я написал по поводу "ядерных" проблем.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Скока ждать можно, скажите в чём баг заключается :dntknw:
     
  13. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    ну не я знаю. еще раз проверил все свои оси (w2k sp4, XP SP2/SP3, S2k3 SP1, Vista SP1), ни на одной SEH не вызывается. если трассировать ольгой, то хорошо видно, что после выполнения IRETD содержимое fs:[0] меняется на значение которое было до установки нашего обработчка.

    ага. маленькая поправка. если обработчиков больше одного, то баг не проявляется. а если обработчик один (как было показано выше), то он слетает.

    xor eax, eax
    xor ebx, ebx
    dec ebx
    push offset handler
    push ebx
    mov fs:[eax], esp

    вот тут мы ставим один обработчик. до его исполнение дело вообще не доходит. сразу же после выполнения IRETD у нас fs:[0] ре-иницилизируется. под отладчком SetUnhandledExceptionFilter ес-но не вызывается. а если применить плагины, которые его таки вызывают, то вызывается SEH.

    короче, под ольгой (1.10, 2.00j) без плагинов SetUnhandledExceptionFilter не вызывается, но fs:[0] послушно "слетает". без отладчика после слета fs:[0] вызывается SetUnhandledExceptionFilter.

    но это ерунда. тут натолкнулся на очевидный антиотладочный прием, с которым провозился добрые полчаса. конкретно туплю блин. сам трюк (после деобфускации) - push -1/popfd. ольга ес-но поглошает исключение при пошаговой трассировке и seh не вызывается.
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    kaspersky
    Не может Teb.Tib.ExceptionList ядром апгрейтиться, это однозначно. На счёт регистра флагов при входе в диспетчер - налаживается маска в KeContextToKframes/KeContextFromKframes, собственно для XPSP3 описано:
    Вероятно в отладчике какието баги, но точно не в ядре. По сути это всё дешёвые антиотладочные трюки, основанные на некоторых багаг в отладчиках, как например NtUnmapViewOfSection - изза нотификации ядром дебуггера, последний выполняет останов взводя TF, соответственно RGP при возврате из сервиса меняются.
     
  15. je_

    je_ New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    143
    так и будем втёмную гадать?
    выложи в аттаче фаил..
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    je_
    Скомпиль сам, в #6 дамп.
     
  17. je_

    je_ New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    143
    я обратился к kaspersky