Вопрос про асм (возврат функции - перехват).

Тема в разделе "WASM.NT.KERNEL", создана пользователем test555, 13 июл 2009.

  1. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Быть может вопрос в рубрику НОВИЧКИ, но т.к. драйвер, все же сюда напишу.

    Итак, веду перехват IoCreateFile в ядре.

    Схема:
    Переписываю первые 8 байт функции, FAR JUMP на свою naked функцию.
    Вид примерно такой (позаимствовал советы из ветки http://wasm.ru/forum/viewtopic.php?id=18923 ):


    Код (Text):
    1. __declspec(naked) new_IoCreateFile(
    2.     OUT PHANDLE             FileHandle,
    3.     IN ACCESS_MASK          DesiredAccess,
    4.     IN POBJECT_ATTRIBUTES   ObjectAttributes,
    5.     OUT PIO_STATUS_BLOCK    IoStatusBlock,
    6.     IN PLARGE_INTEGER       AllocationSize OPTIONAL,
    7.     IN ULONG                FileAttributes,
    8.     IN ULONG                ShareAccess,
    9.     IN ULONG                CreateDisposition,
    10.     IN ULONG                CreateOptions,
    11.     IN PVOID                EaBuffer OPTIONAL,
    12.     IN ULONG                EaLength,
    13.     IN CREATE_FILE_TYPE     CreateFileType,
    14.     IN PVOID                ExtraCreateParameters,
    15.     IN ULONG                Options)
    16. {
    17. UNICODE_STRING unic;
    18. BOOLEAN notfound;
    19. notfound=FALSE;
    20.  
    21. __asm
    22.     {
    23.         push ebp
    24.         mov ebp, esp
    25.         sub esp, 64 //make room for one local variable
    26.         pushad
    27.     }
    28.  
    29. RtlInitUnicodeString(&unic,  L"\\??\\C:\\file.txt");
    30.  
    31.  
    32. if (0==RtlCompareUnicodeString(ObjectAttributes->ObjectName, &unic, TRUE))
    33. {                              
    34. DPRINT("PID %ld IoCreate %S \n",PsGetCurrentProcessId() , ObjectAttributes->ObjectName->Buffer);
    35. // здесь мне надо возвратить в функцию STATUS_OBJECT_NAME_NOT_FOUND (типа чтобы файл не открылся)
    36. __asm {
    37.                 popad
    38.                 mov esp,ebp
    39.                 pop ebp                       // нужно ли это
    40.                 mov eax, 0xC0000034  // тут и не знаю что писать
    41.                 //leave
    42.                 ret
    43.                 }
    44.  
    45. }                                          
    46.    __asm
    47.     {
    48.         popad
    49.         mov esp,ebp
    50.         pop ebp
    51.     }
    52.  
    53.     __asm
    54.     {      
    55.         _emit 0x8b // выполнение оригинальных команд
    56.         _emit 0xff
    57.         _emit 0x55
    58.         _emit 0x8b
    59.         _emit 0xEC
    60.         _emit 0x83
    61.         _emit 0xEC
    62.         _emit 0x0C
    63.  
    64.         _emit 0xEA // джамп обратно на продолжение ориг. функции
    65.         _emit 0xAA
    66.         _emit 0xAA
    67.         _emit 0xAA
    68.         _emit 0xAA
    69.         _emit 0x08
    70.         _emit 0x00
    71.     }
    72. }
    Т.е. после джампа на мою функцию проверяется, что за файл октрывается и выводится на печать, потом выполняются исходные инструкции и идет обратно джамп на следующие после этих 8 байт команды оригинальной функции.

    Я не могу сделать так, чтобы при успешном сравнении возвращялось ошибочное значение и дальше функция не шла..
    Но не знаю как. Полистал справочник, статью "введение в машинный код" и другую литературу, но вот до такого момента не дошел..

    Вроде в eax записал код ошибки, ret написал.. Инструкцию leave DDK не поддерживает (пока не пробовал делать спец. вставку)..
    Если "возвратить" состояние стека, то виснет при открытии нужного файла.
    Или синий экран.

    А если без этого (то есть просто отладочная печать и продолжение выполнения ориг. функции) то прекрасно работает (пока без синих экранов)..

    И еще вопрос, если у меня описана переменная - ну например булевА, то допустим при вызове одной программы CreateFile дело дойдет до этого обработчика, переменной установится значение -1..
    Но перед тем как это значение будет использовано, другая программа успеет вызвать CreateFile и мой обработки запишет уже значение 0 в эту переменную, получится что в ту же самую переменную? И когда первая программа к ней обратиться, нарушиться логика программы? Правильно понимаю?

    Охотно почитаю документацию, но просто не знаю что искать и где...
     
  2. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Не делай этого, пока не поздно. Чуть больше информации здесь.
     
  3. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Я читал статью (вообще читаю твой блог), допустим что фильтровать файловую систему еще можно, но нужно перехватывать и другие функции... В этом то и беда..
    Например нужно защитить процесс от "убиения" - перехватом NtOpenProcess или NtTerminateProcess (в 95% этого хватит) и другие задачи..

    так я бы жил с простой заменой адреса в таблице, но некоторые функции "перебивает" касперский, т.к. программа вполне законна, проблема пока не в сокрытии, а в том что перехват ставят другие продукты.
     
  4. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Напиши любую, правильную, на твой взгляд концовку, скомпилируй, засунь в иду, посмотри на указатель стека напротив каждой комманды(Options->general->disassembly->stack pointer), прикинь как он меняется, чтобы его корректно восстановить потом. Если не заработает -- запусти под сисером, протрассируй функцию, смотри на стек: запомни адрес возврата, регистры, сохраненные pushad и т.д., конечно муторно, но имхо так лучше всего прочувствовать что же происходит на самом деле, после одного такого разбора, больше подобных проблем не возникнет =)
     
  5. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Никакой беды покамест не вижу. Для фильтрации файловой системы используй файловые фильтры, для остального другие методы. Ты же сам потом рад не будешь, тебе же самому потом реально переписывать с нуля всё придётся. Не в этом так в другом проекте. Поверь мне, когда твоя квалификация уже позволит тебе принимать архитектурные решения, ты будешь в ужасе от этого.

    А вот это от незнания всё. Таблица SDT уже давно ни кем не используется для application-based защиты объектов ядра. Вместо этого используй хуки на методы типов.

    Касперский перемещает таблицу, поэтому стандартным способом ты ничего в ней не похукаешь. Я плотно это дело не копал, но там вроде адрес её надо из ETHREAD'а брать. Знающие люди поправят, если что.
     
  6. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Velheart, благодарю за совет. Сижу за сисером, но на данную минуту знаний не достаточно чтобы сходу разобраться в даресах возврата, т.е. нужно сидеть, разбираться, читать доку. Так и буду.
    Просто хотел урвать моментальное решение. Ну ладно.

    X64, прислушиваюсь ко всем советам, и так понимаю что нужно переходить на фильтры, но опять таки знаний не хватает. Вот только недавно перечитал осознанно книгу "рутикиты. Внедрение в ядро".
    там и про фильтры есть, но мало информации.


    А про касперский я сужу просто: запускаем AZV, он показывает что перехват ведется драйвером касперского, если я устанавливаю - то моим, соотв. так же сбивается мой перехватчик.

    Дело то в том, что именно сейчас нужно уже кое что заканчивать, и это самый короткий способ в моем случае.. Со временем конечно нужно развиваться, дойду и до фильтров и прочего...


    Ну а сейчас мне прийдется погрузиться в сисер или IDA.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    test555
    С кодом обработчика проблем быть не должно, там всё тривиально.
    Нельзя использовать модификацию инструкций длиной меньше ветвления, если это не синхронизировано с остальными процессорами. Можно это делать в IPI либо заменять ветвление на IopCreateFile(атомарно смещение на свой обработчик). Но изменение кода это очень не желательный способ.