Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Проблемы с написанием драйвера (https://forum.antichat.xyz/showthread.php?t=49824)

slesh 25.09.2007 15:45

Проблемы с написанием драйвера
 
Вот сталкнулся с такой проблемой:
Програма должна постоянно считывать
через из драйвера через:

ReadFile струткуру следующего типа:

typedef struct _TMySTRUC // структура описывающая запрос к драйверу
{
HANDLE z1;
HANDLE z2;
} TMySTRUC, *PMySTRUC;

ВОт не могу написать как именно осуществить запись со стороны драйвера.
к примеру:

Код:

TMySTRUC mystruc;
 mystruc->z1=11111;
 mystruc->z2=22222;

 irpStack = IoGetCurrentIrpStackLocation (Irp);
 if (irpStack->MajorFunction == IRP_MJ_READ)
 {
ВОт что сюда вставить, чтобы передаться струкруру
mystruc?????
 }

 Irp->IoStatus.Status = STATUS_SUCCESS;
 IoCompleteRequest(Irp, IO_NO_INCREMENT);
 return STATUS_SUCCESS;

Еще чуть запустался с IRP_MJ_READ и IRP_MJ_WRITE

КАк я понял irpStack->MajorFunction == IRP_MJ_READ
будет тогда когда програма будет читать данные из драйвера т.е. readfile, а IRP_MJ_WRITE - когда будет писать чтото драйверу.
Перебрал кучу документаций так толком и не понял как осуществить чтение и запись.

_Great_ 25.09.2007 16:19

какой тип ввода-вывода?
1) если buffered (DO_BUFFERED_IO), тогда Irp->AssotiatedIrp.SystemBuffer указывает на системный буффер, который потом будет скопирован в пользовательский выходной (если это IRP_MJ_READ) или в который уже скопирован входной (если это IRP_MJ_WRITE)

другие типы тебе пока не нужны.. запутаешься нафиг.
тебе нужно лишь проверить длину буффера и скопировать туда структуру

slesh 27.09.2007 16:58

Чтото начал делать в этоге при копировании идет BSOD
Вообще драйвер должен перехватывать запуск процессов.
И потом по требованию возвращать PID и PARENT последнего запущенного процесса.
Код функции обработчика:
Код:

if (irpStack->MajorFunction == IRP_MJ_READ)
 {
  DPRINT("READ");
  if (irpStack->Parameters.Read.Length < 8)
    {
            DPRINT("LENGTH < 8");
        Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL;
        Irp->IoStatus.Information  = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    } else
        {
          DPRINT("LENGTH OK");       
Еcли раскоментировать, то BSOD >>>        //RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &RUNPROC, 8);


          Irp->IoStatus.Status = status = STATUS_SUCCESS;
          IoCompleteRequest (Irp, IO_NO_INCREMENT);
      return status;
        }
 }

где
TRUNPROC RUNPROC
typedef struct _TRUNPROC
{
HANDLE parent;
HANDLE PID;
} TRUNPROC, *PRUNPROC;


И вот вопрос еще один. Как мне получать то, что выводится через DbgPrint?
Юзаю WinDbg. Т.е. я запускаю через него прогу, которая общается с драйвером, но почемуто сообщения от DbgPrint на экране они не появляются :(

Ni0x 27.09.2007 17:12

Путаешь. Для просмотра сообщений от DbgPrint тебе нужен DebugView от Sysinternals.
Сейчас посмотрю код.

Ky3bMu4 27.09.2007 21:33

Если я не ошибаюсь, то для передачи информации драйвер<->программа драйвер должен создать устройство, через которое будет передаваться инфа. Вот тебе:
http://www.wasm.ru/article.php?article=apihook_3 (см.Взаимодействие драйвера с приложением)
И вот: http://wasm.ru/article.php?article=drvw2k04

slesh 27.09.2007 22:27

не с устройсвом всё ок. всё создано отлично. И пашет отлично. А вот тока как именно драйвер должен передать ответ - хз.
На счет васма - процел всё - толком там не описано.

Ni0x 27.09.2007 22:51

Да сделай ты через DeviceIoControl, проще будет, один из аргументов функции - буфер для обратного ответа. Будешь передавать драйверу IOCTL коды.
Код:

#define IOCTL_GETPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, \
        METHOD_BUFFERED, \
        FILE_READ_DATA | FILE_WRITE_DATA)

А драйвер будет обрабатывать их.
Код:

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIrp;
...
NTSTATUS MyIrp(IN PDEVICE_OBJECT dev, IN PIRP pirp)
{
...
switch (ioctl_code)
        {
        case IOCTL_GETPID:
                GetPid();
                break;
        default:       
                ns = STATUS_INVALID_DEVICE_REQUEST;
        }
...


slesh 27.09.2007 23:12

с DbgPrint разобрался +

----------
Суть в том, что я юзаю DeviceIoControl для чуть другйо функции.
а именно - защита процесса. Чтобы его не могли выкинуть стандартными методами.
у меня он заюзан вот так:
if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
ProtectedPid = (HANDLE)irpStack->Parameters.DeviceIoControl.IoControlCode;

slesh 27.09.2007 23:26

2 Ni0x В принципе можно былобы и сделать как ты говоришь, но тогда таже проблема - чтение и запись.

Ni0x 27.09.2007 23:27

И в чем проблема использовать DeviceIoControl для всего?

slesh 28.09.2007 00:21

переписал на DeviceIoControl
но чуть не допер как получить параметр.
сделал вот что. но тут чегото не хватает. А именно знаний в С:
Код:

if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
 {
  switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  {
        case 0x12345:
            if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(HANDLE))
                {
------> Вот тут я туплю. Как правильно сделать? ProtectedPid=Irp->AssociatedIrp.SystemBuffer;
                                DPRINT("PID= %d",ProtectedPid);
                }
                break;
               
        default: status = STATUS_INVALID_DEVICE_REQUEST;
        }
 
 }


Ni0x 28.09.2007 00:33

Тут указаны примеры для разных методов:
Код:

stack = IoGetCurrentlrpStackLocation (Irp);
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE: case IRP_MJ_CLOSE: break;
case IRP_MJ_DEVICE_CONTROL:
switch (stack->Parameters.DeviceloControl.loControlCode)
{
case IOCTL_MY_BUFFERED:
InBuffer = Irp->AssociatedIrp.SystemBuffer;
InLength =  stack->Parameters.DeviceloControl.InputBuffer.Length;
OutBuffer = Irp->AssociatedIrp.SystemBuffer;
OutLength = stack->Parameters.DeviceloControl.OutputBufferLength;
case IOCTL_MY_IN_DIRECT:
//OutBuffer доступен только для чтения
InBuffer = Irp->AssociatedIrp.SystemBuffer;
InLength = stack->Parameters.DeviceloControl.InputBufferLength;
OutBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress );
OutLength = stack->Parameters.DeviceloControl.OutputBufferLength;
break;
case IOCTL_MY_OUT_DIRECT:
//OutBuffer доступен для чтения/записи
InBuffer = Irp->AssociatedIrp.SystemBuffer;
InLength = stack->Parameters.DeviceloControl.InputBufferLength;
OutBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress);
OutLength = stack->Parameters.DeviceloControl.OutputBufferLength; break;
case IOCTL_MY_NEITHER:
InBuffer = irpStack->Parameters.DeviceloControl.TypeInputBuffer;
InLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
OutBuffer = Irp->UserBuffer;
OutLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
break;

Также обязательно прочитай:
Цитата:

При использовании буферизованного метода, Диспетчер ввода/вывода выделяет в системной невыгружаемой памяти промежуточный буфер, размер которого равен максимальному из размеров буферов InBuffer и OutBuffer. Если при запросе был определен InBuffer и его длина не нулевая, содержание InBuffer копируется в промежуточный буфер. В любом случае, адрес промежуточного буфера помещается в IRP в поле Associatedlrp.SystemBuffer. Затем IRP, содержащий запрос, передается драйверу.
Данные, находящиеся в промежуточном буфере, могут читаться и перезаписываться драйвером. Затем драйвер размещает в промежуточном буфере данные, которые нужно вернуть в OutBuffer.
При завершении запроса ввода/вывода, если OutBuffer был определен при запросе ввода/вывода и его длина не нулевая, Диспетчер ввода/вывода копирует из промежуточного буфера в OutBuffer столько байтов, сколько было указано в поле 1гр->IoStatus.Information. После этого, как и при любом буферизированном запросе Ввода/вывода, Диспетчер ввода/вывода освобождает промежуточный буфер.
При использовании методов METHOD_IN_DIRECT и METHOD_OUT_ DIRECT, буфер InBuffer, если он определен в запросе ввода/вывода и его длина не нулевая, обрабатывается в точности так же, как и при буферизованном вводе/выводе. В этом случае выделяется промежуточный буфер, в него копируется InBuffer, указатель на промежуточный буфер помещается в IRP в поле Associatedlrp.SystemBuffer.
Буфер OutBuffer, если он определен в запросе ввода/вывода и его длина не нулевая, обрабатывается в соответствии с прямым вводом/выводом. В этом случае адрес проверяется на возможность доступа (запись или чтение), производится закрепление физических страниц в памяти, и создается таблица описания памяти MDL, описывающая OutBuffer. Указатель на MDL передается в поле Irp->MdlAddress.
При использовании метода METHOD_NEITHER, оба буфера передаются в соответствии с методом Neither. To есть, не производится проверка доступности памяти, не выделяются промежуточные буфера и не создаются MDL. В пакете IRP передаются виртуальные адреса буферов в пространстве памяти инициатора запроса ввода/вывода. Адрес буфера OutBuffer передается в фиксированной части IRP в поле Irp-
>UserBuffer, адрес буфера InBuffer передается в стеке размещения ввода/вывода в поле stack->Parameters.DeviceControl.TypeInputBuffer.

_Great_ 28.09.2007 08:58

Цитата:

Сообщение от Ky3bMu4
Если я не ошибаюсь, то для передачи информации драйвер<->программа драйвер должен создать устройство, через которое будет передаваться инфа. Вот тебе:
http://www.wasm.ru/article.php?article=apihook_3 (см.Взаимодействие драйвера с приложением)
И вот: http://wasm.ru/article.php?article=drvw2k04

Я тебя умоляю, если ты не шаришь в теме, не пиши

slesh 28.09.2007 15:30

подскажите что я делаю не так. почему BSOD?
При установке ProtectedPid - ставится всё нормально и пашет отлично.
А при чтении его - BSOD. читаю через

PID,TrId:dword;
DeviceIoControl(hDriver, $23456, nil, 0, @PID, 4, TrId, nil);

Вот код обработчика
Код:

HANDLE ProtectedPid;

NTSTATUS DriverDispatcher(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
 NTSTATUS status;
 PIO_STACK_LOCATION irpStack;
 irpStack = IoGetCurrentIrpStackLocation (Irp);
 
if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
 {
  switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  {
        case 0x12345:
            if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(HANDLE))
                {
                     
                                ProtectedPid=*(HANDLE *)Irp->AssociatedIrp.SystemBuffer;
                                DPRINT("PID= %d",ProtectedPid);
                }
                break;
        case 0x23456:
        if (irpStack->Parameters.Read.Length < 4)
    {
            DPRINT("LENGTH < 4");
        Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL;
        Irp->IoStatus.Information  = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }
        else
        {
    DPRINT("LENGTH OK");       
    Irp->IoStatus.Information  = 4;
// чтото тут я не мойму как реализовать.
        *(HANDLE *)Irp->AssociatedIrp.SystemBuffer=ProtectedPid;
        Irp->IoStatus.Status = status = STATUS_SUCCESS;
          IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return status;
        }
        break;
       
        default: status = STATUS_INVALID_DEVICE_REQUEST;
        }
 
 }

Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);

 return status;
 }


_Great_ 28.09.2007 21:28

Кто тебе сказал что ты можешь какие угодно io control code задавать?
Юзай макрос IOCTL_CODE()
Самое главное - тип ввода-вывода (младшие 2 бита), у тебя видно тип не buffered во втором случае (да и в первом тоже)

slesh 28.09.2007 22:56

2 _Great_ Ты имеешь ввиду что именно через CTL_CODE и истанавливаются прва на запись, чтение и мето ввода-вывод?

Вот еще сталкнулся с такой проблемой. Иногда почемуто програма не может связаться с драйвером. Драйвер у меня как сервис. Поэтому я делаю:
net stop MyDRV
потом перекомпиливаю драйвер
затем: net start MyDRV
Все пахало нормально. но потом через несколько перезагрузок почемуто из програмы не возможно связаться с драйвером. т.е.
CreateFile('\\.\MyDRVS', GENERIC_ALL, 0, nil, OPEN_EXISTING, 0, 0);
возвращает INVALID_HANDLE_VALUE
Хотя драйвер пашет нормально - по дебаговым сообщением видно что создания процессов перехватываются. НО связи по сей час нет. уже перезагружался пару раз - дохлое дело.

Также заметил один интерестный факт. Вроде все програмы и DLL ки виндовые отображаются на память, а драйвера получается что нет? потому что при запущенном драйвере можно спакойно удалить файл драйвара.

Ni0x 28.09.2007 23:50

А самому лень посмотреть?
winioctl.h
Код:

#define CTL_CODE( DeviceType, Function, Method, Access ) (               
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
)


KEZ 29.09.2007 00:17

Цитата:

Также заметил один интерестный факт. Вроде все програмы и DLL ки виндовые отображаются на память, а драйвера получается что нет? потому что при запущенном драйвере можно спакойно удалить файл драйвара.
А тебе драйвера то не рано ещё писать? ; )
И DLL и EXE любую можно удалить без проблем как и драйвер.
Просто после загрузки драйвера винда не лочит попытки удаления его файла на диске, а для user-mode модулей - лочит. Т.е. файл остается открытым для user-mode модулей и закрывается сразу после загрузки для драйверов (а нахер ему быть открытым).
Но, ИМХО, одно из двух писал НЕ ты. Либо "драйвер не отображается на память", либо сам драйвер ; )

Учитесь как надо кодить
http://img216.imageshack.us/img216/2995/dibzb7.jpg
всё хотел кому-нибудь показать чтоб оценили
гыгыг

_Great_ 29.09.2007 07:53

Цитата:

Сообщение от slesh
2 _Great_ Ты имеешь ввиду что именно через CTL_CODE и истанавливаются прва на запись, чтение и мето ввода-вывод?

Некоторые биты ио контрол кода служебные. А ты рандомно задаешь все число. Поэтому и глюки

Цитата:

CreateFile('\\.\MyDRVS', GENERIC_ALL, 0, nil, OPEN_EXISTING, 0, 0);
возвращает INVALID_HANDLE_VALUE
GetLastError() ?

slesh 29.09.2007 08:01

2 _Great_ спасибо за разъяснение. Переписал все через CTL_CODE.
Но всеже также осталась проблема с доступом к драйверу.
GetLastError дает код ошибки - 317

_Great_ 29.09.2007 08:41

Хм.. у меня описания к нему вобще нет.
Давай полный сорс драйвера в студию + кусок сорса программы управления, которая пытается открыть девайс, созданный драйвером
Кстати, когда открываешь девайс, надо задавать флаги общего доступа FILE_SHARE_READ|FILE_SHARE_WRITE, а у тебя там ноль. Иначе будут проблемы. С этой вряд ли связано, но на будущее учти

KEZ 29.09.2007 11:37

Зачем открывать с GENERIC_ALL ? У нее GENERIC_EXECUTE вообще-то ещё стоит. GENERIC_READ|GENERIC_WRITE используй
Кстати, зачем тебе вообще все это, ты же пишешь обычный пинч етц, скрывающий процесс по присланному PID (наверное через хук sdt).
Почему бы просто не рассматривать IRP_MJ_CONTROL и не делать в юзермоде DeviceIoControl() ?

slesh 29.09.2007 12:39

Суть драйвера такова: Он должен перехватывать запуск процессов и заносить в лог.
также она должен защищать програму от выгрузки,
а именно через перехват функции NtOpenProcess
Сначало я начал делать всё без драйвера.
т.е. через инжект своей DLL'ки которая перехватывала запуск программы.
Но не на всех компах работало стабильно. То фаер матерился, то авир.
Бывало аткое, что пашет отлично, но на некоторых прогах - вылетает.


Вот для теста драйвера програма:
Код:

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.

Вот код драйвера:
Код:

#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;

}


KEZ 29.09.2007 14:30

Софт айс + брек на DriverDispatcher

_Great_ 29.09.2007 14:47

Цитата:

#define IOCTL_GETPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
лучше file_all_access

Цитата:

#ifdef DEBUG
#define DPRINT DbgPrint
#else
#define DPRINT
#endif
дурной тон. лучше KdPrint(())

Цитата:

//снимаем перехват
__asm
{
cli // запрещаем прерывания
mov eax, cr0
mov CR0Reg,eax
and eax,0xFFFEFFFF // сбросить WP bit
mov cr0, eax
}
запрещать прерывания не поможет на многопроцессорной системе. нам нужно делать KfRaiseIrql( HIGH_LEVEL )

Цитата:

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;
}
}
что это за чудо и зачем оно надо

Цитата:

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

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

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

Цитата:

rc = PsSetCreateProcessNotifyRoutine(*CreateProcessNoti fyRoutine, FALSE);
Что за нах? Откуда звездочка? У тебя ЭТО вообще компилируется? Сомневаюсь... сильно...

slesh 29.09.2007 23:37

rc = PsSetCreateProcessNotifyRoutine(*CreateProcessNoti fyRoutine, FALSE); - это как раз и есть фишка с помощью которой можно отлавливать запуск и заврешение программы. Компилится запросто. Пример был взят с rootkits.ru а именно: http://rootkits.ru/viewtopic.php?id=32

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

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

нашел в чем была проблема. почему я не мог связаться с драйвером. по умолчанию при открытии нужно было возвращаться статус: STATUS_SUCCESS;
о чем я забыл.

_Great_ 30.09.2007 08:57

У тебя вообще в драйвере КУЧА ошибок. У тебя будет множество глюков вплоть до бсодов, с ними связанных

slesh 30.09.2007 16:30

2 _Great_ чуть исправил драйвер. Вроде ошибок не вижу, т.к. делал всё на базе примеров которые взял с wasm.
Шас тестировал его - работате отлично глюков вообще не заметил.

_Great_ 06.10.2007 18:44

Неточности связанные с обработкой ошибок:

Код:

else
 {
  DPRINT("IoCreateSymbolicLink ERROR");
 }
}
else
{
DPRINT("IoCreateDevice ERROR");
}

Кроме вывода сообщения было бы желательно почистить всё, что успешно создалось, и выйти из DriverEntry с ошибочным статусом

slesh 06.10.2007 23:21

я вообще это делал для отладки. в последствии всё исправил.


Время: 19:56