Search code examples
windowskerneldriverioctlwindows-kernel

Problem in DeviceIoControl dispatch routine


so im stuck at this problem , the DeviceControle dispatch routine is not even been invoked:

driver.cpp:

#include "PlaybackState.h"
 
 
 
 
playBackState* g_state;
UNICODE_STRING symlink;
UNICODE_STRING devName;
PDEVICE_OBJECT device = nullptr;
 
 
 
void melodyUnload(PDRIVER_OBJECT driverObj)
{
 
    delete g_state;
    IoDeleteSymbolicLink(&symlink);
    IoDeleteDevice(driverObj->DeviceObject);
 
}
 
NTSTATUS melodyCreateClose(PDEVICE_OBJECT device , PIRP irp)
{
    auto status = STATUS_SUCCESS;
 
    if (IoGetCurrentIrpStackLocation(irp)->MajorFunction == IRP_MJ_CREATE)
    {
        status = g_state->Start(device); // create thread
        //KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] Thread Created ! : 0x%08X\n", status));
 
    }
    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] melodyCreateClose invoked ...\n"));
    return CompReq(irp, status);
}
 
NTSTATUS melodyDeviceControl(PDEVICE_OBJECT, PIRP irp)
{
    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] Entered melodyDeviceControl !\n"));
    auto irpsp = IoGetCurrentIrpStackLocation(irp);
    auto& dic = irpsp->Parameters.DeviceIoControl;
    auto status = STATUS_SUCCESS;
    ULONG info = 0;
 
    switch (dic.IoControlCode)
    {
    case IOCTL_MEL_PLAY:
 
        if (dic.InputBufferLength == 0 || (dic.InputBufferLength % sizeof(note) != 0))
        {
            KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[-] STATUS_INVALID_BUFFER_SIZE !\n"));
            status = STATUS_INVALID_BUFFER_SIZE;
            break;
        }
 
        auto data = (note*)irp->AssociatedIrp.SystemBuffer;
        
        if (data == nullptr)
        {
            KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[-] STATUS_INVALID_PARAMETER !\n"));
            status = STATUS_INVALID_PARAMETER;
            break;
        }
        
        auto noteCount = dic.InputBufferLength / sizeof(note);
        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] callingB AddNotes ...\n"));
        status = g_state->AddNotes(data, noteCount);
 
        if (!NT_SUCCESS(status))
        {
            KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[-] failed calling AddNotes : 0x%08X!\n", status));
            break;
        }
        
        info = dic.InputBufferLength;
        break;
        
    }
    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] passed melodyDeviceControl ...\n"));
    return CompReq(irp, status, info);
}
 
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath)
{
    UNREFERENCED_PARAMETER(regPath);
    
    g_state = new(PagedPool)playBackState;
    if (g_state == nullptr)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
 
    driverObj->DriverUnload = melodyUnload;
    driverObj->MajorFunction[IRP_MJ_CREATE] = driverObj->MajorFunction[IRP_MJ_CLOSE] = melodyCreateClose;
    driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = melodyDeviceControl;
 
    symlink = RTL_CONSTANT_STRING(SYM_LINK);
    devName = RTL_CONSTANT_STRING(L"\\Device\\melodyDevice");
    
    auto status = STATUS_SUCCESS;
 
    do
    {
 
        status = IoCreateDevice(driverObj,
            0,
            &devName,
            FILE_DEVICE_UNKNOWN,
            0,
            FALSE,
            &device);
 
        if (!NT_SUCCESS(status))
        {
            break;
        }
 
        status = IoCreateSymbolicLink(&symlink, &devName);
 
        if (NT_SUCCESS(status))
        {
            break;
        }
 
    } while (false);
    
    if (!NT_SUCCESS(status))
    {
        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[-] error initializing device & shit : 0x%08X\n", status));
 
        delete(g_state);
 
        if (device)
        {
            IoDeleteDevice(device);
        }
 
        return status;
    }
 
    //device->Flags =| DO_BUFFERED_IO;
    
    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] evrything is good in DriverEntry : 0x%08X\n", status));
    
    return STATUS_SUCCESS;
}

main.cpp:

#include <Windows.h>
#include <stdio.h>
#include "..\MyDriver1\src\MelodyCommon.h"
 
int main()   
{
        
    HANDLE hDevice = CreateFile(SYM_LINK,
        GENERIC_WRITE,
        0,
        nullptr,
        OPEN_EXISTING,
        0,
        nullptr);
    
    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("[-] Failed to open device! Error: 0x%08X\n", GetLastError());
        return 1; 
    }
 
 
    note notes[10];
 
    for (int i = 0; i < _countof(notes); i++) {
        notes[i].freq = 400 + i * 30;
        notes[i].dur = 500;
        printf("[+] note[%d].freq = %d, note[%d].dur = %d !\n", i, notes[i].freq, i, notes[i].dur);
    }
 
    DWORD bytes;
 
    BOOL status = DeviceIoControl(hDevice,
        IOCTL_MEL_PLAY,
        notes,
        sizeof(notes),
        nullptr,
        0, 
        &bytes,
        nullptr);
 
    if (!status)
    {
        printf("[-] failed in DeviceIoControl : 0x%08X\n", status);
    }
 
 
    
 
    if (hDevice)
    {
        CloseHandle(hDevice);
    }
    
    system("pause");
    return 0;
}

MelodyCommon.h:

#pragma once
 
#define SYM_LINK L"\\??\\MelSymlink"
#define DRIVER_TAG '0LEM'
 
struct note // features of a note
{
    ULONG freq, dur, delay{ 0 }, repeat{1};
};
 
#define IOCTL_MEL_PLAY \
     CTL_CODE(0x8003, 0x800, METHOD_BUFFERED, FILE_ALL_ACCESS)

i checked with windbg , i have verified that IRP_MJ_DEVICE_CONTROL points to melodyDeviceControl. and the ([+] Entered melodyDeviceControl !) is not even reached! , all other dispatch routines work well, idk what is going on... pls help.


Solution

  • #define IOCTL_MEL_PLAY \
         CTL_CODE(0x8003, 0x800, METHOD_BUFFERED, FILE_ALL_ACCESS)
    

    Access in CTL_CODE must be 2 bits size. so in range [0, 3]. so we have only 4 variants here

    • FILE_ANY_ACCESS // 0
    • FILE_READ_ACCESS // 1
    • FILE_WRITE_ACCESS // 2
    • FILE_READ_ACCESS| FILE_WRITE_ACCESS // 3

    the FILE_ALL_ACCESS is 001f01ff not valid here at all

    CTL_CODE(0x8003, 0x800, METHOD_BUFFERED, FILE_ALL_ACCESS) expanded to c07fe000 so by fact DeviceType here is c07f and RequiredAccess is 3 (0xE000 >> 14) what is mean FILE_READ_ACCESS| FILE_WRITE_ACCESS. but you open file with GENERIC_WRITE, so you not have FILE_READ_ACCESS on handle. I/O manager must return STATUS_ACCESS_DENIED to you