Проблема с переопределением функции ZwCreateProcess.

Тема в разделе "WASM.NT.KERNEL", создана пользователем lev, 11 июн 2007.

  1. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Подскажите почему драйвер перестает загружаться если начинаешь записывать в SST ядра адреса своих функций.
    В приведенном ниже коде если заремарить строчку «NTCALL(48) = CreateProcess;»
    То драйвер начинает нормально загружаться.

    Код (Text):
    1. typedef NTSTATUS (NTAPI *NTPROC)();
    2. typedef NTPROC *PNTPROC;
    3. #define NTCALL(_function) KeServiceDescriptorTable->NtoskrnlTable.ServiceTable[_function]
    4.  
    5. PDEVICE_EXTENSION   pDeviceExtension = NULL;
    6. NTPROC              ntproc = NULL;
    7.  
    8. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
    9.     PDEVICE_OBJECT      DeviceObject = NULL;
    10.     NTSTATUS            Status;
    11.     UNICODE_STRING      uStr;
    12.     ULONG               CR0Reg;
    13.     pDeviceExtension    = NULL;
    14.     ntproc              = NULL;
    15.     ntprocEx            = NULL;
    16.     RtlInitUnicodeString(&uStr,NT_DEVICE_NAME);
    17.     Status = IoCreateDevice(DriverObject,sizeofDEVICE_EXTENSION),&uStr,FILE_DEVICE_DRVFLT,0,FALSE,&DeviceObject);
    18.     if(NT_SUCCESS(Status)){
    19.         RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
    20.         pDeviceExtension = DeviceObject->DeviceExtension;
    21.         DriverObject->DriverUnload = DrvUnload;
    22.  
    23.         ntproc = NTCALL(48);
    24.         __asm{
    25.             cli
    26.             mov eax, cr0
    27.             mov CR0Reg, eax
    28.             and eax, 0xFFFEFFFF
    29.             mov cr0, eax
    30.             }
    31.         NTCALL(48) = CreateProcess;
    32.         __asm{
    33.             mov eax, CR0Reg
    34.             mov cr0, eax
    35.             sti
    36.         }
    37.         dprintf("addr: %x\n",ntproc);
    38.     }else  DrvUnload(DriverObject);
    39.     return Status;
    40. }
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    48 - точно NtCreateProcess на той ОСи под которую пишешь?
    покажи обработчик CreateProcess, может ты некорректно что-то в нём делаешь, а при загрузку вызывается эта функция, хотя наврядли это помещает загрузке драйвера, но всё-таки.
     
  3. pushick

    pushick New Member

    Публикаций:
    0
    Регистрация:
    22 мар 2007
    Сообщения:
    95
    lev

    гений, 48 это NtCreateProcessEx
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Конкретнее что с ним происходит?
     
  5. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Спасибо за ответы.
    Но сейчас неважно, какая это функция «NtCreateProcessEx» или «NtCreateProcess» так как до нее все равно дело не доходит.
    С драйвером не чего не происходит .
    В реестре появляется ключ «INITSTARTFAILED REG_DWORD 0x00000001(1)».
    Такое впечатление, что какой то сервис следит за загрузкой драйверов переопределяющих функции в SST ядра и блокирует их загрузку.
    Может быть это «Касперский» или «Windows» начала видоизменятся после регулярных апдейтов.
     
  6. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Переписал код драйвера, но все равно таже проблема осталась. Не загружается и все.
    Только теперь проблема вот в этой строчке «mov ebx, offset CreateProcessEx».
    Если ее заменить вот так, например «mov ebx, 0» все работает правда потом красивый синий экран, но это уже неважно ;).
    PDEVICE_EXTENSION pDeviceExtension = NULL;
    ULONG proc;

    NTSTATUS CreateProcessEx(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN HANDLE InheritFromProcessHandle,IN ULONG CreateFlags,IN HANDLE SectionHandle OPTIONAL,IN HANDLE DebugPort OPTIONAL,IN HANDLE ExceptionPort OPTIONAL,IN ULONG JobMemberLevel){
    dprintf("ZwCreateProcessEx\n");
    return ZwCreateProcessEx(ProcessHandle,DesiredAccess,ObjectAttributes,InheritFromProcessHandle,CreateFlags,SectionHandle,DebugPort,ExceptionPort,JobMemberLevel);
    }
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
    PDEVICE_OBJECT DeviceObject = NULL;
    NTSTATUS Status;
    UNICODE_STRING uStr;
    ULONG a;
    pDeviceExtension = NULL;
    proc = 0;
    dprintf("Loading Driver\n");
    RtlInitUnicodeString(&uStr,NT_DEVICE_NAME);
    Status = IoCreateDevice(DriverObject,sizeof(DEVICE_EXTENSION),&uStr,FILE_DEVICE_DRVFLT,0,FALSE,&DeviceObject);
    if(NT_SUCCESS(Status)){
    RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
    pDeviceExtension = DeviceObject->DeviceExtension;
    DriverObject->DriverUnload = DrvUnload;
    proc = (ULONG)KeServiceDescriptorTable->NtoskrnlTable.ServiceTable[48];
    a = 48*4+(ULONG)KeServiceDescriptorTable->NtoskrnlTable.ServiceTable;
    __asm{
    cli
    mov ecx, CR0
    mov edx, ecx
    and ecx, 0xFFFEFFFF
    mov CR0, ecx
    mov eax, a
    mov ebx, offset CreateProcessEx
    mov [eax], ebx
    mov CR0, edx
    sti
    }
    dprintf("addr: %x\n",proc);
    dprintf("addr: %x\n",a);
    }else DrvUnload(DriverObject);
    return Status;
    }
    VOID DrvUnload(IN PDRIVER_OBJECT DriverObject){
    ULONG a;
    a = 48*4+(ULONG)KeServiceDescriptorTable->NtoskrnlTable.ServiceTable;
    __asm{
    cli
    mov ecx, CR0
    mov edx, ecx
    and ecx, 0xFFFEFFFF
    mov CR0, ecx
    mov eax, a
    mov ebx, proc
    mov [eax], ebx
    mov CR0, edx
    sti
    }
    IoDeleteDevice(DriverObject->DeviceObject);
    dprintf("Unloading Driver\n");
    }
     
  7. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    __stdcall ?
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    а что, ebx уже сохранять не нужно?

    вроде должно быть 0xFFFFFFFF, или нет?
     
  9. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Смотря какой флаг хочешь сбросить)
    Кстати, делать AND 0xFFFFFFFF бессмысленно... значение не изменится же
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    я делал это так (на примере ZwQueryDirectoryFile):


    Код (Text):
    1. #define NUM_ZWQUERY             0x91;
    2.  
    3. typedef NTSTATUS (NTAPI * _ZwQueryDirectoryFile) (HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine,
    4.                                                   PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
    5.                                                   PVOID FileInformation, ULONG FileInformationLength,
    6.                                                   FILE_INFORMATION_CLASS FileInformationClass,
    7.                                                   BOOLEAN ReturnSingleEntry, PUNICODE_STRING FileName OPTIONAL,
    8.                                                   BOOLEAN RestartScan);
    9.  
    10. _ZwQueryDirectoryFile           TrueZwQueryDirectoryFile = NULL;
    11. PVOID                           tmpCR0;
    12.  
    13. //==================================================================================
    14. void HookCode(int SrvNum, PVOID* TrueAddr, PVOID NewAddr) {
    15.    
    16.     __asm {
    17.         pushad
    18.         mov         edi,KeServiceDescriptorTable
    19.         mov         edi,[edi]
    20.         mov         ecx,[SrvNum]                    //SrvNum
    21.         mov         eax,[edi+(ecx*4)]
    22.         cmp         eax,[NewAddr]
    23.         je          _skip
    24.         mov         edx,[TrueAddr]                  //TrueAddr
    25.         mov         [edx],eax
    26.         cli
    27.         mov         eax,CR0
    28.         mov         [tmpCR0],eax
    29.         and         eax, -1
    30.         mov         CR0, eax
    31.         mov         eax, [NewAddr]                  //NewAddr
    32.         mov         [edi+(ecx*4)], eax
    33.         mov         eax, [tmpCR0]
    34.         mov         CR0, eax
    35.         sti
    36.         _skip:
    37.         popad
    38.     }
    39.  
    40.     return;
    41. }
    42.  
    43. //====================================================================================
    44. void UnhookCode(int SrvNum, PVOID TrueAddr){
    45.     __asm {
    46.         pushad
    47.         mov         edi,KeServiceDescriptorTable
    48.         mov         edi,[edi]
    49.         cli
    50.         mov         eax,CR0
    51.         mov         [tmpCR0],eax
    52.         and         eax, -1
    53.         mov         CR0, eax
    54.         mov         eax, [TrueAddr]                     //TrueAddr
    55.         mov         ecx, [SrvNum]                       //SrvNum
    56.         mov         [edi+(ecx*4)], eax
    57.         mov         eax, [tmpCR0]
    58.         mov         CR0, eax
    59.         sti
    60.         popad
    61.     }    
    62.     return;
    63. }
    64.  
    65. //====================================================================================
    66. NTSTATUS DriverEntry(PDRIVER_OBJECT  DriverObject, PUNICODE_STRING RegistryPath ){
    67.  
    68.     //..............
    69.     HookCode(NUM_ZWQUERY, (PVOID) &TrueZwQueryDirectoryFile, &NewZwQueryDirectoryFile);
    70.     //..............
    71. }
    72.  
    73. //====================================================================================
    74. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){
    75.  
    76.     //..............
    77.     UnhookCode(NUM_ZWQUERY, TrueZwQueryDirectoryFile);
    78.     //..............
    79. }
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Great

    везде, где я видел манипуляции с KeServiceDescriptorTable, выполнялось and reg,-1.
    В т.ч. и на этом сайте неоднократно.
    Что это дает - я не вникал, возможно это и бессмысленно, но это работает точно :)
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    cresta
    Это сброс бита WP, насколько я помню. и -1 там быть не должно.
    А AND reg,-1 смысла не несет.. разве что только флаги меняет
     
  13. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Спасибо за ответы.
    Но речь идет не о способе сброса бита WP .
    Почему-то если в драйвер добавить любую из таких, например строчек он перестает загружаться.
    «ULONG proc = (ULONG)&CreateProcessEx;» или «ULONG proc = (ULONG)CreateProcessEx;» или «mov ebx, offset CreateProcessEx».
    Функция «CreateProcessEx» действительно «__stdcall».
     
  14. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    скинь бинарник драйвера с одной из таких строчек
     
  15. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Пожалуйста, вставил все 3 строчки.
    А вот как его IDA дизассемблирует:
    Код (Text):
    1. .text:000104D1                 mov     proc, offset CreateProcessEx
    2. .text:000104DB                 mov     proc, offset CreateProcessEx
    3. .text:000104E5                 mov     ecx, ds:KeServiceDescriptorTable
    4. .text:000104EB                 mov     edx, [ecx]
    5. .text:000104ED                 mov     eax, [edx+0C0h]
    6. .text:000104F3                 mov     proc, eax
    7. .text:000104F8                 mov     ecx, ds:KeServiceDescriptorTable
    8. .text:000104FE                 mov     edx, [ecx]
    9. .text:00010500                 add     edx, 0C0h
    10. .text:00010506                 mov     [ebp+var_4], edx
    11. .text:00010509                 cli
    12. .text:0001050A                 mov     ecx, cr0
    13. .text:0001050D                 mov     edx, ecx
    14. .text:0001050F                 and     ecx, 0FFFEFFFFh
    15. .text:00010515                 mov     cr0, ecx
    16. .text:00010518                 mov     eax, [ebp+var_4]
    17. .text:0001051B                 mov     ebx, offset CreateProcessEx
    18. .text:00010520                 mov     [eax], ebx
    19. .text:00010522                 mov     cr0, edx
    20. .text:00010525                 sti
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Твой драйвер не запустится, посколько к нему прилинкована юзер-модная либа (ntdll.dll), из которой импортируется ZwCreateProcessEx.
    Когда ты из кода удаляешь mov proc, offset CreateProcessEx, компилятор удаляет из бинарника твою CreateProcessEx, и заодно вместе с ней удаляет вызов ZwCreateProcessEx, тем самым предотвращая линковку ntdll.dll. И драйвер запускается.

    Сделай как в том коде который я показал, и все будет работать. Т.е. typedef :

    Код (Text):
    1. typedef NTSTATUS (NTAPI * _ZwCreateProcessEx) ( some parameters );
    и в нужном месте будешь вызывать _ZwCreateProcessEx, а не ZwCreateProcessEx. Это предотвратит линковку ntdll.
     
  17. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Сresta, большое спасибо.
    Сделал как ты написал, все заработало.
    Понравились твои "asm" вставки, но их пришлось немного доработать. А то мучил синий экранчик.
    В причинах его появления не разбирался, но ниже приведенные вставки работают идеально.
    Код (Text):
    1. __asm{//HookCode
    2.              pushad
    3.     mov edi,    KeServiceDescriptorTable
    4.     mov edi,    [edi]
    5.     mov edx,    48
    6.     mov eax,    [edi+(edx*4)]
    7.     mov ebx,    offset ZwCreateProcessEx
    8.     mov [ebx],  eax
    9.     cli
    10.     mov eax,    CR0
    11.     mov ecx,    eax
    12.     and eax,    0xFFFEFFFF
    13.     mov CR0,    eax
    14.     mov eax,    offset CreateProcessEx
    15.     mov [edi+(edx*4)], eax
    16.     mov CR0, ecx
    17.     sti
    18.     popad
    19.     }
    20.  
    21. __asm{
    22.     pushad
    23.     mov edi,    KeServiceDescriptorTable
    24.     mov edi,    [edi]
    25.     mov edx,    48
    26.     cli
    27.     mov eax,    CR0
    28.     mov ecx,    eax
    29.     and eax,    0xFFFEFFFF
    30.     mov CR0,    eax
    31.     mov eax,    ZwCreateProcessEx
    32.     mov [edi+(edx*4)], eax
    33.     mov CR0,    ecx
    34.     sti
    35.     popad
    36.     }
     
  18. Deyton

    Deyton Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    94
    Может кто-то написал глупость, другие ее повторяют. Но
    Может кто-то таким образом хочет восстановить старое значение cr0, но для этого надо бы сохранить его предидущее значение а потом просто восстановить
    Код (Text):
    1.      __asm
    2.               {
    3.                  cli
    4.                  mov eax, cr0
    5.                  mov CR0Reg,eax            //сохранить CR0
    6.                  and eax,0xFFFEFFFF      // сбросить WP bit
    7.                  mov cr0, eax
    8.                  ...
    9.                  mov eax, CR0Reg    
    10.                  mov cr0, eax            // востановить содержимое CR0
    11.                  sti
    12.               }
    ну если не сохранять CR0, то можно установить тот бит, кот. сбрасывется and eax,0xFFFEFFFF
    командой or eax, 0x10000, но никак ни and eax, 0xFFFFFFFF, но это тоже не корректно, поскольку бит ВСЕГДА установится, а не понятно был ли он установлен до того как сбрасывался, или может он и был 0 . Работать то оно будет, и если не восстанавливать cr0, но извините, это не совсем корректно, нужно все вернуть как было. Ну а если не сбрасывать бит в cr0 - тоже ИНОГДА будет работать, на компах, где память не защищена от записи.
     
  19. lev

    lev New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2006
    Сообщения:
    16
    Deyton, совсем непонятно про что ты пишешь, и причем тут "and eax, 0xFFFFFFFF ".
    Код (Text):
    1. mov eax,    CR0
    2. mov ecx,    eax              // сохраняю "CR0" в регистре "ECX" тоже самое что и "mov CR0Reg, eax"
    3. and eax,    0xFFFEFFFF   // это не FFFFFFFF тут есть буква "E"
    4. mov CR0,    eax             // сбросить WP bit
    5. mov CR0, ecx                // востановить содержимое CR0 только не из переменной а из регистра содержание
    6.                                   // которого не изменялось.
    Все работает отлично, что тут некорректно совсем непонятно.
     
  20. Deyton

    Deyton Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    94
    lev
    вот это мне не понятно:
    cresta:
    Код (Text):
    1.         cli
    2.         mov         eax,CR0
    3.         mov         [tmpCR0],eax
    4.         and         eax, -1
    5.         mov         CR0, eax
    что делает этот код?