PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Kernel Driver » Драйвер, защищающий процесс от завершения


Драйвер, защищающий процесс от завершения

Сообщений 1 страница 26 из 26

1

Этот драйвер позволяет защитить процесс от закрытия через диспетчер задач и другие подобные программы. Защита происходит на уровне ядра операционной системы методом перехвата функций ядра ОС, таких как NtOpenProcess() и NtTerminateProcess(). Работает в винде от Windows 2000 до Windows 8 включительно.
Код предназначен для компиляции в среде программирования PureBasic 5.11.

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

; Объявляем прототип True функции для перехватываемой функции.
Prototype pNtOpenProcess(*ProcessHandle, DesiredAccess,
                              *ObjectAttributes, *ClientId)
Prototype.i pNtTerminateProcess(ProcessHandle.i, ExitStatus.i)

Global TrueNtOpenProcess.pNtOpenProcess=0   ; Оригинальная функция из ядра.
Global TrueNtTerminateProcess.pNtTerminateProcess=0   ; Оригинальная функция из ядра.

Global gOpenProcId=0, gTerminateProcId=0, gMyPID.l=0

*A=@DriverEntry()
!jmp [p_A]

#Debug = #False ; #True

IncludePath #PB_Compiler_Home+"DDK\"
XIncludeFile "ntddk.pbi"
XIncludeFile "ntstatus.pbi"
XIncludeFile "ntfunct.pbi"

Import "ntoskrnl.lib"
  *KeServiceDescriptorTable.SERVICE_DESCRIPTOR_TABLE As "__imp__KeServiceDescriptorTable"
  *NtBuildNumber.Unicode As "__imp__NtBuildNumber"
  *MmUserProbeAddress As "__imp__MmUserProbeAddress"
EndImport

#IOCTL_NewPid = $200


Macro NTCALL(_function)
  *KeServiceDescriptorTable\ntoskrnl\ServiceTable\ar[_function]
EndMacro

Macro CernelDebug(String)
  CompilerIf #Debug = #True
    DbgPrint(@String)
  CompilerEndIf
EndMacro

EnableExplicit
EnableASM

Procedure NewNtOpenProcess(*ProcessHandle, DesiredAccess,
                           *ObjectAttributes, *ClientId.CLIENT_ID)
  Protected ProcessId
  
  If gMyPID<>0
    
    MOV   ebx, *ClientId
    CMP   ebx, *MmUserProbeAddress
    JBE   l_newntopenprocess_m1
    CernelDebug("*ClientId > *MmUserProbeAddress")
    ProcedureReturn #STATUS_INVALID_PARAMETER
    m1:
    
    If *ClientId
      ProcessId = *ClientId\UniqueProcess
    Else
      CernelDebug("*ClientId = 0")
      ProcedureReturn #STATUS_INVALID_PARAMETER
    EndIf
    
    If gMyPID = ProcessId
      CernelDebug("My Process")
      ProcedureReturn #STATUS_ACCESS_DENIED
    Else
      Goto m2
    EndIf
    
  Else
    m2:
    If TrueNtOpenProcess
      ProcedureReturn TrueNtOpenProcess(*ProcessHandle, DesiredAccess,
                                        *ObjectAttributes, *ClientId)
    Else
      ProcedureReturn #STATUS_INVALID_ADDRESS
    EndIf
  EndIf
  
EndProcedure

Procedure GetPID(ProcessHandle)
  Protected *obj, ProcessId
  
  ProcessId = $FFFFFFFF
  
  If ObReferenceObjectByHandle(ProcessHandle, 0 ,0, #KernelMode,
                               @*obj,#Null) = #STATUS_SUCCESS
    ProcessId = PsGetProcessId(*obj)
    ObDereferenceObject(*obj)
  EndIf
  
  ProcedureReturn ProcessId
EndProcedure
  

Procedure.i NewNtTerminateProcess(ProcessHandle.i, ExitStatus.i)
  
  If gMyPID<> 0 And GetPID(ProcessHandle) = gMyPID
    CernelDebug("Terminate my process")
    ProcedureReturn #STATUS_ACCESS_DENIED
  Else
    If TrueNtTerminateProcess
      ProcedureReturn TrueNtTerminateProcess(ProcessHandle, ExitStatus)
    Else
      ProcedureReturn #STATUS_INVALID_ADDRESS
    EndIf
  EndIf
  
EndProcedure


Procedure DeviceIoControl(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP)
  Protected ntStatus, *Point, *Stack.IO_STACK_LOCATION
  Protected inBuffersize, outBuffersize, CtrlBuff.l
  Protected Code
  
  *Stack = *pIrp\Tail\Overlay\CurrentStackLocation
  
  inBuffersize = *Stack\Parameters\DeviceIoControl\InputBufferLength
  outBuffersize = *Stack\Parameters\DeviceIoControl\OutputBufferLength
  
  If inBuffersize>=4
    CtrlBuff   = PeekL(*pIrp\SystemBuffer)
    
    Code = *Stack\Parameters\DeviceIoControl\IoControlCode
    
    ntStatus = #STATUS_SUCCESS
    
    Select Code
      Case #IOCTL_NewPid
        gMyPID = CtrlBuff
      Default
        ntStatus = #STATUS_UNSUCCESSFUL
    EndSelect
    
  Else
    ntStatus = #STATUS_BUFFER_TOO_SMALL
  EndIf
  
  *pIrp\IoStatus\Information = 0
  *pIrp\IoStatus\Status = ntStatus
  IoCompleteRequest(*pIrp, #IO_NO_INCREMENT)
  
  ProcedureReturn ntStatus
EndProcedure

Procedure CreateDispatch(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP)
  *pIrp\IoStatus\Information = 0
  *pIrp\IoStatus\Status = #STATUS_SUCCESS
  IoCompleteRequest(*pIrp, #IO_NO_INCREMENT)
  ProcedureReturn #STATUS_SUCCESS
EndProcedure

Macro UnInterception()
    
  CLI                   ; запрещаем прерывания
  MOV eax, cr0
  MOV CR0Reg,eax
  AND eax,$FFFEFFFF     ; сбросить WP bit
  MOV cr0, eax
  
  If TrueNtOpenProcess
    NTCALL(gOpenProcId) = TrueNtOpenProcess
  EndIf
  
  If TrueNtTerminateProcess
    NTCALL(gTerminateProcId) = TrueNtTerminateProcess
  EndIf
  
  MOV eax, CR0Reg    
  MOV cr0, eax            ; востановить содержимое CR0
  STI                     ; разрешаем прерывания
  
EndMacro

Procedure DriverUnload(*DriverObject.DRIVER_OBJECT)
  Protected uniDOSString.UNICODE_STRING
  Protected CR0Reg.i
  
  UnInterception()
  
  RtlInitUnicodeString(@uniDOSString, ?DosDevices)
  IoDeleteSymbolicLink (@uniDOSString)
  IoDeleteDevice(*DriverObject\DeviceObject)
EndProcedure

Macro Interception()
  
  Select *NtBuildNumber\u
    Case 2195  ; Win 2000
      gOpenProcId = $06A
      gTerminateProcId = 0 ; Не перехватывать, т. к. в ядре отсутствует Native фукнция PsGetProcessId()!
      
    Case 2600  ; Win XP
      gOpenProcId = $07A
      gTerminateProcId = $101
      
    Case 3790 ; Win 2003.
      gOpenProcId = $80
      gTerminateProcId = $10A
      
    Case 6000, ; Win Vista RTM.
         6001, ; Win Vista SP1 и Win Server 2008 RTM.
         6002  ; Win Vista SP2 и  Win Server 2008 SP2.
      gOpenProcId = $C2
      If *NtBuildNumber\u=6000
        gTerminateProcId = $152
      Else
        gTerminateProcId = $14e
      EndIf
      
    Case 7600, ; Win 7 RTM и Win Server 2008 R2 RTM.
         7601  ; Win 7 SP1 и Win Server 2008 R2 SP1.
      gOpenProcId = $BE
      gTerminateProcId = $172
      
    Case 9200 ; Win 8.
      gOpenProcId = 0 ; Не перехватывать, т. к. BSoD.
      gTerminateProcId = $23
      
    Default
      ProcedureReturn #STATUS_NOT_IMPLEMENTED
  EndSelect
  
  ; Устанавливаем перехваты.
  
  If gOpenProcId>0
    TrueNtOpenProcess = NTCALL(gOpenProcId)
    If TrueNtOpenProcess = 0
      ProcedureReturn #STATUS_INVALID_ADDRESS
    EndIf
  Else
    TrueNtOpenProcess = 0
  EndIf
  
  If gTerminateProcId>0
    TrueNtTerminateProcess = NTCALL(gTerminateProcId)
    If TrueNtTerminateProcess = 0
      ProcedureReturn #STATUS_INVALID_ADDRESS
    EndIf
  Else
    TrueNtTerminateProcess = 0
  EndIf
  
  
  CLI                     ; запрещаем прерывания
  MOV eax, cr0
  MOV CR0Reg,eax
  AND eax,$FFFEFFFF      ; сбросить WP bit
  MOV cr0, eax
  
  If gOpenProcId>0
    NTCALL(gOpenProcId) = @NewNtOpenProcess()
  EndIf
  
  If gTerminateProcId>0
    NTCALL(gTerminateProcId) = @NewNtTerminateProcess()
  EndIf
  
  
  MOV eax, CR0Reg    
  MOV cr0, eax            ; востановить содержимое CR0
  STI                     ; разрешаем прерывания
  
  
EndMacro

Procedure DriverEntry(*DriverObject.DRIVER_OBJECT, *RegistryPath.UNICODE_STRING)
  Protected deviceObject.DEVICE_OBJECT
  Protected uniNameString.UNICODE_STRING
  Protected uniDOSString.UNICODE_STRING, status
  Protected CR0Reg.i
  
  If *KeServiceDescriptorTable And *NtBuildNumber
    
    Interception()
    
    RtlInitUnicodeString(@uniNameString, ?Device)
    RtlInitUnicodeString(@uniDOSString, ?DosDevices)
    status = IoCreateDevice(*DriverObject, 0, @uniNameString, #FILE_DEVICE_UNKNOWN,
                            0, #False, @deviceObject)
    If status <> #STATUS_SUCCESS
      UnInterception()
      ProcedureReturn status
    EndIf
    
    status = IoCreateSymbolicLink(@uniDOSString, @uniNameString)
    If status <> #STATUS_SUCCESS
      IoDeleteDevice(@deviceObject) ; Мы должны сами убирать "хвосты" в режиме ядра!
      UnInterception()
      ProcedureReturn status
    EndIf
    
    *DriverObject\DriverUnload = @DriverUnload()
    
    *DriverObject\MajorFunction[#IRP_MJ_CREATE] = @CreateDispatch()
    *DriverObject\MajorFunction[#IRP_MJ_CLOSE]  = @CreateDispatch()
    *DriverObject\MajorFunction[#IRP_MJ_DEVICE_CONTROL] = @DeviceIoControl()
    
    ProcedureReturn #STATUS_SUCCESS
    
  Else
    ProcedureReturn #STATUS_INVALID_SYSTEM_SERVICE
  EndIf
  
EndProcedure

DataSection
  CompilerSelect #PB_Compiler_Processor
    CompilerCase #PB_Processor_x86 
      Device:
      !du '\Device\pbNoKill', 0, 0
      
      DosDevices:
      !du '\DosDevices\pbNoKill', 0, 0
    CompilerCase #PB_Processor_x64
      Device:
      !du '\Device\pbNoKill_x64', 0, 0
      
      DosDevices:
      !du '\DosDevices\pbNoKill_x64', 0, 0
  CompilerEndSelect
EndDataSection

Код этого драйвера и его модификации можно найти в папке "Examples\Driver\pbNoKill" среды программирования PureBasic 5.11.

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

Код:
XIncludeFile "DrUserModeFramework.pbi"

#IOCTL_NewPid = $200
#IOCTL_DelPid = $400

SetCurrentDirectory(GetPathPart(ProgramFilename()))

g_hSemaphore_runonly = CreateSemaphore_(#Null,0,1,"pbNoKilltest_runs")
If g_hSemaphore_runonly And GetLastError_()=#ERROR_ALREADY_EXISTS 
  CloseHandle_(g_hSemaphore_runonly) 
  MessageRequester("", "Программа уже работает!", #MB_ICONWARNING)
  End
EndIf

OSv = OSVersion()
If OSv<#PB_OS_Windows_2000 Or OSv>#PB_OS_Windows_8
  MessageRequester("", "ОС не поддерживается")
  End
EndIf

hDriver=OpenDriver(GetPathPart(ProgramFilename())+"pbNoKill.sys", "pbNoKill", "pbNoKill", "pbNoKill")

If hDriver=0 
  Driver_UnInstall("pbNoKill")
  MessageRequester("", "Не удалось загрузть драйвер")
  End
EndIf

PID = GetCurrentProcessId_()

Code = DeviceIoControl_(hDriver, #IOCTL_NewPid, @PID, 4, 0, 0, @BytesReturned, 0)
If Code
 

OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(0, 4, 10, 210, 30, "Попробуй завершить процесс этой проги с помощью диспетчера задач")
ButtonGadget(4, 10,170, 200, 20, "Закрыть")
Repeat 
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    If EventGadget()=4
      Break
    EndIf
  EndIf
ForEver

Else
  Code = GetLastError_()
  MessageRequester("", "Ошибка "+Str(Code)+" при обращении к драйверу")
EndIf

CloseHandle_(hDriver)
Driver_UnInstall("pbNoKill")
CloseHandle_(g_hSemaphore_runonly)

Найти этот пример, а так же файл DrUserModeFramework.pbi можно в папке "Examples\Driver\pbNoKill\NtOpenProcess и NtTerminateProcess" среды программирования PureBasic 5.11.

0

2

Пётр
Вы простите за глупый вопрос, но я ноль в программировании) Каким образом при помощи вашего кода мне защитить свою программу(процесс) от принудительного закрытия?

0

3

Нужно передать драйверу PID процесса защищаемой программы.

Код:
PID = GetCurrentProcessId_()
Code = DeviceIoControl_(hDriver, #IOCTL_NewPid, @PID, 4, 0, 0, @BytesReturned, 0)

0

4

Пётр
Если не затруднит, ответьте на 3 вопроса.
1) Через диспетчер закрыть не удается, есть ли какие то способы закрыть приложение?
2) Допустим у меня есть одна программа, которая при запуске закрывает другую программу. Я хочу при помощи вашего текста сделать свою программу независимой, то есть чтоб ее невозможно было закрыть сторонним приложением. Чтоб реализовать это, мне нужно всего лишь подставить PID процесса программы и запустить скрипт?
3) Как мне подставить PID процесса, если он каждый запуск меняется? Даже на примере вашей программы, PID каждый раз новый. Или я чего то не понимаю?

Отредактировано h1tCH (01.06.2015 16:43:31)

0

5

h1tCH написал(а):

1) Через диспетчер закрыть не удается, есть ли какие то способы закрыть приложение?

Способы конечно есть, но они не так просты и те кто не в теме, не смогут закрыть программу.

h1tCH написал(а):

Чтоб реализовать это, мне нужно всего лишь подставить PID процесса программы и запустить скрипт?

Это не скрипт а код программы. Его нужно компилировать и получить драйвер (*.sys) или приложение (*.exe) в зависимости от кода.

h1tCH написал(а):

3) Как мне подставить PID процесса, если он каждый запуск меняется?

Его можно узнать в диспетчере задач.

0

6

Пётр

Пётр написал(а):

Его можно узнать в диспетчере задач.

Так он же рандомный =) Каждый запуск PID другое число)

Пётр написал(а):

Его нужно компилировать и получить драйвер (*.sys) или приложение (*.exe) в зависимости от кода.

Хочу разобраться в теме, от которой далеко. Есть программа HxD хекс редактор, при запуске приложения этот хекс редактор автоматически закрывается. У меня есть Ваш код программы (самый первый код в первом посту). Простите за глупый вопрос - что менять в тексте? Если PID запущенного хекс редактора сейчас 2656.

0

7

Тогда используйте этот вариант программы. http://www.cyberforum.ru/attachments/464969d1418232261
Запускаете ее и указываете PID процесса.

0

8

Пётр написал(а):

Тогда используйте этот вариант программы. http://www.cyberforum.ru/attachments/464969d1418232261
Запускаете ее и указываете PID процесса.

Указываю PID процесса, добавляю. При закрытии Хекс редактора через крестик/диспетчер, программа закрывается с ошибкой. Не действует этот метод. Чем ваш драйвер плох? Или мою тему через него нельзя реализовать?

Отредактировано h1tCH (01.06.2015 19:57:17)

0

9

h1tCH написал(а):

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

При запуске какого приложения? И почему он закрывается?

0

10

Пётр написал(а):

При запуске какого приложения? И почему он закрывается?

онлайн игра, при запуске игры запускается защита SmartGuard, эта защита закрывает все стороннее ПО.

0

11

так что придумать то можно?)

0

12

h1tCH написал(а):

При закрытии Хекс редактора через крестик/диспетчер, программа закрывается с ошибкой.

Закрывается с какой ошибкой? Какая операционная система и ее разрядность?

0

13

http://s014.radikal.ru/i326/1506/7b/79d007ff3ee4.jpg

0

14

привет
этот драйвер должен работать на вин7 х64 ?
у меня все попытки запуска заканчиваются сообщением "Не удалось загрузть драйвер"
проверял и на готовых примерах и на скомпилинных, результат один((

0

15

atasher написал(а):

этот драйвер должен работать на вин7 х64 ?

Нет не должен. И тому много причин. Во первых, на х64 просто так нельзя перехватить функции ядра, переписав их адрес в таблице. Во вторых, у драйвера обязательно должна быть цифровая подпись (она стоит денег). И в третьих, драйвер должен быть скомпилирован для х64 системы, но делать это не имеет смысла из-за вышеописанных причин.

0

16

это очень странно
я видел проги которые врядли имеют лицензию для цифровой подписи
и при этом они работают на уровне нулевого кольца

а у меня даже не компилится пример на х64 из этой ссылки http://pure-basic.narod.ru/forum_files/ … er_x64.zip
вылетает ошибка фасма и вешает компилятор((

как это вылечить не в курсе?

0

17

Этот код драйвера бессмысленно компилировать под x64 потому что все равно работать не будет.

atasher написал(а):

я видел проги которые врядли имеют лицензию для цифровой подписи

В свойствах файла драйвера есть вкладка "Цифровые подписи"?

0

18

я компилил не этот драйвер, а тот что в примерах на х64

я что то делаю не так или эта прога не рабочая?

0

19

Какой пример компилировали?

0

20

дык он там один вроде)
driver_port_io.pb (pbdriverio_x64.sys)

мне этот драйвер вроде как и не нужен пока,
но факт в том что он не компилиться(

0

21

atasher написал(а):

не компилиться

У меня компилируется.

Что пишет компилятор?

0

22

ничего конкретного

"прекращена работа программы фасм.ехе"  потом  "программа фасм.ехе не работает"

потом
"прекращена работа программы PBCompiler.ехе"  потом  "программа PBCompiler.ехе не работает"

потом
"компилятор неожиданно завершил работу или отказал и будет перезапущен."

и все((

может, все таки, я что то делаю не так?

0

23

Может дело в антивирусе? Возможно он вызывает такие ошибки. Нужно попробовать его отключить на время компиляции.

0

24

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

я так понимаю что трабла где то в  Fasm.exe зарылась,
но как это лечить хз((

0

25

Случайно не в песочнице запускаете?

0

26

нет, для моих тестов песочница не подходит))

кста, узнал что проверку подписей можно отключать,
но защищенные проги это обнаруживают с лёту.

видимо придется отложить все эксперименты с ядром((

0


Вы здесь » PureBasic - форум » Kernel Driver » Драйвер, защищающий процесс от завершения