Очередные глюки fasm'а(команда int 3) ?

Тема в разделе "WASM.ASSEMBLER", создана пользователем Asterix, 15 авг 2004.

  1. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Интересно как fasm кодирует int 3, вот:
    Код (Text):
    1. CD 03          INT 3




    т.е. db 0xCD,0x03 вместо 0xCC



    почему так?
     
  2. ProgramMan

    ProgramMan New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2004
    Сообщения:
    263
    Opcode Instruction Description

    CC INT 3 Interrupt 3—trap to debugger.

    CD ib INT imm8 Interrupt vector number specified by immediate byte.

    CE INTO Interrupt 4—if overflow flag is 1.



    Так что CCh это оптимизированный вариант CDh,03h и нет тут никакого глюка.



    RTFM!
     
  3. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    ProgramMan

    Я и не сомневался в правильности опкода, я имел ввиду почему так не оптимально, два байта вместо одного..
     
  4. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    FASM позволяет использовать оба варианта. 2й пишется так:

    int3
     
  5. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    S_T_A_S_

    > FASM позволяет использовать оба варианта. 2й пишется так:

    int3




    Даже не мог такое предположить %)
     
  6. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Упс... Не надо юзать CD 03. Винда этого не понимает.



    Почти год назад мы обсуждали в группе какой-то екзешник by DAEMON, который якобы детектил айс использую как раз этот вариант инт 3. Сам екзешник у мя не сохранился. Остались тока два моих поста. Из них, в принципе всё понятно.







    Vladimir> Ну какой из голого int 3 антиотладочный прием? Да никакого!

    Vladimir> Ведь что пнем по сове, что сову об пень - будет код возврата

    Vladimir> STATUS_BREAKPOINT и усе!



    Во-первых, предыдущую мою мессагу с кодом NtIceDetect читали?



    Во-вторых, я еще маленько покопал Демоновский detect NTIce.EXE и ...

    Я уже говорил, что он никакого айса не детектит и детектить не может -

    он просто в любом случае показывает 'NTICE FOUND by ^DAEMON^!' и вот

    почему...



    SEH обработчиком у него является 00401005, который тупо прибавляет к

    текущему eip в структуре CONTEXT 4 и возвращает

    ExceptionContinueExecution.



    Сначала он вбрасывает int3. Обратите внимание на опкод CD 03 !!!


    Код (Text):
    1. :00401028 CD 03               int     3
    2. :0040102A EB 12               jmp     short loc_40103E
    3. :0040102C                   ; -----------------------------------------------------------
    4. :0040102C EB 20               jmp     short loc_40104E
    5. :0040102E                   ; -----------------------------------------------------------
    6. :0040102E 6A 00               push    0
    7. :00401030 68 00 20 40 00      push    offset aHello   ; "Hello!"
    8. :00401035 68 40 20 40 00      push    offset aNticeFoundByDa ; "NTICE FOUND by ^DAEMON^!"
    9. :0040103A 6A 00               push    0




    Прикол в том, что в обработчике SEH в CONTEXT.regEip мы должны

    получить 00401028 (и если бы опкод был 0CCh, то так и было бы, что

    кстати тоже не верно, но об этом позже). Но мы получаем 00401029 !!!

    Т.е. толи у камня, то ли у системы едет крыша, то ли я чего-то не

    понимаю.



    Демоновский SEH обработчик прибавляет 4 и получается 0040102D - это

    середина команды jmp loc_40104E. Туда возвращается управление и мы

    получаем новое исключение и опять попадаем в SEH-обработчик.

    CONTEXT.regEip = 0040102D. Опять прибавляем 4 и получаем 00401031, а

    это середина push offset aHello. Туда возвращается управление и мы

    получаем новое исключение :derisive: и опять попадаем в SEH-обработчик.

    CONTEXT.regEip = 00401031 + 4 = 00401035. Наконец-то мы получили

    валидный адрес и попадаем туда.



    Пихаем в стек offset aNticeFoundByDa и 0 и вызываем MessageBoxA. Он

    снимает со стека, как и полагается, 4 DWORD'а: наши 0 и offset

    aNticeFoundByDa и, по счастливой случайности, следующим в стеке сидит

    0012FFE0 - MessageBoxA считает, что это адрес строки заголовка (по

    этому адресу некая последовательность байт превращающаяся в строку

    'яяяя[aиw}йw', которую мы и видим в заголовке), и наконец в качестве

    4 параметра MessageBoxA снимает со стека 00401005, интерпритирует 5

    как MB_RETRYCANCEL - именно поэтому MessageBoxA появляется с двумя

    кнопками :derisive: - и показывает нам "NTICE FOUND by ^DAEMON^!". Причем

    покажет он это в любом случае :derisive: и никакой детекции айса тут нет.



    А все потому, что вместо int3 надо влепить int1 (CD 01). Поменяйте 03

    на 01 и увидите, что все заработало как надо.



    А теперь два вопроса!

    1. Почему наткнувшись на CD 03 система передает в SEH адрес 00401029,

    указывающий в середину инструкции?

    2. Даже если вместо CD 03 влепить СС система передаст в SEH адрес

    самого int3. Но ведь int3 это не fault, а trap и адрес должен указывать на

    следующую инструкцию. Какого ж хрена он кажет на саму int3, как будто

    это трап?





    В аттаче еще маленько упрощенный пример детекции на int1.



    -----------------------

    Four-F











    Four-F> А теперь два вопроса!

    Four-F> 1. Почему наткнувшись на CD 03 система передает в SEH адрес 00401029,

    Four-F> указывающий в середину инструкции?

    Four-F> 2. Даже если вместо CD 03 влепить СС система передаст в SEH адрес

    Four-F> самого int3. Но ведь int3 это не fault, а trap и адрес должен указывать на

    Four-F> следующую инструкцию. Какого ж хрена он кажет на саму int3, как будто

    Four-F> это трап?



    Чтобы дальнейшие объяснения были более понятны, выпомните, что когда

    процессор натыкается на int3 генерится исключение типа Trap (ловушка).

    А если ловушка, то камень передаст обработчику этого исключения адрес

    инструкции следующей сразу за int3.



    Int3 существует в двух вариантах: с опкодом СС, к которому мы все

    привыкли и с опкодом CD03. Обратите внимание, один байт и два байта.

    При натыкании на любой из этих опкодов, камень генерит исключение, и

    передает обработчику: в случае CC адрес на один больший чем адрес CC,

    в случае CD03 адрес на два больший чем адрес CD03. Здесь все четко.

    Камень свои опкоды знает и ошибиться не может.





    Теперь сам спросил, сам отвечу.



    Ответ 1: Потому, что обработчик _KiTrap03 никак не ожидает int3 с

    опкодом CD03. Он считает что int3 имеет только только опкод CC.



    Ответ 2: Потому, что обработчик _KiTrap03 уменьшает адрес переданный

    камнем на 1. Причем делает он это в любом случае. Для СС это будет

    указатель на него самого, как будто это не Trap, а Fault. Для CD03

    будет большая лажа :derisive: Адрес переданный камнем будет уменьшен на 1 и

    будет указывать в середину int3 с опкодом CD03.





    Во втором мануале от интела "Instruction Set Reference" находим такую

    фразу:



    "Note that the “normal” 2-byte opcode for INT 3 (CD03) does not have

    these special features. Intel and Microsoft assemblers will not

    generate the CD03 opcode from any mnemonic, but this opcode can be

    created by direct numeric code definition or by self-modifying code."



    Т.е. M$ вообще не предполагает обработку int3 с опкодом CD03, а только

    с опкодом CC! Демоновский код был скомпилен не masm, поэтому в

    обработчике SEH мы имеем eip указывающий в середину инструкции int3 с

    опкодом CD03.





    Вот куски из ntoskrnl.exe от w2k+sp2 (от ХР я тоже глянул - там все то

    же самое).


    Код (Text):
    1. :00465D6E _KiTrap03:
    2. . . .
    3. :00465DEC loc_465DEC:
    4. :00465DEC       mov esi, ecx
    5. :00465DEE       mov edi, edx
    6. :00465DF0       mov edx, eax
    7. :00465DF2       mov ebx, [ebp+KTRAP_FRAME.Eip]
    8. :00465DF5       dec ebx                          ; <- !!! eip = eip-1
    9. :00465DF6       mov ecx, 3
    10. :00465DFB       mov eax, STATUS_BREAKPOINT
    11. :00465E00       call CommonDispatchException
    12.  
    13.  
    14. :004301B0 _KiDispatchException@20 proc near
    15. . . .
    16. :00430216 loc_430216:
    17. :00430216       lea eax, [ebp+var_38C]
    18. :0043021C       push eax
    19. :0043021D       push [ebp+arg_4]
    20. :00430220       mov esi, [ebp+TrapFrame]             ; PKTRAP_FRAME
    21. :00430223       push esi
    22. :00430224       call _KeContextFromKframes@12
    23. :00430229       mov edi, [ebp+exr]                   ; PEXCEPTION_RECORD
    24. :0043022C       cmp [edi+EXCEPTION_RECORD.ExceptionCode], STATUS_BREAKPOINT
    25. :00430232       jnz short loc_43023A
    26. :00430234       dec [ebp+Eip]                        ; <- !!! eip = eip-1




    Если EXCEPTION_RECORD.ExceptionCode == STATUS_BREAKPOINT, то просто

    [ebp+Eip] - это CONTEXT.Eip - уменьшается на 1 (В строке 00430234).



    Гы-гы-гы.



    -----------------------

    Four-F
     
  7. ProgramMan

    ProgramMan New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2004
    Сообщения:
    263
    Four-F

    Уменя Win2K+SP2+ SoftICE нормально обрабатывает инструкцию CD 03

    Asterix Извени, видимо я не понял тебя.
     
  8. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    ProgramMan, тебе, похоже, попался какой-то custom build винды ;) См. аттач.



    [​IMG] _916680702__CD03Trouble.rar