SSE эмулятор

Тема в разделе "WASM.NT.KERNEL", создана пользователем cppasm, 17 мар 2008.

  1. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Да, все нормально
     
  2. Joes

    Joes New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2008
    Сообщения:
    98
    SetUnhandledExceptionFilter не совсем то что тебе надо :)
    KiUserExceptionDispatcher - то.
    Смотри почему.

    Вариант с SetUnhandledExceptionFilter:
    1. Система по очереди вызывает SEH хендлеры
    2. Если ни один не обработал exception, вызывает твой хендлер переданный в SetUnhandledExceptionFilter
    Теперь предположим что программисты программы таки сделали проверку на разные типы exception'ов в своем SEH обработчике и при exception покажут окошко - мол, извините, мы упали. Твой handler так и не получит управления.

    KiUserExceptionDispatcher как раз и есть та самая функция, которая вызывает SEH handler'ы и если ни один не обработал exception - вызывает Unhandled exception handler. Т.е. она первая из всех, кто получает инфу о exception.

    Что до THREAD_DETACH - ага, если поток завершился (TerminateThread или просто вышли).
    Закрытие процесса закрывает все нитки.

    Edit: Кстати, хранение данных в потоке я бы делал с TlsGetValue()/TlsSetValue(). В смысле в куче выделял бы памяти и с помощью TlsSetValue() сохранял бы указатель на нее. Потом, когда надо - с TlsGetValue() читал бы и работал. Никаких блокировок, ляпота. Как вариант, в принципе. Можно и руками разрулить.
     
  3. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Как я понял для KiUserExceptionDispatcher нет функции типа SetUserExceptionDispatcher, надо хукать...
    Сейчас буду разбираться.
    С TLS мне не всё нравится, я вообще бумал свой список делать.
    Просто получается такая картина:
    1.если со списком
    PROCESS_ATTACH: добавляю в список структуру с регистрами
    THREAD_ATTACH: добавляю в список структуру с регистрами
    THREAD_ATTACH: добавляю в список структуру с регистрами
    THREAD_ATTACH: добавляю в список структуру с регистрами
    THREAD_DETACH: удаляю из списка структуру с регистрами
    PROCESS_DETACH: удаляю весь список

    2. если с TLS
    PROCESS_ATTACH: добавляю в TLS адрес структуры с регистрами
    THREAD_ATTACH: добавляю в TLS адрес структуры с регистрами
    THREAD_ATTACH: добавляю в TLS адрес структуры с регистрами
    THREAD_ATTACH: добавляю в TLS адрес структуры с регистрами
    THREAD_DETACH: удаляю из TLS адрес структуры с регистрами
    PROCESS_DETACH: удаляю из TLS адрес структуры с регистрами
    Я не могу удалить весь список - не знаю адресов, а THREAD_DETACH вызвалось не для всех потоков.
    Выходят утечки памяти.
    Хотя при закрытии процесса оно конечно всё равно, но не красиво...
     
  4. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Блин, есть где-нибудь нормальный пример как хукнуть функцию из ntdll? Куча вопросов.
    Сплайсинг не подходит - мне надо будет вызывать оригинальзую функцию если исключение не моё.
    А пока я восстановлю оригинальное начало функции до того момента как я восстановлю хук если произойдёт переключение потоков то исключение я не поймаю...
     
  5. JamesB

    JamesB New Member

    Публикаций:
    0
    Регистрация:
    3 фев 2008
    Сообщения:
    66
    Ээ. Сплайсить можно (и нужно обязательно) так, чтоб сохранялись старые байты и вызов старой функции - это выполнение сохраненных инструкций + джамп на оригинальный_адрес+размер_сохраненных_инструкций. Сплайс получается безопасным и ничего перезаписывать не надо будет никогда.
    Или я не понимаю что-то?)
     
  6. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    cppasm
    читай MsRem на сайте
     
  7. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    И как ты предлагаеш мне сохранить с начала функции целое количество инструкций?
    Дизассемблер длин туда ещё засунуть?
    Если я сохраню 5 байт с начала функции, туда всуну свой джамп, потом мне надо вызывать оригинальную функцию.
    Я НЕ могу выполнить SavedBytes+jmp (HookedFunc+sizeof(SavedBytes)) потому что в буфер я мог скопировать только кусок последней команды.
    И даже если я скопировал целиком - а если там относительный jmp или call?
    При выполнении на новом месте управление будет передано в далёкий туман...
    Делать надо как-то так:
    Код (Text):
    1. Save5Bytes();
    2. PatchJmpToMyFunc();
    А в моей функции что-то в духе:
    Код (Text):
    1. MyFunc()
    2.  {
    3.    // Do something useful...
    4.  
    5.    RestoreSavedBytes();
    6.    call OriginalFunction();
    7.    PatchJmpToMyFunc();
    8.  }
    И тут важно чтобы между RestoreSavedBytes() и PatchJmpToMyFunc() не произошло переключение потоков, а то в этот момент хук не установлен.
    Да его и прочитал, не очень понятно. Переводить все потоки в Suspend что-то не охота.
    Может кроме сплайса есть другой метод перехвата без создания потоков и т.д.?
     
  8. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    А ты хочешь писать эмулятор SSE без дизассемблерного движка?.. :)
     
  9. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Нет, я хочу писать эмулятор SSE с дизассемблером исключительно SSE, а не обобщённым.
    Там всё очень упрощается - например недопустим префикс 66h и т.д.
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    cppasm
    Сплайс
    - Ищем дизассемблером длин в нужной функции достаточно длинную инструкцию/команду, чтобы целиком внутри поместить код перенаправления потока
    - lock cmpxchg8b/cmpxchg16b (при этом заменив в (r)ecx:dntknw:r)ebx только те байты от исходных, которые сплайсим, которые необходимо, т.е. напр. 6 из 8, то остальные 2 оставляем исходными т.к. могут относиться к другой инструкции, исполняющейся в др. потоке. Иначе -> BSOD)
    Усё.
     
  11. Joes

    Joes New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2008
    Сообщения:
    98
    Гм, ничего сложного в сплайсе нет.
    1. Берешь дизассемблер длин, их сейчас куча. Пример - ADE32, LDE, etc.
    2. Кормишь дизассемблеру начало функции в ntdll. Оно говорит тебе размер комманды.
    3. Увеличиваешь указатель на размер предидущей комманды и повторяешь пункты 2-3 до тех пор пока не наберется 5 или 6 байт (6 если ты хочешь push/ret)
    4. Копируешь начало функции с получившейся длиной в свой локальный буффер.
    5. В локальный буффер дописываешь JMP или тот же PUSH/RET на продолжние оригинальной функции
    6. На место оригинальной функции пишешь JMP на твой обработчик. Вот и все.

    Когда надо дергнуть оригинал - вызываешь свой буффер как обычную функцию.
     
  12. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Не считая того что надо дизассемблер длин применять, меня смущает такой вариант.
    Что если в начале функции (тот код который будем копировать) будет относительный переход.
    При выполнении этого кода по другим адресам (в моём буфере) результат будет печальный.
     
  13. Joes

    Joes New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2008
    Сообщения:
    98
    Ага, и проверку на jmp/call. В ADE32 оно флажок ADE_REL (или как там его) вернет.
    Но в конкретно нужной тебе функции точно не будет прыжка.
    Кстати, если не хочется возиться с дизассемблером длин - просто выкуси в свой буффер начало нужной функции.
    Потом когда будешь патчить - сравнивай. Совпало - пиши смело JMP.
    Непереносимо, но для старта и так сойдет.
     
  14. Novi4ek

    Novi4ek New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    317
    Мм.. Я новичок, наверно не понимаю чего - но нельзя ли дизассемблировать программу и в ней заменить все SSE инструкции вызовами функций, которые будут добавлены в эту программу, а потом ее ассемблировать заново? В этом случае теряется геморрой с подгоном длин команд, как это было бы при патчинге готового бинарника.
     
  15. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Novi4ek
    ты типа предлогаеш в ней таскать дизасм и ассемблер.
    Пожалуйста только в KERNELMODE не делай таких подсказок.
    В BEGINERS твори что хочеш :)
     
  16. Novi4ek

    Novi4ek New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    317
    Ассемблер и дизассемблер такие тяжелые программы? По сути в их таскании, как мне представляется, и заключается решение задачи, добавить нужные функции и заменить инструкции - это совсем нетрудно. И KERNELMODE в таком случае не понадобится. Только я не уловил - увеличение размера программы на несколько килобайт это единственный аргумент против такого подхода?..

    Кроме того это простейший способ решения задачи (если конечно нет каких-то сопряженных с этим проблем, которые мне не очевидны) на коленке, т.к. не совсем ясно для массового ли потребителя без SSE или исключительно для себя автор хотел запустить этот продукт. Если второй вариант то по-моему нет ничего проще моего решения. Или я ошибаюсь?..
     
  17. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Novi4ek
    Автор хочет сделать эмулятор для всех страждующих...
    Писать дизасм и асм для этого смысла нет.
    Вы когда-нибудь в дизасме нарывались на битый код?
    И что дизасм должен делать? Мож ещё эмулятор прикрутить?
    Пусть автор пишет как писал :)
     
  18. Novi4ek

    Novi4ek New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    317
    Да. Метод не универсальный, согласен
     
  19. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    На текущий момент использую UnhandledExceptionFilter, для данной конкретной программы подходит.
    Если понадобится, можно заменить и на VEH, и на KiUserExceptionDispatcher.
    Там по сути две строки заменить.
    Novi4ek - не говоря о Adobe Bridge, просто попробуй ничего не изменяя взять мега сложную программу notepad.exe, её дизассемблировать и потом пересобрать.
    И ты поймёш что это гиблое дело по сути.
    Ни один дизассемблер (в том числе и IDA) не выдаст тебе листинг который сразу можно пересобрать.

    Тут возник вопрос по опкодам, а точнее по lock префиксу.
    Есть к примеру команда lock movss xmm0,[mem_addr]
    Вопрос - на процессорах без SSE UD# будет на lock, или на movss??
    Или на разных процессорах может быть по-разному?
     
  20. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    имхо, на movss
    а вообще, я думаю, в этом случае поведение implementation-specific