Сплайсинг в User-Mode на x86

Тема в разделе "WASM.WIN32", создана пользователем NDIS, 15 июл 2008.

  1. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Задача

    Перехватить определённые функции из определённых DLL (включая ntdll.dll и kernel32.dll).

    Условия

    - Архитектура x86.
    - Использовать метод подмены кода (сплайсинг).
    - Не использовать дизассемблер длин инструкций.
    - Поддержка Windows XP и Vista (любой Service Pack).

    Вопросы

    Возможно ли это?
    Если да, то как сие реализуется, какой принцип?

    Не предлагать

    - Изменение IAT / EAT.
    - Технологию Hot-Patching.
    - Остановку потоков и изменение EIP каждого.
    - Подмену обработчика исключений.

    Спасибо!
     
  2. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Собственно, сама техника сплайсинга далеко не нова и даже официально поддерживается Microsoft'ом - см. Detours. Если кто не в курсе, Microsoft предлагает следующий алгоритм перехвата API:

    1. Скопировать первые 5 байт перехватываемой (target) функции в начало т.н. функции-трамплина (trampoline).
    2. Дописать в конец (по смещению +5 от начала) функции-трамплина команду jmp near на код, находящийся по смещению +5 от начала перехватываемой функции.
    3. Записать в начало перехватываемой функции 5 байт команды jmp near на нашу функцию-перехватчик.
    4. Если нужно дёрнуть оригинальную функцию, сделать это командой call на функцию-трамплин.

    Этот алгоритм и кое-какая другая информация описана в этом документе в формате PDF. Ну вроде бы всё просто, но есть один момент, который мне не понятен. Данный способ перехвата будет прекрасно работать, если первые 5 байт целевой функции представляют собой целое число команд. Но в системных библиотеках мне попадался код, который не укладывается в 5 байт, например, вот такой:

    Код (Text):
    1. push ebp (1 байт)
    2. mov ebp, esp (2 байта)
    3. pop ebp (1 байт)
    4. jmp xxxxxxxx (5 байт)
    Соответственно, просто скопировать отсюда первые 5 байт не получится, т.к. вместе с последним байтом мы прихватим и кусочек команды jmp и по вышеприведённому алгоритму функция-трамплин выполняя команду jmp (пятый байт), "прыгнет" на левый код и приложение, скорее всего, банально упадёт. Проблема, думаю, понятна.

    Какое есть решение этой проблемы? Прежде всего, - дизассемблер длин инструкций, с помощью него мы получим длину минимально возможного кода, который можно вынести в функцию-трамплин, - в нашем случае это будет первые 9 байт. Но, к сожалению, по некоторым не зависящим от меня причинам дизассемблером длин инструкций я воспользоваться не могу, да и не нравится мне это решение. А других решений я, к стыду своему, не знаю.

    Кстати, не очень понятно, как сию проблему решает Detours, кто-нибудь в курсе? Вопрос остаётся открытым, как быть, господа?
     
  3. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Без дизасма длин код получится нестабильным.
    Прийдется тормозить потоки и восстанавливать из обработчика перебитые 5 байт.
    Потом опять ставить обработчик. На многоядерных тачках кодес периодически будет давать еррорс. Плюс, вам эта технология не подходит по условию.

    Статьи по поводу сплайсинга тоже давно написаны и откоментированы.
    раз
    два

    Технологии сто лет в обед.

    ЗЫ: в ntdll первые пять байт - это нопы и mov edi, edi
    специально сделано для сплайса
     
  4. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Это называется Hot-Patching, не подходит по условию (см. первый пост), т.к. не поддерживается в Windows XP < SP2.
     
  5. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    На данный момент пришёл к выводу, что без минимального примитивнейшего дизассемблера длин не получится. Но может быть кто-то знает другие варианты? Ведь Detours как-то решает проблему, описанную во втором посте, интересно узнать как?
     
  6. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    что мешает посмотреть под дизасмом, как реализован перехват??
     
  7. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Оказывается, Detours поставляется в исходниках всем желающим, хм, не знал. Заглянув туда, выяснил, что они таки используют дизассемблер длин + остановку потоков когда вешают хук, в общем-то это гарантированный вариант, хотя я надеялся, что существует более простое решение, но по-видимому нет, тем более что сам Microsoft делает так.

    Ну теперь, думаю, тему можно считать закрытой.
     
  8. dead_body

    dead_body wasm.ru

    Публикаций:
    0
    Регистрация:
    3 сен 2004
    Сообщения:
    603
    Адрес:
    Украина;г.Харьков;г.Н.Каховка
    NDIS
    иногда потоки можно не останавливать для ntdll, если делать перехват в таком коде:dntknw:пишу по памяти - не помню)
    mov eax,??
    mov edx,address_xz
    call edx

    так тут просто меняем команду mov edx,xxxx
    где устанавливаем адрес своего кода.

    тогда можно не тормозить потоки. (У меня в Висте svchost.exe зависал когда я его тормозил и запускал опять, какой то глюк был)
     
  9. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    если по честному - то нужно останавливать и потом запускать только активные в данный момент потоки, а не все.
    Иначе взаимная блокировка происходит в висте и зависание
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    атомарность на 8/16 байт сгодится?
     
  11. 2FED

    2FED New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    1.002
    asmfan это как?
     
  12. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Допустим. Хочешь что-то предложить?
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    2FED
    Это lock cmpxchg8b и cmpxchg16b.
     
  14. 2FED

    2FED New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    1.002
    Первый раз слышу про cmpxchg16b, и masm отказывается её транслировать.
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    2FED
    Ну и чё ?
     
  16. 2FED

    2FED New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    1.002
    Ни чего, хотелосьбы узанать как её в масме заюзать.
    и ещё хотелось бы узнать с каких процессоров она поддерживается
     
  17. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    asmfan
    Атомарно-то оно может и атомарно, но это не спасёт же, если другой поток в данный момент остановлен, скажем, на втором байте функции.

    2FED
    Скачал бы интелловские мануалы (vol2A & vol2B) уже ;)
    cmpxchg16b - x64.
     
  18. NDIS

    NDIS NDIS

    Публикаций:
    0
    Регистрация:
    16 авг 2007
    Сообщения:
    41
    Адрес:
    Москва
    Данная проблема решается единственно возможным способом - проверкой контекстов приостановленных потоков и возврат их EIP на начало целевой функции. А вообще, по этому поводу, думаю, стоит внимательнее глянуть в исходники Detours'а.
     
  19. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    push ebp
    mov ebp,esp
    ....<- тут остановился поток.

    попробуй верни управление на начало. Имхо, проще подождать, пока он уйдёт оттуда, или если уж совсем не терьпится eip переставить на ту-же самую команду, но уже в том месте, куда скопировали начало ф-ии.
     
  20. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Сделать откат инструкций, для этого стандартного пролога это еще возможно:) (просто сымитировать pop ebp)
    Ну а вообще проще, конечно, переставить EIP в трамплин-буффер в ту же самую команду.