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

Код:
Declare DriverEntry(*DriverObject, *RegistryPath)

ImportC "ntoskrnl.lib"
  DbgPrint(*String)
  memset(*mem, Byte, Size)
EndImport

Import "ntoskrnl.lib"
  ZwQuerySystemInformation(SysInfoClass, *SysInfo, SysInfoLength.l, *ReturnLength)
  ExAllocatePool(PoolType, NumBytes)
  ExFreePool(*Point)
EndImport
  

!extrn _DbgPrint
!extrn _memset

!extrn _ZwQuerySystemInformation@16
!extrn _ExAllocatePool@8
!extrn _ExFreePool@4

!extrn _PB_PokeS@8
!extrn PB_PeekL

!public PureBasicStart
!section '.code' code readable executable align 8
!PureBasicStart:
 *A=@DriverEntry()
!jmp [p_A] ; Переход в процедуру DriverEntry().

XIncludeFile #PB_Compiler_Home+"DDK\StringDr.pbi"

EnableExplicit

Structure DrArray_SMI
  Arrays.SYSTEM_MODULE_INFORMATION[1]
EndStructure

; Процедура загрузки драйвера. Вызывается однократно при его запуске.
Procedure DriverEntry(*DriverObject.DRIVER_OBJECT, *RegistryPath.UNICODE_STRING)
  Protected cb.l, *p, *pArray.DrArray_SMI
  Protected dwNumModules.l ;, *pMessage
  Protected Buffer.s{128}, Temp
  
  DbgPrint(@"LoadDriver")
  
  cb=0
  ZwQuerySystemInformation(#SystemModuleInformation, @*p, 0, @cb)
  If cb <> 0 ;
    cb + 32
    *p = ExAllocatePool(#PagedPool, cb)
    If *p<>#Null
      If ZwQuerySystemInformation(#SystemModuleInformation, *p, cb, @cb)= #STATUS_SUCCESS

        *pArray = *p
        dwNumModules = PeekL(*pArray)
        
        PokeS(@Buffer, "Bytes:  ") : Temp=8
        Temp+StrDr(@Buffer+Temp, 128-Temp, cb)
        PokeS(@Buffer+Temp, ";  Address: 0x") : Temp+14
        Temp+HexDr(@Buffer+Temp, 128-Temp, *p)
        PokeS(@Buffer+Temp, ";  Modules: ") : Temp+12
        Temp+StrDr(@Buffer+Temp, 128-Temp, dwNumModules)
        
        DbgPrint(@Buffer)
        memset(@Buffer, 0, 128)
        
        
        *pArray + 4
        
        Temp=0
        While Temp < dwNumModules

          DbgPrint(@*pArray\Arrays[Temp]\ImageName[0])
          
          Temp+1
        Wend
          
      EndIf
      
      ExFreePool(*p)
    EndIf
  EndIf
  
  ; Собщаем об ошибке чтобы система выгрузила драйвер.
  ProcedureReturn #STATUS_DEVICE_CONFIGURATION_ERROR
EndProcedure

Я не буду рассматривать подробно код, т. к. это уже сделано в вышеуказанной статье.
Рассмотрим только отдельные моменты, которых нет в той статье или которые отличаются.
Функции ядра импортируются из библиотеки ntoskrnl.lib. Оператор ImportC, импортирует используя соглашение вызова cdecl, а оператор Import импортирует функции используя соглашение stdcall.
Далее функции объявляются оператором ассемблера FASM - extrn. Восклицательный знак перед ними означает что данные строки не обрабатывает транслятор PureBasic и они будут переданы в неизменном виде FASM'у.
Далее располагается метка PureBasicStart, которая так же в неизменном виде будет передана FASM'у. Это точка входа с  которой начинается выполнение программы, в нашем случае, драйвера. За меткой следует переход в процедуру DriverEntry(), которая должна вызываться при старте драйвера. Нужно отметить что в данном случае ее имя может быть другим, но по традиции оно именно такое, какое заданно.
Оператор EnableExplicit включает явное объявление переменных. По умолчанию переменные объявлять не обязательно, но в случае драйвера, ошибка может слишком дорого стоить, поэтому подстрахуемся.

В процедуре DriverEntry(), в первую очередь отправляется отладочное сообщение с текстом "LoadDriver". Затем, первым вызовом функции ZwQuerySystemInformation() узнаем сколько байт нужно под данные. Этот вызов естественно завершится с ошибкой, т. к. мы задали размер буфера *p, равным 0. Но зато в переменной cb будет значение требуемого размера буфера. Далее запрашиваем у системы блок памяти функцией ExAllocatePool() и если его успешно получили, то снова вызываем функцию ZwQuerySystemInformation(). На сей раз, был указан необходимый размер буфера и вызов функции должен пройти успешно, если конечно за это время не появился новый модуль, что маловероятно. Если вызов успешный, то считываем из первых четырех байт полученных данных, число модулей, и выводим их в отладчик, а так же адрес и число байт. Далее располагается массив структур с данными модулей. Нас интересуют только имена этих модулей, а они хранятся в статическом массиве символов ImageName. Их мы извлекаем из массива структур в цикле While - Wend в котором выводятся в отладчик имена всех загруженных модулей. После чего, освобождается запрошенная память, функцией ExFreePool().
Запомните, в режиме ядра нужно освобождать все ресурсы, которые нам больше не нужны. Даже если драйвер выгрузится, то в отличие от режима пользователя, ресурсы все равно будут заняты драйвером и система их не освободит!
При завершении процедуры, возвращается код ошибки #STATUS_DEVICE_CONFIGURATION_ERROR, что поведет к выгрузке драйвера.
Если же процедура DriverEntry() сообщит что ошибок нет, то драйвер так и останется висеть в памяти, а нам это не нужно, ведь весь код находится в этой процедуре и нужно завершить работу драйвера при завершении процедуры.

Итак, копируйте код в редактор PureBasic. Если кто не знает, его можно скачать здесь.
Затем компилируйте выбрав в меню "Компилятор", пункт "Создать драйвер". Если до этого исходный текст драйвера не был сохранен, то его придется сохранить. Потом указываем место сохранения драйвера и если в коде ошибок нет (а их нет, разве что вы неправильно скопировали код со станицы), то будет создан драйвер в указанном месте.
Как видите, создать драйвер не сложнее чем обычную программу.

Перед проделыванием нижеследующего, обязательно сохраните все документы, т. к. возможно появление BSoD'а (синего экрана смерти).

Теперь мы имеем драйвер и его нужно запустить чтобы посмотреть как он работает.
С помощью меню "Инструменты" среды PureBasic, запускаете два инструмента, имеющие имена Dbgview и KmdManager. В KmdManager указываете путь к драйверу. Далее последовательно нажимаете следующие кнопки в окне: "Register", "Run" и "Unregister". Кнопку "Stop" после "Run" нажимать не нужно, потому что драйвер сообщил об ошибке и система сама его выгрузила, т. е. проделала действие эквивалентное кнопке "Stop".

Если все сделано правильно, то вы увидите следующее:

http://pure-basic.narod.ru/forum_files/driver/img/DrMem.PNG

Скачать файлы к статье можно здесь. http://pure-basic.narod.ru/forum_files/ … elPool.zip