Перехват API функций в Windows NT (статьи)

Тема в разделе "WASM.WIN32", создана пользователем Ms Rem, 30 апр 2005.

  1. Asterix

    Asterix New Member

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



    Спасибо за статьи.

    Получилось 422Kb в chm :)







    Для истинного Воина дзена не важно на каком языке написаны

    исходники :derisive:
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    IceStudent

    Что-то для меня они тоже не доступны.



    Asterix

    Может кинешь .chm на мыл, если трафика не очень жаль: igwasm@mail.ru.

    А то уж больно любопытно стало.
     
  3. Asterix

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    Asterix New Member

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

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    скажу и я свое фи ;)

    в принципе написано интересно, еще одно описание стандартной и наиболее распространенной техники перехвата (это я про ядро)... неплохое чтиво. за труды автору респект!



    зыж еще было бы большим плюсом написать минусы того способа который ты описал и добавить когда и где эта техника не будет работать...
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    2Ms Rem

    Посмотрел, добротная весчь. Дзен одним

    словом.



    2Asterix

    Отдельное сенькс.
     
  14. PavPS

    PavPS New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2004
    Сообщения:
    109
    Адрес:
    Russia
    Статья супер. Прочитал сразу же. Особо интересно было про CallGate. Вообще, этот мотериал обязательно должен быть у каждого. Примеры тоже классные. Просто супер!
     
  15. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Ложечка дёгтя по третьей части (первые две не читал).



    > На уровне ядра мы также имеем аналогичные пары функций, но между

    > ними имеется одно различие, функции с префиксом Nt производят перед

    > выполнением действия проверки системы безопасности (прав

    > пользователя), а функции с префиксом Zw - нет. Из пользовательского

    > режима через интерфейс системных вызовов нам доступны Nt функции, а

    > после проверки безопасности они вызывают соответствующие Zw функции.

    > Драйвера же часто обращаются к Zw функциям напрямую, поэтому какие

    > функции перехватывать, а также метод перехвата определяются тем,

    > следует ли контролировать вызов API функций ядром или нет.



    Вообще говоря, всё наоборот. Zw - это шлюз в ядро через int2e/sysenter,

    а Nt вызываются обработчиком KiSystemService.





    > Также следует обратить внимание на то, что перед изменением

    > содержимого SST производится запрет прерываний и очистка WP бита в

    > регистре CR0. Запрет прерываний необходим по причине того, что наш

    > поток может быть прерван в момент записи в SST, и в это время другой

    > поток обратится к перехватываемой функции, что приведет к падению

    > системы.



    На мультипроцессорных машинах это не покатит.






    Код (Text):
    1. > st = IoCreateDevice(DriverObject,
    2. >                     256,             // максимальный размер принимаемых данных
    3. >                     &DeviceName,
    4. >                     FILE_DEVICE_NULL,
    5. >                     METHOD_NEITHER,  // метод буферизации
    6. >                     ...


    Второй параметр, равный 256, определяет размер дополнительной области

    памяти (device extension), цепляемой к создаваемому объекту

    "устройство" и не имеет никакого отношения к "максимальному размеру

    принимаемых данных". Ни в одном из драйверов в архиве к статье device

    extension не используется. Поэтому во втором параметре следует

    передать 0.



    Пятый параметр, равный METHOD_NEITHER тоже не имеет никакого отношения

    к методу буферизации. На самом деле в нем передаются характеристики

    девайса, такие как: FILE_DEVICE_SECURE_OPEN,

    FILE_CHARACTERISTIC_PNP_DEVICE и т.п. Константа METHOD_NEITHER = 3,

    поэтому этот код на самом деле выглядит так:


    Код (Text):
    1. st = IoCreateDevice(DriverObject,
    2.                     256,
    3.                     &DeviceName,
    4.                     FILE_DEVICE_NULL,
    5.                     FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE,
    6.                     ...


    Метод же буферизации (для функций ReadFile, WriteFile) можно

    установить после создания девайса так:


    Код (Text):
    1. pDeviceObject->Flags |= DO_BUFFERED_IO;    //  буферизованный
    2. pDeviceObject->Flags |= DO_DIRECT_IO;      //  или прямой


    Если ни DO_BUFFERED_IO, ни DO_DIRECT_IO нет в поле Flags, то

    используется метод neither, и только поэтому код работает правильно.





    > if (st == STATUS_SUCCESS)



    В случае с IoCreateDevice это не будет иметь значения, но везде,

    вместо прямого сравнения с STATUS_SUCCESS лучше использовать

    if ( NT_SUCCESS(st) ), т.к. некоторые другие функции могут вернуть код

    успеха, отличный от STATUS_SUCCESS.





    > ppdd [IRP_MJ_CREATE] =



    Нет обработчика для IRP_MJ_CLOSE, а значит будет вызвана

    IopInvalidDeviceRequest, которая вернет ошибку и CloseHandle на

    стороне режима пользователя, соответственно завершится неудачно, хотя

    хендл на самом деле уже закрыт.





    > Но есть также возможность загружать драйвер при старте системы, для

    > этого нужно установить драйвер через SCM...



    Совсем необязательно. Точно так же можно использовать функции для

    работы с реестром и просто прописАть в параметр Start соответствующее

    значение.





    > Status = ObOpenObjectByName(..., 0x80000000, ...);



    0x80000000 = GENERIC_READ





    > Также следует обратить внимание на то, что перед копированием

    > делается попытка закрепить копируемые страницы в памяти,



    С помощью функции VirtualLock невозможно "закрепить страницы в

    памяти", в том смысле, который подразумевается в статье. Для страниц в

    пространстве ядра, VirtualLock вообще ничего делать не будет, а для

    пользовательских страниц она закрепит их не в памяти, в рабочем наборе

    процесса. Это значит что диспетчер памяти будет пытаться держать эти

    страницы в памяти , если это возможно, т.е. все страницы в

    пользоветельских процессах могут быть выгружены, но для закрепленных в

    рабочем наборе это будет сделано в последнюю очередь.





    > Для получения списка всех процессов в системе нам нужно получить

    > указатель на EPROCESS любого процесса, после чего двигаться по

    > спискам ActiveProcessesLink до тех пор, пока не окажемся на той

    > структуре, с которой начали.



    При этом нужно учесть, что PsActiveProcessHead (на картинке она

    ошибочно названа PsActiveProcessLink), которая обязательно

    встретиться при таком обходе не является структурой EPROCESS.

    Кстати, указатель на процесс system можно получить, использовав

    PsInitialSystemProcess, в любом контексте. И поле ActiveProcessLinks

    ошибочно названо ActiveProcessLink.





    > Повышение приоритета потока исключает такую возможность, так как

    > удаление процессов выполняется потоком режима ядра с приоритетом

    > Normal.



    Наверное, на однопроцессорной машине это будет работать, хотя чисто

    теоритически только повышает шансы на успех, но ничего не гарантирует.





    > SE_AUDIT_CREATION_INFO



    SE_AUDIT_PROCESS_CREATION_INFO







    В драйвере ProtectProcess функция TrueNtOpenProcess вызывает

    NtOpenProcess в обрамлении cli/sti. NtOpenProcess - очень сложная

    функция и звать её выключив прерывания - самоубийство. К тому же

    TrueNtOpenProcess каждый раз перед вызовом оригинальной NtOpenProcess

    восстанавливает её точку входа, а после вызова опять хучит! Я не

    большой специалист в API-хуках, но, IMHO, это делается с помощью

    дизассемблера длин инструкций: код точки входа переносится в другое

    место и за ним помещается переход на остаток функции.





    > if ((ULONG)ClientId > 0x80000000) return STATUS_INVALID_PARAMETER;



    Тут я присоединюсь к 90210. Вместо 0x80000000 следует использовать

    MmHighestUserAddress.
     
  16. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    >Вообще говоря, всё наоборот. Zw - это шлюз в ядро через >int2e/sysenter,

    >а Nt вызываются обработчиком KiSystemService.



    опечатка вышла.



    >Совсем необязательно. Точно так же можно использовать >функции для

    >работы с реестром и просто прописАть в параметр Start >соответствующее значение.



    Я вроде бы рассмотрел метод установки драйвера путем ручного создания в реестре соответствующих ключей.



    > С помощью функции VirtualLock невозможно "закрепить >страницы в

    >памяти", в том смысле, который подразумевается в статье. >Для страниц в

    >пространстве ядра, VirtualLock вообще ничего делать не >будет, а для

    >пользовательских страниц она закрепит их не в памяти, в >рабочем наборе

    >процесса. Это значит что диспетчер памяти будет пытаться >держать эти

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



    я не хочу сказать, что в любом случае страницы памяти будут закреплены, закрепить в физической памяти можно с помощью ZwLockVirtualMemory и то, только при включенной соответствующей привилегии. При использовании драйвера для исполнения кода в нулевом кольце, VirtualLock и VirtualUnlock можно убрать, но при использовании каллгейта они повышают стабильность. (вообще, при использовании каллгейта эта функция весьма часто может вызывать BSOD)



    >Наверное, на однопроцессорной машине это будет работать, >хотя чисто

    >теоритически только повышает шансы на успех, но ничего >не гарантирует.



    Повысить шансы на успех иногда тоже полезно :)





    >В драйвере ProtectProcess функция TrueNtOpenProcess >вызывает

    >NtOpenProcess в обрамлении cli/sti. NtOpenProcess - >очень сложная

    >функция и звать её выключив прерывания - самоубийство. К >тому же

    >TrueNtOpenProcess каждый раз перед вызовом оригинальной >NtOpenProcess

    >восстанавливает её точку входа, а после вызова опять >хучит! Я не

    >большой специалист в API-хуках, но, IMHO, это делается с >помощью

    >дизассемблера длин инструкций: код точки входа >переносится в другое

    >место и за ним помещается переход на остаток функции.



    метод перехвата API с помощью дизассемблера длин инструкций описан во 2 статье, а здесь даны были только ПРОСТЕЙШИЕ примеры требующие минимальное количество кода.



    >Тут я присоединюсь к 90210. Вместо 0x80000000 следует >использовать

    >MmHighestUserAddress.



    Об этом уже говорили, в статью будут внесены изменения.
     
  17. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ Ms Rem</font><!--color--><font color="gray]: Я вроде бы рассмотрел метод установки драйвера путем ручного создания в реестре соответствующих ключей. ]</font><!--color-->



    Верно. И сразу же идёт фраза: "Но есть также возможность загружать драйвер при старте системы, для этого нужно установить драйвер через SCM и указать тип загрузки не SERVICE_DEMAND_START, а SERVICE_AUTO_START, SERVICE_SYSTEM_START или SERVICE_BOOT_START." Я поэтому и обращаю твоё внимание на то, что SCM тут использовать совсем не обязательно, т.е. "возможность загружать драйвер при старте системы" не зависит от (не)использования SCM.





    <font color="gray][ Ms Rem</font><!--color--><font color="gray]: я не хочу сказать, что в любом случае страницы памяти будут закреплены, закрепить в физической памяти можно с помощью ZwLockVirtualMemory и то, только при включенной соответствующей привилегии. При использовании драйвера для исполнения кода в нулевом кольце, VirtualLock и VirtualUnlock можно убрать, но при использовании каллгейта они повышают стабильность. (вообще, при использовании каллгейта эта функция весьма часто может вызывать BSOD) ]</font><!--color-->



    Согласен, ты говоришь: "делается попытка". ZwLockVirtualMemory/NtLockVirtualMemory/VirtualLock суть одно и то же. Насчет стабильности, согласен, но как то это...





    <font color="gray][ Ms Rem</font><!--color--><font color="gray]: метод перехвата API с помощью дизассемблера длин инструкций описан во 2 статье, а здесь даны были только ПРОСТЕЙШИЕ примеры требующие минимальное количество кода. ]</font><!--color-->



    Понял. Вторую часть я не читал. Возможно, я окажусь не единственным, а момент этот важный. Я бы добавил пару слов.
     
  18. Edmond

    Edmond узник замка IF THEN ELSE

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    203
    Адрес:
    WASM.RU




    Ужас то какой! Надо исправить дело!!!
     
  19. Edmond

    Edmond узник замка IF THEN ELSE

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    203
    Адрес:
    WASM.RU
    Ms Rem



    Я так понял можно вылажить именно те статьи которые приатачены прямо тут?



    Или будут изменения?



    Если что - шлите лучше на edmond + wasm.ru
     
  20. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    >Согласен, ты говоришь: "делается попытка". >ZwLockVirtualMemory/NtLockVirtualMemory/VirtualLock суть >одно и то же. Насчет стабильности, согласен, но как то >это...



    Одно и то же, но ZwLockVirtualMemory позволяет указать где закреплять страницы, в рабочем наборе, или в физ. памяти.


    Код (Text):
    1. NTSYSAPI
    2. NTSTATUS
    3. NTAPI
    4. ZwLockVirtualMemory(
    5. IN HANDLE ProcessHandle,
    6. IN OUT PVOID *BaseAddress,
    7. IN OUT PULONG LockSize,
    8. IN ULONG LockType
    9. );




    LockType

    A set of flags that describes the type of locking to be performed for the specified

    region of pages.The permitted values are combinations of the flags:

    LOCK_VM_IN_WSL 0x01 // Lock page in working set list

    LOCK_VM_IN_RAM 0x02 // Lock page in physical memory