Github-ioctlfuzzer&ioctlbf

最近做二进制安全研究实习生,主要看的东西是驱动,在Github上发现了款做Fuzz的工具,适用场景说大不大,说小不小。因为它支持的系统只到Windows7(x86+x64)。但是漏洞挖掘嘛,Fuzz还是很重要的,有源码自然要看看了,学习下前辈们的Fuzz方法
大部分的记录我都是直接标记在了源码中,有兴趣的可以直接在我的Github上Clone或者Fork<请务必先仔细看Readme.md>都行,这里放出的只是在看源码中遇见的一些比较重要的问题
由于编码的原因,所以都是英文记录,英语渣,凑合看吧
Github:https://github.com/Iolop/ioctlfuzzer

Important Funtion src\driver\src\driver.cpp

  • KernelGetModuleBase src\driver\src\r0_common\common.cpp
  • KernelGetExportAddress
  • KeAddSystemServiceTable

    seems like an interesting function. Not sure how does this routine works , here is its assembly code.a way to find ssdt in x64 platform

kd> uf nt!KeAddSystemServiceTable
nt!KeAddSystemServiceTable:
83dc40f2 8bff            mov     edi,edi
83dc40f4 55              push    ebp
83dc40f5 8bec            mov     ebp,esp // create stack,but no sub esp??
83dc40f7 837d1801        cmp     dword ptr [ebp+18h],1
83dc40fb 7760            ja      nt!KeAddSystemServiceTable+0x6b (83dc415d)  Branch <END>

nt!KeAddSystemServiceTable+0xb:
83dc40fd 8b4518          mov     eax,dword ptr [ebp+18h]
83dc4100 c1e004          shl     eax,4
83dc4103 83b8c009da8300  cmp     dword ptr nt!KeServiceDescriptorTable (83da09c0)[eax],0
83dc410a 7551            jne     nt!KeAddSystemServiceTable+0x6b (83dc415d)  Branch

nt!KeAddSystemServiceTable+0x1a:                                                            Check the instructions before and the valid address
83dc410c 8d88000ada83    lea     ecx,nt!KeServiceDescriptorTableShadow (83da0a00)[eax]
83dc4112 833900          cmp     dword ptr [ecx],0
83dc4115 7546            jne     nt!KeAddSystemServiceTable+0x6b (83dc415d)  Branch

nt!KeAddSystemServiceTable+0x25:
83dc4117 837d1801        cmp     dword ptr [ebp+18h],1
83dc411b 8b5508          mov     edx,dword ptr [ebp+8]
83dc411e 56              push    esi
83dc411f 8b7510          mov     esi,dword ptr [ebp+10h]
83dc4122 57              push    edi
83dc4123 8b7d14          mov     edi,dword ptr [ebp+14h]
83dc4126 8911            mov     dword ptr [ecx],edx
83dc4128 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
83dc412b 8988040ada83    mov     dword ptr nt!KeServiceDescriptorTableShadow+0x4 (83da0a04)[eax],ecx
83dc4131 89b0080ada83    mov     dword ptr nt!KeServiceDescriptorTableShadow+0x8 (83da0a08)[eax],esi
83dc4137 89b80c0ada83    mov     dword ptr nt!KeServiceDescriptorTableShadow+0xc (83da0a0c)[eax],edi
83dc413d 7418            je      nt!KeAddSystemServiceTable+0x65 (83dc4157)  Branch

nt!KeAddSystemServiceTable+0x4d:
83dc413f 8990c009da83    mov     dword ptr nt!KeServiceDescriptorTable (83da09c0)[eax],edx
83dc4145 8988c409da83    mov     dword ptr nt!KeServiceDescriptorTable+0x4 (83da09c4)[eax],ecx
83dc414b 89b0c809da83    mov     dword ptr nt!KeServiceDescriptorTable+0x8 (83da09c8)[eax],esi
83dc4151 89b8cc09da83    mov     dword ptr nt!KeServiceDescriptorTable+0xc (83da09cc)[eax],edi

nt!KeAddSystemServiceTable+0x65:
83dc4157 5f              pop     edi
83dc4158 b001            mov     al,1
83dc415a 5e              pop     esi
83dc415b eb02            jmp     nt!KeAddSystemServiceTable+0x6d (83dc415f)  Branch

nt!KeAddSystemServiceTable+0x6b:
83dc415d 32c0            xor     al,al

nt!KeAddSystemServiceTable+0x6d:
83dc415f 5d              pop     ebp
83dc4160 c21400          ret     14h
  • SetUpHooks-Hook x64 platform src\driver\src

    Keep walking in this file, I found this tool seems store fuzz options in register
    It contains three functions

    • SaveFuzzerOptions
    • DeleteSavedFuzzerOptions
    • LoadFuzzerOptions
  • DriverDispatch

    most important and complicated

NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    PIO_STACK_LOCATION stack;
    NTSTATUS ns = STATUS_SUCCESS;

    Irp->IoStatus.Status = ns;
    Irp->IoStatus.Information = 0;

    stack = IoGetCurrentIrpStackLocation(Irp);

    if (stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
    {
        ULONG Code = stack->Parameters.DeviceIoControl.IoControlCode;       
        ULONG Size = stack->Parameters.DeviceIoControl.InputBufferLength;
        PREQUEST_BUFFER Buff = (PREQUEST_BUFFER)Irp->AssociatedIrp.SystemBuffer;   

#ifdef DBG_IO

        DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_DEVICE_CONTROL 0x%.8x\n", Code);
#endif
        Irp->IoStatus.Information = Size;

        switch (Code)
        {
        case IOCTL_DRV_CONTROL:
            {
                Buff->Status = S_ERROR;

                if (Size >= sizeof(REQUEST_BUFFER))//inputBufferLength >= struct<REQUEST_BUFFER>
                {
                    ULONG KdCommandLength = 0;
                    IOCTL_FILTER Flt;                   
                    RtlZeroMemory(&Flt, sizeof(Flt));

                    if (Buff->AddObject.bDbgcbAction && Size > sizeof(REQUEST_BUFFER))
                    {
                        // check for zero byte at the end of the string
                        if (Buff->Buff[Size - sizeof(REQUEST_BUFFER) - 1] != 0)
                        {         
                            goto _bad_addobj_request;
                        }

                        // debugger command available
                        KdCommandLength = strlen(Buff->Buff) + 1;
                    }

                    switch (Buff->Code)
                    {
                    case C_ADD_DRIVER:
                    case C_ADD_DEVICE:
                    case C_ADD_PROCESS:
                    case C_ADD_IOCTL:
                        {
                            // check for zero byte at the end of the string
                            if (Buff->AddObject.szObjectName[MAX_REQUEST_STRING - 1] != 0)
                            {         
                                goto _bad_addobj_request;
                            }

                            if (Buff->Code == C_ADD_IOCTL)
                            {
                                Flt.IoctlCode = Buff->AddObject.IoctlCode;
                            }
                            else
                            {
                                ANSI_STRING asName;

                                RtlInitAnsiString(
                                    &asName,
                                    Buff->AddObject.szObjectName
                                );

                                NTSTATUS status = RtlAnsiStringToUnicodeString(&Flt.usName, &asName, TRUE);
                                if (!NT_SUCCESS(status))
                                {
                                    DbgMsg(__FILE__, __LINE__, "RtlAnsiStringToUnicodeString() fails; status: 0x%.8x\n", status);
                                    goto _bad_addobj_request;
                                }
                            }                           

                            switch (Buff->Code)
                            {
                            case C_ADD_DRIVER:

                                // filter by driver file name/path
                                Flt.Type = FLT_DRIVER_NAME;
                                break;

                            case C_ADD_DEVICE:

                                // filter by device name
                                Flt.Type = FLT_DEVICE_NAME;
                                break;

                            case C_ADD_PROCESS:

                                // filter by caller process executable file name/path
                                Flt.Type = FLT_PROCESS_PATH;
                                break;

                            case C_ADD_IOCTL:

                                // filter by IOCTL control code value
                                Flt.Type = FLT_IOCTL_CODE;
                                break;
                            }   

                            KeWaitForMutexObject(&m_CommonMutex, Executive, KernelMode, FALSE, NULL);

                            __try
                            {
                                PIOCTL_FILTER f_entry = NULL;

                                if (Buff->AddObject.bDbgcbAction)
                                {
                                    // add rule into the debugger commands list
                                    if (f_entry = FltDbgcbAdd(&Flt, KdCommandLength))
                                    {
                                        Buff->Status = S_SUCCESS;

                                        if (!m_bEnableDbgcb)
                                        {
                                            // try to reload symbols
                                            if (dbg_exec(".reload"))
                                            {
                                                // kernel debugger communication engine is available and initialized
                                                m_bEnableDbgcb = TRUE;
                                            }                       
                                            else
                                            {
                                                DbgMsg(
                                                    __FILE__, __LINE__,
                                                    __FUNCTION__"(): Kernel debugger interaction is not available\n"
                                                );
                                            }
                                        }                                       
                                    }
                                }
                                else if (Buff->AddObject.bAllow)
                                {
                                    // add filter rule into the ALLOW list
                                    if (f_entry = FltAllowAdd(&Flt, KdCommandLength))
                                    {
                                        Buff->Status = S_SUCCESS;
                                    }
                                }   
                                else
                                {
                                    // add filter rule into the DENY list
                                    if (f_entry = FltDenyAdd(&Flt, KdCommandLength))
                                    {
                                        Buff->Status = S_SUCCESS;
                                    }
                                }

                                if (f_entry)
                                {
                                    f_entry->bDbgcbAction = Buff->AddObject.bDbgcbAction;
                                    if (KdCommandLength > 0)
                                    {
                                        strcpy(f_entry->szKdCommand, Buff->Buff);

                                        if (Buff->Code == C_ADD_IOCTL)
                                        {
                                            DbgPrint(
                                                "<?dml?>" __FUNCTION__ "(): ControlCode=0x%.8x KdCommand=<exec cmd=\"%s\">%s</exec>\n",
                                                f_entry->IoctlCode, f_entry->szKdCommand, f_entry->szKdCommand
                                            );
                                        }
                                        else
                                        {
                                            DbgPrint(
                                                "<?dml?>" __FUNCTION__ "(): Object=\"%wZ\" KdCommand=<exec cmd=\"%s\">%s</exec>\n",
                                                &f_entry->usName, f_entry->szKdCommand, f_entry->szKdCommand
                                            );
                                        }
                                    }
                                }
                            }   
                            __finally
                            {
                                KeReleaseMutex(&m_CommonMutex, FALSE);
                            }   

                            if (Buff->Status != S_SUCCESS &&
                                Buff->Code != C_ADD_IOCTL)
                            {
                                RtlFreeUnicodeString(&Flt.usName);
                            }
_bad_addobj_request:
                            break;
                        }

                    case C_DEL_OPTIONS:
                        {
                            DeleteSavedFuzzerOptions();
                            break;
                        }                   

                    case C_SET_OPTIONS:
                        {
                            KeWaitForMutexObject(&m_CommonMutex, Executive, KernelMode, FALSE, NULL);   

                            __try
                            {
                                m_FuzzOptions = Buff->Options.Options;

                                if (!(m_FuzzOptions & FUZZ_OPT_NO_SDT_HOOKS))
                                {
                                    // hook nt!NtDeviceIoControlFile() syscall
                                    m_bHooksInitialized = SetUpHooks();
                                }

                                if (!(m_FuzzOptions & FUZZ_OPT_LOG_IOCTL_GLOBAL) && m_hIoctlsLogFile)
                                {
                                    ZwClose(m_hIoctlsLogFile);
                                    m_hIoctlsLogFile = NULL;

                                    DbgMsg(__FILE__, __LINE__, "[+] IOCTLs log closed \"%wZ\"\n", &m_usIoctlsLogFilePath);
                                }

                                m_FuzzingType = Buff->Options.FuzzingType;
                                m_UserModeData = Buff->Options.UserModeData;
#ifdef _X86_
                                m_FuzzThreadId = (HANDLE)Buff->Options.FuzzThreadId;
#elif _AMD64_
                                PLARGE_INTEGER FuzzThreadId = (PLARGE_INTEGER)&m_FuzzThreadId;
                                FuzzThreadId->HighPart = 0;
                                FuzzThreadId->LowPart = Buff->Options.FuzzThreadId;
#endif                                 
                                if (m_FuzzOptions & FUZZ_OPT_FUZZ_BOOT)
                                {
                                    // fair fizzing is not available in the boot fuzzing mode
                                    m_FuzzOptions &= ~FUZZ_OPT_FUZZ_FAIR;

                                    // boot fuzzing mode has been enabled
                                    SaveFuzzerOptions();
                                    m_FuzzOptions = 0;
                                }
                                else
                                {
                                    DeleteSavedFuzzerOptions();
                                }

                                if ((m_FuzzOptions & FUZZ_OPT_LOG_EXCEPTIONS) &&
                                    Buff->Options.KiDispatchException_Offset > 0)
                                {
                                    // ofsset of unexported function for exceptions monitoring
                                    m_KiDispatchException_Offset = Buff->Options.KiDispatchException_Offset;

                                    if (!m_bKiDispatchExceptionHooked)
                                    {
                                        // set up hooks for exception monitoring
                                        m_bKiDispatchExceptionHooked = ExcptHook();
                                    }

                                    m_bLogExceptions = TRUE;
                                }                           
                                else
                                {
                                    m_bLogExceptions = FALSE;
                                }

                                Buff->Status = S_SUCCESS;
                            }                           
                            __finally
                            {
                                KeReleaseMutex(&m_CommonMutex, FALSE);
                            }                           

                            break;
                        }

                    case C_GET_DEVICE_INFO:
                        {
                            // check for zero byte at the end of the string
                            if (Size > sizeof(REQUEST_BUFFER) &&
                                Buff->Buff[Size - sizeof(REQUEST_BUFFER) - 1] == 0)
                            {         
                                ANSI_STRING asDeviceName;
                                UNICODE_STRING usDeviceName;

                                RtlInitAnsiString(
                                    &asDeviceName,
                                    Buff->Buff
                                );

                                NTSTATUS status = RtlAnsiStringToUnicodeString(&usDeviceName, &asDeviceName, TRUE);
                                if (NT_SUCCESS(status))
                                {
                                    // open disk device object
                                    PDEVICE_OBJECT TargetDeviceObject = NULL;
                                    PFILE_OBJECT TargetFileObject = NULL;
#ifdef USE_IoGetDeviceObjectPointer
                                    status = IoGetDeviceObjectPointer(
                                        &usDeviceName,
                                        GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
                                        &TargetFileObject,
                                        &TargetDeviceObject
                                    );
                                    if (NT_SUCCESS(status))     
#else
                                    if (TargetFileObject = GetDeviceObjectPointer(&usDeviceName))
                                    {
                                        TargetDeviceObject = TargetFileObject->DeviceObject;
                                    }

                                    if (TargetFileObject)
#endif
                                    {
                                        // pass device object information to the caller
                                        Buff->DeviceInfo.DeviceObjectAddr = TargetDeviceObject;
                                        if (TargetDeviceObject->DriverObject)
                                        {
                                            Buff->DeviceInfo.DriverObjectAddr = TargetDeviceObject->DriverObject;

                                            // get driver object name by pointer
                                            POBJECT_NAME_INFORMATION NameInfo = GetObjectName(TargetDeviceObject->DriverObject);
                                            if (NameInfo)
                                            {
                                                ANSI_STRING asDriverName;
                                                status = RtlUnicodeStringToAnsiString(&asDriverName, &NameInfo->Name, TRUE);
                                                if (NT_SUCCESS(status))
                                                {
                                                    strncpy(
                                                        Buff->DeviceInfo.szDriverObjectName,
                                                        asDriverName.Buffer,
                                                        min(MAX_REQUEST_STRING - 1, asDriverName.Length)
                                                    );

                                                    RtlFreeAnsiString(&asDriverName);
                                                }
                                                else
                                                {
                                                    DbgMsg(__FILE__, __LINE__, "RtlUnicodeStringToAnsiString() fails; status: 0x%.8x\n", status);                                               
                                                }

                                                ExFreePool(NameInfo);
                                            }

                                            // get loader information entry for the driver
                                            PLDR_DATA_TABLE_ENTRY pModuleEntry = (PLDR_DATA_TABLE_ENTRY)
                                                TargetDeviceObject->DriverObject->DriverSection;

                                            if (pModuleEntry &&
                                                MmIsAddressValid(pModuleEntry) &&
                                                ValidateUnicodeString(&pModuleEntry->FullDllName))
                                            {
                                                ANSI_STRING asDllName;
                                                status = RtlUnicodeStringToAnsiString(&asDllName, &pModuleEntry->FullDllName, TRUE);
                                                if (NT_SUCCESS(status))
                                                {
                                                    strncpy(
                                                        Buff->DeviceInfo.szDriverFilePath,
                                                        asDllName.Buffer,
                                                        min(MAX_REQUEST_STRING - 1, asDllName.Length)
                                                    );

                                                    RtlFreeAnsiString(&asDllName);
                                                }
                                                else
                                                {
                                                    DbgMsg(__FILE__, __LINE__, "RtlUnicodeStringToAnsiString() fails; status: 0x%.8x\n", status);                                               
                                                }
                                            }

                                            Buff->Status = S_SUCCESS;
                                        }                                 

                                        ObDereferenceObject(TargetFileObject);
                                    }
#ifdef USE_IoGetDeviceObjectPointer
                                    else
                                    {
                                        DbgMsg(
                                            __FILE__, __LINE__,
                                            "IoGetDeviceObjectPointer() fails for \"%wZ\", status: 0x%.8x\n",
                                            &usDeviceName, status
                                        );                                               
                                    }
#endif
                                    RtlFreeUnicodeString(&usDeviceName);         
                                }
                                else
                                {
                                    DbgMsg(__FILE__, __LINE__, "RtlAnsiStringToUnicodeString() fails; status: 0x%.8x\n", status);
                                }
                            }

                            break;
                        }

                    case C_GET_OBJECT_NAME:
                        {
                            PFILE_OBJECT pFileObject = NULL;
                            NTSTATUS ns = ObReferenceObjectByHandle(
                                Buff->ObjectName.hObject,
                                0,
                                *IoFileObjectType,
                                KernelMode,
                                (PVOID *)&pFileObject,
                                NULL
                            );
                            if (NT_SUCCESS(ns))
                            {
                                if (pFileObject->DeviceObject)
                                {
                                    // get name of the object
                                    POBJECT_NAME_INFORMATION NameInfo = GetObjectName(pFileObject->DeviceObject);
                                    if (NameInfo)
                                    {                       
                                        ANSI_STRING asName;
                                        ns = RtlUnicodeStringToAnsiString(&asName, &NameInfo->Name, TRUE);
                                        if (NT_SUCCESS(ns))
                                        {
                                            strncpy(
                                                Buff->ObjectName.szObjectName,
                                                asName.Buffer,
                                                min(MAX_REQUEST_STRING - 1, asName.Length)
                                            );

                                            Buff->Status = S_SUCCESS;

                                            RtlFreeAnsiString(&asName);
                                        }
                                        else
                                        {
                                            DbgMsg(__FILE__, __LINE__, "RtlUnicodeStringToAnsiString() fails; status: 0x%.8x\n", ns);
                                        }

                                        M_FREE(NameInfo);
                                    }
                                }

                                ObDereferenceObject(pFileObject);
                            }
                            else
                            {
                                DbgMsg(__FILE__, __LINE__, "ObReferenceObjectByHandle() fails; status: 0x%.8x\n", ns);
                            }                 

                            break;
                        }

                    case C_CHECK_HOOKS:
                        {
                            if (m_bKiDispatchExceptionHooked ||
                                m_bHooksInitialized)
                            {
                                Buff->CheckHooks.bHooksInstalled = TRUE;
                            }
                            else
                            {
                                Buff->CheckHooks.bHooksInstalled = FALSE;
                            }

                            break;
                        }
                    }
                }

                break;
            }           

        default:
            {
                ns = STATUS_INVALID_DEVICE_REQUEST;
                Irp->IoStatus.Information = 0;
                break;
            }           
        }
    }
    else if (stack->MajorFunction == IRP_MJ_CREATE)
    {
        DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_CREATE\n");

#ifdef DBGPIPE

        DbgOpenPipe();
#endif
        KeWaitForMutexObject(&m_CommonMutex, Executive, KernelMode, FALSE, NULL);

        __try
        {
            // delete all filter rules
            FltAllowFlushList();
            FltDenyFlushList();
            FltDbgcbFlushList();

            m_FuzzProcess = PsGetCurrentProcess();
            ObReferenceObject(m_FuzzProcess);
        }       
        __finally
        {
            KeReleaseMutex(&m_CommonMutex, FALSE);
        }       
    }
    else if (stack->MajorFunction == IRP_MJ_CLOSE)
    {
        DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_CLOSE\n");       

        KeWaitForMutexObject(&m_CommonMutex, Executive, KernelMode, FALSE, NULL);   

        __try
        {
            // delete all filter rules
            FltAllowFlushList();
            FltDenyFlushList();
            FltDbgcbFlushList();

            m_FuzzOptions = 0;

            if (m_FuzzProcess)
            {
                ObDereferenceObject(m_FuzzProcess);
                m_FuzzProcess = NULL;
            }
        }
        __finally
        {
            KeReleaseMutex(&m_CommonMutex, FALSE);
        }               

#ifdef DBGPIPE

        DbgClosePipe();
#endif

        if (m_hIoctlsLogFile)
        {
            ZwClose(m_hIoctlsLogFile);
            m_hIoctlsLogFile = NULL;

            DbgMsg(__FILE__, __LINE__, "[+] IOCTLs log closed \"%wZ\"\n", &m_usIoctlsLogFilePath);
        }
    }

    if (ns != STATUS_PENDING)
    {       
        Irp->IoStatus.Status = ns;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }

    return ns;
}

After fixing the path,i get sys file. But when I run the ioctlfuzzer.exe in Win7 x86,it seems this exe autoload sys!
What…?
Found a piece of code in ioctlfuzzer.cpp,it could release resources.Fuxx.

Seems this exe only load the driver and set it on boot mode.So the DriverDispatch() is the actually fuzzer function.

Ring3:

  • DrvDeviceRequest()-DeviceIoControl(IOCTL_DRV_CONTROL)
    这里写图片描述
    这里写图片描述

In DriverDispatch()
A important struct REQUEST_BUFFER

typedef struct _REQUEST_BUFFER
{
    // operation status (see S_* definitions)
    ULONG Status;

    // operation code (see C_* definitions)
    ULONG Code;

    union
    {
        struct
        {
            ULONG Options;
            ULONG FuzzThreadId;
            FUZZING_TYPE FuzzingType;
            PUSER_MODE_DATA UserModeData;
            ULONG KiDispatchException_Offset;

        } Options;

        struct
        {
            PVOID DeviceObjectAddr;
            PVOID DriverObjectAddr;
            char szDriverObjectName[MAX_REQUEST_STRING];
            char szDriverFilePath[MAX_REQUEST_STRING];

        } DeviceInfo;

        struct
        {
            // for C_ADD_IOCTL
            ULONG IoctlCode;

            // for all C_ADD_*
            BOOLEAN bAllow;

            // for C_ADD_DEVICE,  C_ADD_DRIVER and C_ADD_PROCESS
            char szObjectName[MAX_REQUEST_STRING];

            /*
                If TRUE -- debugger command, that stored in Buff[],
                must be executed for every IOCTL, that has been matched
                by this object.
            */
            BOOLEAN bDbgcbAction;

        } AddObject;

        struct
        {
            HANDLE hObject;
            char szObjectName[MAX_REQUEST_STRING];

        } ObjectName;

        struct
        {
            BOOLEAN bHooksInstalled;

        } CheckHooks;
    };       
  • ParseAllowDenySection() src\application\src\ioctlfuzzer.cpp

This function create the REQUEST_BUFFER in ring3 and complete it.


I was wrong,DriverDispatch() just check the options,
Fuzz function is here.

  • new_NtDeviceControlFile()
  • Fuzz_NtDeviceIoControlFile()
  • FuzzContinue_NtDeviceIoControlFile()—this is the real fuzz function
//--------------------------------------------------------------------------------------
void FuzzContinue_NtDeviceIoControlFile(
    KPROCESSOR_MODE PrevMode,
    HANDLE FileHandle,
    HANDLE Event,
    PIO_APC_ROUTINE ApcRoutine,
    PVOID ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG IoControlCode,
    PVOID InputBuffer,
    ULONG InputBufferLength,
    PVOID OutputBuffer,
    ULONG OutputBufferLength)
{                       
    // allocate temporary buffer for original request
    PUCHAR NewBuff = (PUCHAR)M_ALLOC(InputBufferLength);
    if (NewBuff)
    {
        RtlCopyMemory(NewBuff, InputBuffer, InputBufferLength);

        if (m_FuzzingType == FuzzingType_Random)
        {
            /**
            * Fuzzing with random values
            */

            for (int i = 0; i < RANDOM_FUZZING_ITERATIONS; i++)
            {
                ULONG TmpInputLength = InputBufferLength;

                if (m_FuzzOptions & FUZZ_OPT_FUZZ_SIZE)
                {
                    TmpInputLength = getrand(1, TmpInputLength * 4);
                }

                // fill buffer with random data
                for (ULONG s = 0; s < InputBufferLength; s++)
                {
                    *((PUCHAR)InputBuffer + s) = (UCHAR)getrand(1, 0xff);
                }

                // change previous mode to UserMode
                SetPreviousMode(PrevMode);//why here?

                // send fuzzed request
                NTSTATUS status = old_NtDeviceIoControlFile(
                    FileHandle,
                    Event, ApcRoutine,
                    ApcContext,
                    IoStatusBlock,
                    IoControlCode,
                    InputBuffer,
                    TmpInputLength,
                    OutputBuffer,
                    OutputBufferLength
                );
            }
        }
        else if (m_FuzzingType == FuzzingType_Dword)
        {             
            /**
            * Fuzzing with predefined dwords
            */

            // check buffer length
            ULONG FuzzingLength = XALIGN_DOWN(InputBufferLength, sizeof(ULONG));
            if (FuzzingLength <= DWORD_FUZZING_MAX_LENGTH && FuzzingLength >= sizeof(ULONG))
            {
                // fuzz each dword value in input buffer
                for (ULONG i = 0; i < FuzzingLength; i += DWORD_FUZZING_DELTA)
                {
                    for (ULONG i_v = 0; i_v < sizeof(m_DwordFuzzingConstants) / sizeof(ULONG); i_v++)
                    {                       
                        // put dword constant into the buffer
                        ULONG OldBuffVal = *(PULONG)((PUCHAR)InputBuffer + i);
                        *(PULONG)((PUCHAR)InputBuffer + i) = m_DwordFuzzingConstants[i_v];                       

                        // set previous mode to UserMode
                        SetPreviousMode(PrevMode);

                        // send fuzzed request
                        NTSTATUS status = old_NtDeviceIoControlFile(
                            FileHandle,
                            Event, ApcRoutine,
                            ApcContext,
                            IoStatusBlock,
                            IoControlCode,
                            InputBuffer,
                            InputBufferLength,
                            OutputBuffer,
                            OutputBufferLength
                        );

                        // restore changed dword
                        *(PULONG)((PUCHAR)InputBuffer + i) = OldBuffVal;                       
                    }
                }
            }
        }


        // restore buffer
        RtlCopyMemory(InputBuffer, NewBuff, InputBufferLength);       
        ExFreePool(NewBuff);
    }
    else
    {
        DbgMsg(__FILE__, __LINE__, "M_ALLOC() ERROR\n");
    }

    // try to fuzz missing output buffer length checks
    if (OutputBufferLength > 0)
    {       
        // ... with user-mode buffer addresses
        PVOID TmpOutputBuffer = USER_BUFFER_ADDRESS;

        // set previous mode to UserMode
        SetPreviousMode(PrevMode);

        // send fuzzed request
        NTSTATUS status = old_NtDeviceIoControlFile(
            FileHandle,
            Event, ApcRoutine,
            ApcContext,
            IoStatusBlock,
            IoControlCode,
            InputBuffer,
            InputBufferLength,
            TmpOutputBuffer, 0
        );       

        // ... with kernel-mode buffer addresses
        TmpOutputBuffer = KERNEL_BUFFER_ADDRESS;

        // set previous mode to UserMode
        SetPreviousMode(PrevMode);

        // send fuzzed request
        status = old_NtDeviceIoControlFile(
            FileHandle,
            Event, ApcRoutine,
            ApcContext,
            IoStatusBlock,
            IoControlCode,
            InputBuffer,
            InputBufferLength,
            TmpOutputBuffer, 0
        );
    }

    ULONG Method = IoControlCode & 3;
    if (Method != METHOD_BUFFERED)
    {
        // try to fuzz buffer addresses, if method is not buffered
        for (int i = 0; i < BUFFERED_FUZZING_ITERATIONS; i++)
        {
            // ... with user-mode addresses
            PVOID TmpInputBuffer  = USER_BUFFER_ADDRESS;
            PVOID TmpOutputBuffer = USER_BUFFER_ADDRESS;
            ULONG TmpInputBufferLength  = getrand(0, 0x100);
            ULONG TmpOutputBufferLength = getrand(0, 0x100);

            // set previous mode to UserMode
            SetPreviousMode(PrevMode);

            // send fuzzed request
            NTSTATUS status = old_NtDeviceIoControlFile(
                FileHandle,
                Event, ApcRoutine,
                ApcContext,
                IoStatusBlock,
                IoControlCode,
                TmpInputBuffer,
                TmpInputBufferLength,
                TmpOutputBuffer,
                TmpOutputBufferLength
            );
        }

        for (int i = 0; i < BUFFERED_FUZZING_ITERATIONS; i++)
        {
            // ... with kernel-mode addresses
            PVOID TmpInputBuffer  = KERNEL_BUFFER_ADDRESS;
            PVOID TmpOutputBuffer = KERNEL_BUFFER_ADDRESS;
            ULONG TmpInputBufferLength  = getrand(0, 0x100);
            ULONG TmpOutputBufferLength = getrand(0, 0x100);

            // change previous mode to UserMode
            SetPreviousMode(PrevMode);

            // send fuzzed request
            NTSTATUS status = old_NtDeviceIoControlFile(
                FileHandle,
                Event,
                ApcRoutine,
                ApcContext,
                IoStatusBlock,
                IoControlCode,
                TmpInputBuffer,
                TmpInputBufferLength,
                TmpOutputBuffer,
                TmpOutputBufferLength
            );
        }
    }
}

After hooking the nt!NtDeviceIoControlFile,new_NtDeviceControlFile()
takes place of it,and it calls FuzzContinue_NtDeviceIoControlFile().

As u see,it will generate random buffer and length.


However,there is a bad news. DeviceIoControlFile() is deprecated and replaced by DeviceIoControl(), which means we need to hook it. So,we need to re-compile the source code to get a new sys&exe file.


既然DeviceIoControlFile()已经被标记废弃,想继续使用这要工具就得自己修改源码来hook DeviceIoCotrol(),hook之后是拦截正常通信,来修改我们的buffer区域,换一个思路,我们也可直接和一个有Symbol name的对象通信,只不过这样就需要我们自己来测试或者拦截到可能的参数(ex:ControlCode BufferSize),所以想要直接通信,我们还需要其他的工具,具体的请参照此仓库https://github.com/koutto/ioctlbf中的Readme.md最后几行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值