代码这样写奇丑无比...编码前期要做好规划工作啊

NTSTATUS ScDetective_DispatchDeviceControl(
    IN PDEVICE_OBJECT        DeviceObject,
    IN PIRP                    Irp
    )
{
    NTSTATUS    ntStatus = STATUS_SUCCESS;
    PVOID       InputBuffer     = NULL;
    PVOID       OutputBuffer    = NULL;
    ULONG       cbInputBuffer   = 0;
    ULONG       cbOutputBuffer  = 0;
    PIO_STACK_LOCATION irpSp    = NULL;
    
    __try {
        irpSp = IoGetCurrentIrpStackLocation(Irp);

        InputBuffer     = Irp->AssociatedIrp.SystemBuffer;
        cbInputBuffer   = irpSp->Parameters.DeviceIoControl.InputBufferLength;
        OutputBuffer    = Irp->AssociatedIrp.SystemBuffer;
        cbOutputBuffer  = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

        switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
        {
        case IOCTL_DUMP_KERNEL_MEMORY: 
            {
                PVOID DumpAddress;
                PMDL MdlCreate;

                if (cbInputBuffer == sizeof(ULONG)) {
                    DumpAddress = (PVOID)((PULONG)InputBuffer)[0];
                    if (!MmIsAddressValid(DumpAddress)) {
                        ntStatus = STATUS_INVALID_ADDRESS;
                        break;
                    } else {
                        ScmMapVirtualAddress(DumpAddress, cbOutputBuffer, &MdlCreate);
                        RtlCopyMemory(OutputBuffer, DumpAddress, cbOutputBuffer);
                        ScmUnmapVirtualAddress(MdlCreate);
                        Irp->IoStatus.Information = cbOutputBuffer;  break; 
                    }
                } else {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_SSDT:    // 获取 ssdt
            {         
                ULONG NeedLen = 0;
                ULONG Number = GetSsdtServiceNumber();

                NeedLen = Number * sizeof(SSDT_ADDRESS);
                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
                Number = GetSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen);
                if (Number == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS);
                break;
            } 
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_UNHOOK_SSDT:          // 恢复 ssdt
            {
                PSSDT_ADDRESS SsdtOrig = (PSSDT_ADDRESS)InputBuffer;

                if (cbInputBuffer < sizeof(SSDT_ADDRESS) || 
                    InputBuffer == NULL) {
                    KdPrint(("输入缓冲区或输入缓冲区长度无效"));
                    ntStatus = STATUS_UNSUCCESSFUL;
                    break;
                }
                KdPrint(("要恢复的服务号:%d 原始地址:0x%X", 
                    SsdtOrig->nIndex, SsdtOrig->FunAddress));

                if (!UnHookSsdtItem(SsdtOrig)) {
                    KdPrint(("恢复失败"));
                    ntStatus = STATUS_UNSUCCESSFUL;
                }
                break;
            } 
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_SSDTSHADOW:
            {
                ULONG Number = GetShadowSsdtServiceNumber();
                ULONG NeedLen = 0;
                
                NeedLen = Number * sizeof(SSDT_ADDRESS);
                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
                Number = GetShadowSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen);

                if (Number == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS);
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_UNHOOK_SSDTSHADOW:
            {
                PSSDT_ADDRESS ShadowSsdtOrig = (PSSDT_ADDRESS)InputBuffer;

                if (cbInputBuffer < sizeof(SSDT_ADDRESS) || 
                    InputBuffer == NULL) {
                    KdPrint(("输入缓冲区或输入缓冲区长度无效"));
                    ntStatus = STATUS_UNSUCCESSFUL;  break;
                }
                KdPrint(("要恢复的服务号:%d 原始地址:0x%X", 
                    ShadowSsdtOrig->nIndex, ShadowSsdtOrig->FunAddress));

                if (!UnHookShadowSsdtItem(ShadowSsdtOrig, g_CsrssProcess)) {
                    ntStatus = STATUS_UNSUCCESSFUL;
                }
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_PROCESSES:  
            {
                PPROCESS_LIST_HEAD ProcessHead;
                ULONG NeedLen;
                ULONG ReturnLength;

                ProcessHead = ScPsQuerySystemProcessList();
                NeedLen = ProcessHead->NumberOfProcesses * sizeof(PROCESS_INFO);

                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL; break;
                }
                ReturnLength = ExCopyProcessList2Buffer((PPROCESS_INFO)OutputBuffer);
                if (ReturnLength == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = ReturnLength;
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_PROCESS_IMAGE_PATH:
            {
                PEPROCESS Process = NULL;
                PUNICODE_STRING NameString;
                ULONG BufferSize;

                if (cbInputBuffer == sizeof(ULONG)) {
                    Process = ((PEPROCESS*)InputBuffer)[0];
                    if (Process == NULL) {
                        ntStatus = STATUS_ACCESS_DENIED; break;
                    }
                } else {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                    break;
                }
                if (Process == g_SystemProcess) {
                    if (cbOutputBuffer > sizeof(L"System")) {
                        RtlCopyMemory(OutputBuffer, L"System", sizeof(L"System"));
                        Irp->IoStatus.Information = sizeof(L"System");
                        break; 
                    }
                } else if (Process == g_IdleProcess) {
                    if (cbOutputBuffer > sizeof(L"Idle")) {
                        RtlCopyMemory(OutputBuffer, L"Idle", sizeof(L"Idle"));
                        Irp->IoStatus.Information = sizeof(L"Idle");
                        break; 
                    }
                }
                if (cbOutputBuffer < 520) {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                    break;
                }
                BufferSize = cbOutputBuffer + sizeof(UNICODE_STRING);
                NameString = ExAllocatePoolWithTag(NonPagedPool, BufferSize, MEM_TAG);
                NameString->Buffer = (PWCH)((ULONG)NameString + 8);
                NameString->Length = 0;
                NameString->MaximumLength = (USHORT)cbOutputBuffer;

                ntStatus = ScPsGetProcessImagePath(Process, NameString);
                if (NT_SUCCESS(ntStatus)) {
                    RtlCopyMemory(OutputBuffer, NameString->Buffer, NameString->Length);
                }
                Irp->IoStatus.Information = NameString->Length;
                ExFreePoolWithTag(NameString, MEM_TAG);
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_PROCESS_THREADS:
            {            
                PTHREAD_LIST_HEAD ThreadHead = NULL;
                PEPROCESS EProcess = NULL;
                ULONG NeedLen = 0;
                ULONG ReturnLength = 0;
                
                if (cbInputBuffer == sizeof(ULONG)) {
                    EProcess = ((PEPROCESS*)InputBuffer)[0];
                } else {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                    break;
                }
                if (EProcess == g_IdleProcess) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;  
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break; 
                    }
                }
                ThreadHead = ScPsQueryProcessThreadList(EProcess);
                if (ThreadHead == NULL) {
                    ntStatus = STATUS_UNSUCCESSFUL;
                    break;
                }
                NeedLen = ThreadHead->NumberOfThread * sizeof(THREAD_INFO);
 
                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
                ReturnLength = ExCopyThreadList2Buffer((PTHREAD_INFO)OutputBuffer);
                if (ReturnLength == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = ReturnLength;
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_PROCESS_MODULES:
            {
                PMODULE_LIST_HEAD ModuleHead = NULL;
                PEPROCESS EProcess = NULL;
                ULONG NeedLen = 0;
                ULONG ReturnLength = 0;

                if (cbInputBuffer == sizeof(ULONG)) {
                    EProcess = ((PEPROCESS*)InputBuffer)[0];
                } else {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }

                if (EProcess == g_IdleProcess) {
                    if (cbOutputBuffer = sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break; 
                    }
                }
                ModuleHead = ScPsQueryProcessModuleList(EProcess);
                if (ModuleHead == NULL) {
                    ntStatus = STATUS_UNSUCCESSFUL;  break;
                }
                NeedLen = ModuleHead->NumberOfModules * sizeof(MODULE_INFO);

                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
                ReturnLength = ExCopyModuleList2Buffer((PMODULE_INFO)OutputBuffer);
                if (ReturnLength == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = ReturnLength;
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_GET_DRIVER_OBJECT:
            {
                PDRIVER_LIST_HEAD DriverHead = NULL;
                PEPROCESS EProcess = NULL;
                HANDLE UserEvent;
                PKEVENT kEvent;
                ULONG NeedLen = 0;
                ULONG ReturnLength = 0;

                if (cbInputBuffer == sizeof(HANDLE) * 2) {
                    UserEvent = *(PHANDLE)InputBuffer;
                    ntStatus = ObReferenceObjectByHandle(UserEvent, 0, 
                                *ExEventObjectType, UserMode, &kEvent, NULL);
                    if (NT_SUCCESS(ntStatus)) {
                        ScObQueryDriverObject(pdoGlobalDrvObj, kEvent);
                        ObDereferenceObject(kEvent);
                    }
                    Irp->IoStatus.Information = 0;  break;
                }

                DriverHead = ScObQueryDriverObject(NULL, NULL);
                if (DriverHead == NULL) {
                    ntStatus = STATUS_UNSUCCESSFUL;  break;
                }
                NeedLen = DriverHead->NumberOfDrivers * sizeof(DRIVER_INFO);

                if (cbOutputBuffer < NeedLen) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLen;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }
                ReturnLength = ExCopyDriverList2Buffer((PDRIVER_INFO)OutputBuffer);
                if (ReturnLength == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = ReturnLength;
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_LIST_DIRECTORY:
            {
                PWCHAR pszDirectory;
                ULONG NeedLength;
                ULONG ReturnLength;
                PFILE_LIST_HEAD FileHead;

                pszDirectory = ExAllocatePoolWithTag(PagedPool, 260 * 2, MEM_TAG);
                RtlZeroMemory(pszDirectory, 260 * 2);

                if (cbInputBuffer == 260 * 2) {
                    RtlCopyMemory(pszDirectory, InputBuffer, 260 * 2);
                } else {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;  break;
                }

                FileHead = ScfsQueryDirectoryInformation(pszDirectory);
                if (FileHead == NULL) {
                    ((PULONG)OutputBuffer)[0] = 0;
                    Irp->IoStatus.Information = sizeof(ULONG);
                    ntStatus = STATUS_SUCCESS;  break;
                }
                NeedLength = FileHead->NumberOfItems * sizeof(FILE_INFO);

                if (cbOutputBuffer < NeedLength) {
                    if (cbOutputBuffer == sizeof(ULONG)) {
                        ((PULONG)OutputBuffer)[0] = NeedLength;
                        Irp->IoStatus.Information = sizeof(ULONG);
                        break;
                    }
                    ntStatus = STATUS_BUFFER_TOO_SMALL; break;
                }
                ReturnLength = ExCopyFileList2Buffer((PFILE_INFO)OutputBuffer);
                if (ReturnLength == 0)  ntStatus = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = ReturnLength;
                ExFreePoolWithTag(pszDirectory, MEM_TAG);
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_PROTECT_MYSELF:
            {
                HANDLE ProcessId;
                if (cbInputBuffer == sizeof(ULONG)) {
                    ProcessId = ((PHANDLE)InputBuffer)[0];
                    if (ProcessId) {
                        ntStatus = ScPtHideProcessById(ProcessId);
                    }
                }
                Irp->IoStatus.Information = 0;
                break;
            }
        //////////////////////////////////////////////////////////////////////////
        case IOCTL_EXIT_PROCESS:
            ScPtUnloadRoutine();
            break;
        //////////////////////////////////////////////////////////////////////////
        default:
            Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
            Irp->IoStatus.Information = 0;
            break;
        }
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        ntStatus = GetExceptionCode();
        Irp->IoStatus.Information = 0;
    }
  
    Irp->IoStatus.Status = ntStatus;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return ntStatus;
}

 

应该像psnull那样把各个分发例程分两层处理的,不但看起来美观,而且方便管理

一旦内核和用户层交互多了,这该怎么管理啊,真后悔开始没有多参考优秀的工程啊

以后又有很多体力活要做了。。。

posted @ 2010-12-22 16:46  kedebug  阅读(431)  评论(0编辑  收藏  举报