Проблемы с написанием драйвера

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 25 Sep 2007.

  1. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    Хм.. у меня описания к нему вобще нет.
    Давай полный сорс драйвера в студию + кусок сорса программы управления, которая пытается открыть девайс, созданный драйвером
    Кстати, когда открываешь девайс, надо задавать флаги общего доступа FILE_SHARE_READ|FILE_SHARE_WRITE, а у тебя там ноль. Иначе будут проблемы. С этой вряд ли связано, но на будущее учти
     
  2. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Зачем открывать с GENERIC_ALL ? У нее GENERIC_EXECUTE вообще-то ещё стоит. GENERIC_READ|GENERIC_WRITE используй
    Кстати, зачем тебе вообще все это, ты же пишешь обычный пинч етц, скрывающий процесс по присланному PID (наверное через хук sdt).
    Почему бы просто не рассматривать IRP_MJ_CONTROL и не делать в юзермоде DeviceIoControl() ?
     
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Суть драйвера такова: Он должен перехватывать запуск процессов и заносить в лог.
    также она должен защищать програму от выгрузки,
    а именно через перехват функции NtOpenProcess
    Сначало я начал делать всё без драйвера.
    т.е. через инжект своей DLL'ки которая перехватывала запуск программы.
    Но не на всех компах работало стабильно. То фаер матерился, то авир.
    Бывало аткое, что пашет отлично, но на некоторых прогах - вылетает.


    Вот для теста драйвера програма:
    Code:
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,WInSVC;
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Memo1: TMemo;
        Button4: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
      CTL_SETPID,CTL_GETPID:dword;
    type
     TRUNPROC=record
      Parent:dword;
      PID:dword;
     end;
    
    implementation
    
    {$R *.dfm}
    const
     METHOD_BUFFERED = 0;
     FILE_READ_ACCESS = 1;
     FILE_WRITE_ACCESS = 2;
     FILE_DEVICE_UNKNOWN =$22;
    
    function CTL_CODE(ADeviceType: Integer; AFunction: Integer; AMethod: Integer; AAccess: Integer): DWORD;
    begin
      Result := (ADeviceType shl 16) or (AAccess shl 14) or (AFunction shl 2) or AMethod;
    end;
    
    
    
    procedure TForm1.Button1Click(Sender: TObject); // Установка драйвера
    var
    h:thandle;
    g_hSCManager,g_hService:thandle;
    p:pansichar;
    begin
    
    h:=CreateFile('\\.\MyDRVS', GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if h<>windows.INVALID_HANDLE_VALUE then
     begin
      memo1.Lines.add('[+] Driver Already Installed');
      closehandle(h);
      exit;
     end;
    
    g_hSCManager:=OpenSCManager(nil,nil, SC_MANAGER_ALL_ACCESS);
    if g_hSCManager=0 then
     begin
      memo1.Lines.add('OpenSCManager ERROR');
      exit;
     end;
    
    g_hService:=CreateService(g_hSCManager, 'MyDRVS','MyDRVS',
    				SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
    				SERVICE_ERROR_IGNORE, 'F:\RCI\Driver\MyDRVS.sys', nil, nil, nil, nil, nil);
    if g_hService=0 then
     begin
      memo1.Lines.add('CreateService ERROR');
      exit;
     end;
    if StartService(g_hService, 0, p)=false then
     begin
      memo1.Lines.add('StartService ERROR');
      exit;
     end;
    
    h:=CreateFile('\\.\MyDRVS', GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if h<>windows.INVALID_HANDLE_VALUE then
     begin
      MessageBox(0, 'OK', 'OPEN', MB_ICONINFORMATION or MB_OK);
      exit;
     end;
    
    //DeleteService(g_hService);
    CloseServiceHandle(g_hService);
    CloseServiceHandle(g_hSCManager);
    
    memo1.Lines.add('[+] Install OK');
    closehandle(h);
    
    end;
    
    procedure TForm1.Button2Click(Sender: TObject); // установка своего PID для защиты
    var
    hDriver:thandle;
    TrId:dword;
    d:dword;
    begin
    hDriver:=CreateFile('\\.\MyDRVS', GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    memo1.Lines.Add(inttostr(GetLastError));
     if hDriver = INVALID_HANDLE_VALUE then
        begin
         memo1.Lines.add('Open Driver Error');
         exit;
        end;
        d:=GetCurrentProcessId();
    DeviceIoControl(hDriver, CTL_SETPID,@d,  4, nil, 0, TrId, nil);
    closehandle(hDriver);
    memo1.Lines.add('Set PID');
    
    
    end;
    
    procedure TForm1.Button3Click(Sender: TObject); // снятие защиты
    var
    hDriver:thandle;
    TrId,d:dword;
    begin
    hDriver:=CreateFile('\\.\MyDRVS', GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
     if hDriver = INVALID_HANDLE_VALUE then
        begin
         memo1.Lines.add('Open Driver Error');
         exit;
        end;
    d:=$FFFFFFFF;
    DeviceIoControl(hDriver, CTL_SETPID,@d,  4, nil, 0, TrId, nil);
    closehandle(hDriver);
    memo1.Lines.add('UnSet PID');
    end;
    
    procedure TForm1.Button4Click(Sender: TObject); // чтение PID'a
    var
    hDriver:thandle;
    TrId,PID:dword;
    begin
    hDriver:=CreateFile('\\.\MyDRVS', GENERIC_READ+GENERIC_WRITE, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
     if hDriver = INVALID_HANDLE_VALUE then
        begin
         memo1.Lines.add('Open Driver Error');
         exit;
        end;
    DeviceIoControl(hDriver, CTL_GETPID, nil, 0, @PID, 4, TrId, nil);
    memo1.Lines.Add(inttostr(PID));
    closehandle(hDriver);
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    CTL_GETPID:=CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS);
    CTL_SETPID:=CTL_CODE(FILE_DEVICE_UNKNOWN, 2, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS);
    end;
    
    end.
    
    Вот код драйвера:
    Code:
    #include <ntddk.h>
    
    #define DEBUG
    
    #ifdef DEBUG
      #define DPRINT DbgPrint
    #else
      #define DPRINT
    #endif
    
    #define IOCTL_GETPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
    #define IOCTL_SETPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x02, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
    
    typedef PVOID* PNTPROC;
    typedef DWORD (ULONG);
    typedef DWORD*	PDWORD;
    typedef unsigned char (BYTE);
    typedef BYTE* PBYTE;
    
    typedef struct _SYSTEM_SERVICE_TABLE
    {
        PNTPROC ServiceTable; 
        PDWORD  CounterTable; 
        ULONG   ServiceLimit; 
        PBYTE   ArgumentTable; 
    }
    SYSTEM_SERVICE_TABLE ,
    * PSYSTEM_SERVICE_TABLE ,
    * * PPSYSTEM_SERVICE_TABLE ;
    
    
    typedef struct _SERVICE_DESCRIPTOR_TABLE {
       SYSTEM_SERVICE_TABLE ntoskrnl;  //SST для ntoskrnl.exe
       SYSTEM_SERVICE_TABLE win32k;    //SST для win32k.sys
       SYSTEM_SERVICE_TABLE unused1;   //не используется
       SYSTEM_SERVICE_TABLE unused2;   //не используется
    }
    SERVICE_DESCRIPTOR_TABLE ,
    * PSERVICE_DESCRIPTOR_TABLE,
    * * PPSERVICE_DESCRIPTOR_TABLE ;
    
    typedef struct _TRUNPROC // структура описывающая запрос к драйверу
    {
    	HANDLE parent;
    	HANDLE PID;
    } TRUNPROC, *PRUNPROC;
    
    
    #define NTCALL(_function) KeServiceDescriptorTable->ntoskrnl.ServiceTable[_function]
    extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
    extern PUSHORT NtBuildNumber;
    typedef NTSTATUS (*NtOpenPrcPointer) (OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess,  IN POBJECT_ATTRIBUTES ObjectAttributes,  IN PCLIENT_ID ClientId OPTIONAL);
    
    NtOpenPrcPointer TrueNtOpenProcess; 
    ULONG OpenProcId;
    
    
    UNICODE_STRING DeviceName;
    UNICODE_STRING SymbolicLinkName;
    PDEVICE_OBJECT deviceObject = NULL;
    
    HANDLE ProtectedPid = 0;
    TRUNPROC RUNPROC;
    
    //функция - обработчик перехвата
    NTSTATUS NewNtOpenProcess (OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess,  IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL)
    {
     HANDLE ProcessId;
     //безопасным образом извлекаем ProcessId
     if ((ULONG *)ClientId > MmUserProbeAddress) return STATUS_INVALID_PARAMETER;
     __try
     {
      ProcessId = ClientId->UniqueProcess;
     }
    __except(EXCEPTION_EXECUTE_HANDLER)
     {
      DPRINT("Exception");
      return STATUS_INVALID_PARAMETER;
      }
    
     if (ProcessId == ProtectedPid) //защищаем процесс 
      {
       DPRINT("Access Denied!");
       return STATUS_ACCESS_DENIED;
       }
     else return TrueNtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
    }
    
    
    VOID CreateProcessNotifyRoutine(IN HANDLE  ParentId,
        IN HANDLE  ProcessId,
        IN BOOLEAN  Create)
    {
    DPRINT("CREATENOTIFY");
        if (Create) 
        {
    	  DPRINT("RUN CREATENOTIFY %d",ProcessId);
          RUNPROC.parent=ProcessId;
          RUNPROC.PID=ParentId;
        }
    }
    
    NTSTATUS DriverDispatcher(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    {
     NTSTATUS status;
     PIO_STACK_LOCATION irpStack;
     DPRINT("DriverDispatcher");
     irpStack = IoGetCurrentIrpStackLocation (Irp);
     
    if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) 
     {
      switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
       {
    	case IOCTL_SETPID: // утановка PID
    	    if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(HANDLE)) 
    		{
    		       
    				ProtectedPid=*(HANDLE *)Irp->AssociatedIrp.SystemBuffer;
    				DPRINT("PID= %d",ProtectedPid);
    				status = STATUS_SUCCESS;
    	 	}
    		break;
    	case IOCTL_GETPID: // Чтение PID
    	if (irpStack->Parameters.Read.Length < 4)
        {
    	    DPRINT("LENGTH < 4");
            Irp->IoStatus.Information  = 0;
    		status = STATUS_BUFFER_TOO_SMALL;
          
        } 
    	 else
    	{
         DPRINT("LENGTH OK");	
         Irp->IoStatus.Information  = 4;
    	 *(HANDLE *)Irp->AssociatedIrp.SystemBuffer=ProtectedPid; 
    	 status = STATUS_SUCCESS;
    	}
    	break;
    	
    	default: status = STATUS_INVALID_DEVICE_REQUEST;
    	}
     
     }
    
     
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    
     return status;
     }
    
    
    
    VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
    {
     ULONG CR0Reg;
      DPRINT("Driver Unload");
     PsSetCreateProcessNotifyRoutine(*CreateProcessNotifyRoutine, TRUE); 
     IoDeleteSymbolicLink(&SymbolicLinkName); // удаляем символическую ссылку
     IoDeleteDevice(deviceObject);            // удаляем устройство
    
     //снимаем перехват
    __asm
     {
      cli                     // запрещаем прерывания
      mov eax, cr0
      mov CR0Reg,eax
      and eax,0xFFFEFFFF		// сбросить WP bit
      mov cr0, eax
    }
    
    NTCALL(OpenProcId) = TrueNtOpenProcess;
    
    __asm
     {
      mov eax, CR0Reg    
      mov cr0, eax            // востановить содержимое CR0
      sti                     // разрешаем прерывания
    }
    DPRINT("Driver Unloaded");
     return;
    }
    
    
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                         IN PUNICODE_STRING RegistryPath)
    {
    
     ULONG CR0Reg;
     NTSTATUS st;
     NTSTATUS rc;	
     
     PCWSTR dDeviceName       = L"\\Device\\MyDRVS";
     PCWSTR dSymbolicLinkName = L"\\DosDevices\\MyDRVS";
    
     (long int)ProtectedPid = 0x0FFFFFFFF;
     DPRINT("Driver loaded");
     RtlInitUnicodeString(&DeviceName,       dDeviceName);
     RtlInitUnicodeString(&SymbolicLinkName, dSymbolicLinkName);
      st = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_NULL, 0, FALSE,  &deviceObject);    
        
    if (st == STATUS_SUCCESS) 
    {
    DPRINT("IoCreateDevice OK");
    st = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
    if (st == STATUS_SUCCESS) 
     {
       DPRINT("IoCreateSymbolicLink OK");
     }
     else
     {
       DPRINT("IoCreateSymbolicLink ERROR");
     }
    } 
    else 
    {
    DPRINT("IoCreateDevice ERROR");
    }
    
    //определяем версию ядра системы
    switch (*NtBuildNumber)
     {
       case 2195 :  //win 2k
        OpenProcId = 0x06A;
    	DPRINT("WIn2000");
        break;
          
       case 2600 : //win xp
          OpenProcId = 0x07A;
    	  DPRINT("WinXP");
          break;
       
       default :
           return STATUS_NOT_IMPLEMENTED;
          break;
      }
    	
    //устанавливаем перехват	
      TrueNtOpenProcess  = NTCALL(OpenProcId);
    
    __asm
     {
      cli                     // запрещаем прерывания
      mov eax, cr0
      mov CR0Reg,eax
      and eax,0xFFFEFFFF		// сбросить WP bit
      mov cr0, eax
     }
    
    NTCALL(OpenProcId) = NewNtOpenProcess;
    
    __asm
     {
      mov eax, CR0Reg    
      mov cr0, eax            // востановить содержимое CR0
      sti                     // разрешаем прерывания
     }
     
    rc = PsSetCreateProcessNotifyRoutine(*CreateProcessNotifyRoutine, FALSE); 
    
    
    DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = 
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatcher; 
    DriverObject->DriverUnload = DriverUnload;
    DPRINT("END LOAD");
      return STATUS_SUCCESS;
    
    }
    
     
  4. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Софт айс + брек на DriverDispatcher
     
    #24 KEZ, 29 Sep 2007
    Last edited: 29 Sep 2007
  5. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    лучше file_all_access

    дурной тон. лучше KdPrint(())

    запрещать прерывания не поможет на многопроцессорной системе. нам нужно делать KfRaiseIrql( HIGH_LEVEL )

    что это за чудо и зачем оно надо

    С чего ты взял что длина будет в irpStack->Parameters.Read.Length ?
    RTFM, она будет в irpStack->Parameters.DeviceIoControl.OutputBufferLength

    А в irpStack->Parameters.Read.Length будет длина буффера при IRP_MJ_READ

    В DriverEntry множество ошибок, связанных с обработкой статусов от IoCreateDevice/IoCreateSymbolicLink

    Что за нах? Откуда звездочка? У тебя ЭТО вообще компилируется? Сомневаюсь... сильно...
     
  6. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    rc = PsSetCreateProcessNotifyRoutine(*CreateProcessNotifyRoutine, FALSE); - это как раз и есть фишка с помощью которой можно отлавливать запуск и заврешение программы. Компилится запросто. Пример был взят с rootkits.ru а именно: http://rootkits.ru/viewtopic.php?id=32

    На счет процеов - я уверен что драйвер не будет истользовать на многопроцессорных системах.

    О точно. Яже сначало сделал через READ. поэтому и оставалось irpStack->Parameters.Read.Length

    нашел в чем была проблема. почему я не мог связаться с драйвером. по умолчанию при открытии нужно было возвращаться статус: STATUS_SUCCESS;
    о чем я забыл.
     
    #26 slesh, 29 Sep 2007
    Last edited: 29 Sep 2007
  7. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    У тебя вообще в драйвере КУЧА ошибок. У тебя будет множество глюков вплоть до бсодов, с ними связанных
     
  8. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 _Great_ чуть исправил драйвер. Вроде ошибок не вижу, т.к. делал всё на базе примеров которые взял с wasm.
    Шас тестировал его - работате отлично глюков вообще не заметил.
     
  9. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    Неточности связанные с обработкой ошибок:

    Code:
     else
     {
       DPRINT("IoCreateSymbolicLink ERROR");
     }
    } 
    else 
    {
    DPRINT("IoCreateDevice ERROR");
    }
    Кроме вывода сообщения было бы желательно почистить всё, что успешно создалось, и выйти из DriverEntry с ошибочным статусом
     
  10. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    я вообще это делал для отладки. в последствии всё исправил.