
#ifndef CXX_FILEPROTECTX86_H
#    include "FileProtectX86.h"
#endif

ULONG gC2pKeyCount = 0;
PDRIVER_OBJECT gDriverObject = NULL;

BOOLEAN bOk = FALSE;

ULONG_PTR  IndexOffsetOfFunction = 0;
ULONG_PTR  SSDTDescriptor = 0;
KIRQL Irql;
ULONG_PTR   ulIndex = 0;
ULONG_PTR   ulIndex1 = 0;
ULONG_PTR   ulIndex2 = 0;
pfnNtSetInformationFile Old_NtSetInformationFileWinXP = NULL;
pfnNtDeleteFile Old_NtDeleteFileWinXP = NULL;
//pfnNtCreateFile Old_NtCreateFileWinXP = NULL;
pfnNtWriteFile Old_NtWriteFileWinXP = NULL;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegisterPath)
{
    ULONG i; 
    NTSTATUS status;

    // 填写所有的分发函数的指针
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 
    { 
        DriverObject->MajorFunction[i] = c2pDispatchGeneral; 
    } 

    // 单独的填写一个Read分发函数。因为要的过滤就是读取来的按键信息
    // 其他的都不重要。这个分发函数单独写。
    DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead; 

    // 单独的填写一个IRP_MJ_POWER函数。这是因为这类请求中间要调用
    // 一个PoCallDriver和一个PoStartNextPowerIrp，比较特殊。
    DriverObject->MajorFunction [IRP_MJ_POWER] = c2pPower; 

    // 我们想知道什么时候一个我们绑定过的设备被卸载了（比如从机器上
    // 被拔掉了？）所以专门写一个PNP（即插即用）分发函数
    DriverObject->MajorFunction [IRP_MJ_PNP] = c2pPnP; 

    // 卸载函数。
    DriverObject->DriverUnload = c2pUnload; 
    gDriverObject = DriverObject;
    // 绑定所有键盘设备
    status =c2pAttachDevices(DriverObject, RegisterPath);

    SSDTDescriptor = (ULONG_PTR)GetFunctionAddressByNameFromNtosExport(L"KeServiceDescriptorTable");
    IndexOffsetOfFunction = 1;

    ulIndex = GetSSDTApiFunctionIndexFromNtdll("NtSetInformationFile");
    ulIndex1 = GetSSDTApiFunctionIndexFromNtdll("NtWriteFile");
    ulIndex2 = GetSSDTApiFunctionIndexFromNtdll("NtDeleteFile");

    HookSSDT(ulIndex);
    HookWrite(ulIndex1);
    HookDelete(ulIndex2);

    return STATUS_SUCCESS;
}



NTSTATUS 
    c2pDevExtInit( 
    IN PC2P_DEV_EXT devExt, 
    IN PDEVICE_OBJECT pFilterDeviceObject, 
    IN PDEVICE_OBJECT pTargetDeviceObject, 
    IN PDEVICE_OBJECT pLowerDeviceObject ) 
{ 
    memset(devExt, 0, sizeof(C2P_DEV_EXT)); 
    devExt->NodeSize = sizeof(C2P_DEV_EXT); 
    devExt->pFilterDeviceObject = pFilterDeviceObject; 
    KeInitializeSpinLock(&(devExt->IoRequestsSpinLock)); 
    KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE); 
    devExt->TargetDeviceObject = pTargetDeviceObject; 
    devExt->LowerDeviceObject = pLowerDeviceObject; 
    return( STATUS_SUCCESS ); 
}


// 这个函数经过改造。能打开驱动对象Kbdclass，然后绑定
// 它下面的所有的设备：
NTSTATUS 
    c2pAttachDevices( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ) 
{ 
    NTSTATUS status = 0; 
    UNICODE_STRING uniNtNameString; 
    PC2P_DEV_EXT devExt; 
    PDEVICE_OBJECT pFilterDeviceObject = NULL; 
    PDEVICE_OBJECT pTargetDeviceObject = NULL; 
    PDEVICE_OBJECT pLowerDeviceObject = NULL; 

    PDRIVER_OBJECT KbdDriverObject = NULL; 

    KdPrint(("MyAttach\n")); 

    // 初始化一个字符串，就是Kdbclass驱动的名字。
    RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME); 
    // 请参照前面打开设备对象的例子。只是这里打开的是驱动对象。
    status = ObReferenceObjectByName ( 
        &uniNtNameString, 
        OBJ_CASE_INSENSITIVE, 
        NULL, 
        0, 
        IoDriverObjectType, 
        KernelMode, 
        NULL, 
        &KbdDriverObject 
        ); 
    // 如果失败了就直接返回
    if(!NT_SUCCESS(status)) 
    { 
        KdPrint(("MyAttach: Couldn't get the MyTest Device Object\n")); 
        return( status ); 
    }
    else
    {
        // 这个打开需要解应用。早点解除了免得之后忘记。
        ObDereferenceObject(DriverObject);
    }

    // 这是设备链中的第一个设备    
    pTargetDeviceObject = KbdDriverObject->DeviceObject;
    // 现在开始遍历这个设备链
    while (pTargetDeviceObject) 
    {
        // 生成一个过滤设备，这是前面读者学习过的。这里的IN宏和OUT宏都是
        // 空宏，只有标志性意义，表明这个参数是一个输入或者输出参数。
        status = IoCreateDevice( 
            IN DriverObject, 
            IN sizeof(C2P_DEV_EXT), 
            IN NULL, 
            IN pTargetDeviceObject->DeviceType, 
            IN pTargetDeviceObject->Characteristics, 
            IN FALSE, 
            OUT &pFilterDeviceObject 
            ); 

        // 如果失败了就直接退出。
        if (!NT_SUCCESS(status)) 
        { 
            KdPrint(("MyAttach: Couldn't create the MyFilter Filter Device Object\n")); 
            return (status); 
        } 

        // 绑定。pLowerDeviceObject是绑定之后得到的下一个设备。也就是
        // 前面常常说的所谓真实设备。
        pLowerDeviceObject = 
            IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject); 
        // 如果绑定失败了，放弃之前的操作，退出。
        if(!pLowerDeviceObject) 
        { 
            KdPrint(("MyAttach: Couldn't attach to MyTest Device Object\n")); 
            IoDeleteDevice(pFilterDeviceObject); 
            pFilterDeviceObject = NULL; 
            return( status ); 
        } 

        // 设备扩展！下面要详细讲述设备扩展的应用。
        devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension); 
        c2pDevExtInit( 
            devExt, 
            pFilterDeviceObject, 
            pTargetDeviceObject, 
            pLowerDeviceObject ); 

        // 下面的操作和前面过滤串口的操作基本一致。这里不再解释了。
        pFilterDeviceObject->DeviceType=pLowerDeviceObject->DeviceType; 
        pFilterDeviceObject->Characteristics=pLowerDeviceObject->Characteristics; 
        pFilterDeviceObject->StackSize=pLowerDeviceObject->StackSize+1; 
        pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE) ; 
        //next device 
        pTargetDeviceObject = pTargetDeviceObject->NextDevice;
    }
    return status; 
} 


VOID 
    c2pDetach(IN PDEVICE_OBJECT pDeviceObject) 
{ 
    PC2P_DEV_EXT devExt; 
    BOOLEAN NoRequestsOutstanding = FALSE; 
    devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension; 
    __try 
    { 
        __try 
        { 
            IoDetachDevice(devExt->TargetDeviceObject);
            devExt->TargetDeviceObject = NULL; 
            IoDeleteDevice(pDeviceObject); 
            devExt->pFilterDeviceObject = NULL; 
            DbgPrint(("Detach Finished\n")); 
        } 
        __except (EXCEPTION_EXECUTE_HANDLER){} 
    } 
    __finally{} 
    return; 
}



VOID 
    c2pUnload(IN PDRIVER_OBJECT DriverObject) 
{ 
    PDEVICE_OBJECT DeviceObject; 
    PDEVICE_OBJECT OldDeviceObject; 
    PC2P_DEV_EXT devExt; 

    LARGE_INTEGER    lDelay;
    PRKTHREAD CurrentThread;
    //delay some time 
    lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
    CurrentThread = KeGetCurrentThread();
    // 把当前线程设置为低实时模式，以便让它的运行尽量少影响其他程序。
    KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);

    UNREFERENCED_PARAMETER(DriverObject); 
    KdPrint(("DriverEntry unLoading...\n")); 

    // 遍历所有设备并一律解除绑定
    DeviceObject = DriverObject->DeviceObject;
    while (DeviceObject)
    {
        // 解除绑定并删除所有的设备
        c2pDetach(DeviceObject);
        DeviceObject = DeviceObject->NextDevice;
    } 
    ASSERT(NULL == DriverObject->DeviceObject);

    while (gC2pKeyCount)
    {
        KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    }

    UnHookSSDT(ulIndex);
    UnHookSSDTWrite(ulIndex1);
    UnHookSSDTDelete(ulIndex2);
    KdPrint(("DriverEntry unLoad OK!\n")); 
    //return; 
} 


//处理我们不关心的所有IRP
NTSTATUS c2pDispatchGeneral( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    // 其他的分发函数，直接skip然后用IoCallDriver把IRP发送到真实设备
    // 的设备对象。 
    KdPrint(("Other Diapatch!")); 
    IoSkipCurrentIrpStackLocation(Irp); 
    return IoCallDriver(((PC2P_DEV_EXT)
        DeviceObject->DeviceExtension)->LowerDeviceObject, Irp); 
} 
//只处理主功能号为IRP_MJ_POWER的IRP
NTSTATUS c2pPower( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    PC2P_DEV_EXT devExt;
    devExt =
        (PC2P_DEV_EXT)DeviceObject->DeviceExtension; 

    PoStartNextPowerIrp( Irp ); 
    IoSkipCurrentIrpStackLocation( Irp ); 
    return PoCallDriver(devExt->LowerDeviceObject, Irp ); 
} 
//设备被拔出时，需解除绑定，并删除过滤设备
NTSTATUS c2pPnP( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    PC2P_DEV_EXT devExt; 
    PIO_STACK_LOCATION irpStack; 
    NTSTATUS status = STATUS_SUCCESS; 
    KIRQL oldIrql; 
    KEVENT event; 

    // 获得真实设备。
    devExt = (PC2P_DEV_EXT)(DeviceObject->DeviceExtension); 
    irpStack = IoGetCurrentIrpStackLocation(Irp); 

    switch (irpStack->MinorFunction) 
    { 
    case IRP_MN_REMOVE_DEVICE: 
        KdPrint(("IRP_MN_REMOVE_DEVICE\n")); 

        // 首先把请求发下去
        IoSkipCurrentIrpStackLocation(Irp); 
        IoCallDriver(devExt->LowerDeviceObject, Irp); 
        // 然后解除绑定。
        IoDetachDevice(devExt->LowerDeviceObject); 
        // 删除我们自己生成的虚拟设备。
        IoDeleteDevice(DeviceObject); 
        status = STATUS_SUCCESS; 
        break; 

    default: 
        // 对于其他类型的IRP，全部都直接下发即可。 
        IoSkipCurrentIrpStackLocation(Irp); 
        status = IoCallDriver(devExt->LowerDeviceObject, Irp); 
    } 
    return status; 
}

// 这是一个IRP完成回调函数的原型
NTSTATUS c2pReadComplete( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp, 
    IN PVOID Context 
    ) 
{
    POBJECT_NAME_INFORMATION ObjetNameInfor;  
    ULONG* ulProcessNameLen;
    PIO_STACK_LOCATION IrpSp;
    ULONG buf_len = 0;
    PUCHAR buf = NULL;
    size_t i;
    ULONG numKeys = 0;
    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //  如果这个请求是成功的。很显然，如果请求失败了，这么获取
    //   进一步的信息是没意义的。
    if( NT_SUCCESS( Irp->IoStatus.Status ) ) 
    { 
        PKEYBOARD_INPUT_DATA pKeyData;
        // 获得读请求完成后输出的缓冲区
        buf = Irp->AssociatedIrp.SystemBuffer;
        pKeyData = Irp->AssociatedIrp.SystemBuffer;

        // 获得这个缓冲区的长度。一般的说返回值有多长都保存在
        // Information中。

        buf_len = Irp->IoStatus.Information;
        numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        __try
        {
            if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)IrpSp->FileObject, &ObjetNameInfor)))  
            {  
                if(wcsstr(ObjetNameInfor->Name.Buffer,L"Shine.txt")!=0)
                {
                    DbgPrint("aaaaaaa");
                }
            }  
        }
        __except(1)
        {
            DbgPrint("Exception:%x",GetExceptionCode());
        }


        //通过Process获得进程名称
        for(i = 0; i < numKeys; i++) 
        {
            //    DbgPrint("%02X %d\n",pKeyData[i].MakeCode,pKeyData[i].Flags);

            if(pKeyData[i].MakeCode == 0x1d && pKeyData[i].Flags == KEY_MAKE)
            {
                //左Ctrl
                bOk = TRUE;
            }

            if(pKeyData[i].MakeCode == 0x2e && pKeyData[i].Flags == KEY_MAKE && bOk == TRUE ) //按下
            {
                pKeyData[i].MakeCode = 0x20;
                bOk = FALSE;
                DbgPrint("aaaaaaaaaaaaaa");
            }
        }
        //… 这里可以做进一步的处理。我这里很简单的打印出所有的扫
        // 描码。

        //    for(i=0;i<buf_len;++i)
        //    {
        //DbgPrint("ctrl2cap: %2x\r\n", buf[i]);
        //        if(buf[i]==0x3a)
        //        {
        //            DbgPrint("SSSSSS");
        //        }
        //    }

    }
    gC2pKeyCount--;

    if( Irp->PendingReturned )
    { 
        IoMarkIrpPending( Irp ); 
    } 
    return Irp->IoStatus.Status;
}

NTSTATUS c2pDispatchRead( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp ) 
{ 
    NTSTATUS status = STATUS_SUCCESS; 
    PC2P_DEV_EXT devExt; 
    PIO_STACK_LOCATION currentIrpStack; 
    KEVENT waitEvent;
    KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );

    if (Irp->CurrentLocation == 1) 
    { 
        ULONG ReturnedInformation = 0; 
        KdPrint(("Dispatch encountered bogus current location\n")); 
        status = STATUS_INVALID_DEVICE_REQUEST; 
        Irp->IoStatus.Status = status; 
        Irp->IoStatus.Information = ReturnedInformation; 
        IoCompleteRequest(Irp, IO_NO_INCREMENT); 
        return(status); 
    } 

    // 全局变量键计数器加1
    gC2pKeyCount++;

    // 得到设备扩展。目的是之后为了获得下一个设备的指针。
    devExt =
        (PC2P_DEV_EXT)DeviceObject->DeviceExtension;

    // 设置回调函数并把IRP传递下去。 之后读的处理也就结束了。
    // 剩下的任务是要等待读请求完成。
    currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine( Irp, c2pReadComplete, 
        DeviceObject, TRUE, TRUE, TRUE ); 
    return  IoCallDriver( devExt->LowerDeviceObject, Irp );     
}

VOID  HookSSDT(ULONG_PTR ulIndex)
{
    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;    //数组首地址
    Old_NtSetInformationFileWinXP  = (pfnNtSetInformationFile)ServiceTableBase[ulIndex];      //先保存原先的函数地址

    WPOFF();  
    ServiceTableBase[ulIndex] = (ULONG32)Fake_NtSetInformationFileWinXP;  //将KeBugCheckEx函数的偏移地址放入SSDT表中
    WPON();    
}

VOID HookWrite(ULONG_PTR ulIndex)
{
    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;    //数组首地址
    Old_NtWriteFileWinXP  = (pfnNtWriteFile)ServiceTableBase[ulIndex];      //先保存原先的函数地址

    WPOFF();  
    ServiceTableBase[ulIndex] = (ULONG32)Fake_NtWriteFileWinXP;  //将KeBugCheckEx函数的偏移地址放入SSDT表中
    WPON();
}

VOID HookDelete(ULONG_PTR ulIndex)
{
    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;    //数组首地址
    Old_NtDeleteFileWinXP  = (pfnNtDeleteFile)ServiceTableBase[ulIndex];      //先保存原先的函数地址

    WPOFF();  
    ServiceTableBase[ulIndex] = (ULONG32)Fake_NtDeleteFileWinXP;  //将KeBugCheckEx函数的偏移地址放入SSDT表中
    WPON();
}


VOID
    UnHookSSDT(ULONG_PTR ulIndex)
{
    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;

    WPOFF();
    ServiceTableBase[ulIndex] = (ULONG32)Old_NtSetInformationFileWinXP;
    WPON();
}

VOID
    UnHookSSDTWrite(ULONG_PTR ulIndex)
{

    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;

    WPOFF();
    ServiceTableBase[ulIndex] = (ULONG32)Old_NtWriteFileWinXP;
    WPON();

}

VOID
    UnHookSSDTDelete(ULONG_PTR ulIndex)
{
    PULONG32  ServiceTableBase = NULL;
    ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;

    WPOFF();
    ServiceTableBase[ulIndex] = (ULONG32)Old_NtDeleteFileWinXP;
    WPON();
}


NTSTATUS Fake_NtSetInformationFileWinXP(
    __in HANDLE FileHandle,
    __out PIO_STATUS_BLOCK IoStatusBlock,
    __in_bcount(Length) PVOID FileInformation,
    __in ULONG Length,
    __in FILE_INFORMATION_CLASS FileInformationClass
    )
{
    NTSTATUS Status;
    PFILE_OBJECT hObject;
    POBJECT_NAME_INFORMATION ObjetNameInfor;  

    Status = ObReferenceObjectByHandle(FileHandle,FILE_READ_DATA,0,KernelMode,&hObject, 0);
    //通过进程句柄获取EProcess对象

    if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)hObject, &ObjetNameInfor)))  
    {  
        if(wcsstr((ObjetNameInfor->Name).Buffer,L"D:\\Shine.txt"))
        {
            if(FileInformationClass == FileRenameInformation)
            {
                return STATUS_ACCESS_DENIED;
            }
        }
    }  

    return Old_NtSetInformationFileWinXP(FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass);
}

NTSTATUS
    Fake_NtWriteFileWinXP (
    __in HANDLE FileHandle,
    __in_opt HANDLE Event,
    __in_opt PIO_APC_ROUTINE ApcRoutine,
    __in_opt PVOID ApcContext,
    __out PIO_STATUS_BLOCK IoStatusBlock,
    __in_bcount(Length) PVOID Buffer,
    __in ULONG Length,
    __in_opt PLARGE_INTEGER ByteOffset,
    __in_opt PULONG Key
    )
{
    NTSTATUS Status;
    PFILE_OBJECT hObject;
    POBJECT_NAME_INFORMATION ObjetNameInfor;  

    Status = ObReferenceObjectByHandle(FileHandle,FILE_READ_DATA,0,KernelMode,&hObject, 0);
    //通过进程句柄获取EProcess对象

    if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)hObject, &ObjetNameInfor)))  
    {  
        if(wcsstr((ObjetNameInfor->Name).Buffer,L"D:\\Shine.txt"))
        {
            return STATUS_ACCESS_DENIED;
        }
    }  

    return Old_NtWriteFileWinXP(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
}


NTSTATUS Fake_NtDeleteFileWinXP(
    __in POBJECT_ATTRIBUTES ObjectAttributes
    )
{
    if(wcsstr((ObjectAttributes->ObjectName)->Buffer,L"D:\\Shine.txt"))
    {
        return STATUS_ACCESS_DENIED;
    }
    return Old_NtDeleteFileWinXP(ObjectAttributes);
}



PVOID 
    GetFunctionAddressByNameFromNtosExport(WCHAR *wzFunctionName)
{
    UNICODE_STRING uniFunctionName;  
    PVOID FunctionAddress = NULL;

    if (wzFunctionName && wcslen(wzFunctionName) > 0)
    {
        RtlInitUnicodeString(&uniFunctionName, wzFunctionName);      
        FunctionAddress = MmGetSystemRoutineAddress(&uniFunctionName);  
    }

    return FunctionAddress;
}

LONG GetSSDTApiFunctionIndexFromNtdll(char* szFindFunctionName)
{

    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    PVOID    MapBase = NULL;
    PIMAGE_NT_HEADERS       NtHeader;
    PIMAGE_EXPORT_DIRECTORY ExportTable;
    ULONG*  FunctionAddresses;
    ULONG*  FunctionNames;
    USHORT* FunctionIndexs;
    ULONG   ulIndex;
    ULONG   i;
    CHAR*   szFunctionName;
    SIZE_T  ViewSize=0;
    ULONG_PTR ulFunctionAddress;
    WCHAR wzNtdll[] = L"\\SystemRoot\\System32\\ntdll.dll";

    Status = MapFileInUserSpace(wzNtdll, NtCurrentProcess(), &MapBase, &ViewSize);
    if (!NT_SUCCESS(Status))
    {
        return STATUS_UNSUCCESSFUL;
    }
    else
    {
        __try{
            NtHeader = RtlImageNtHeader(MapBase);
            if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress){
                ExportTable =(IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)MapBase + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
                FunctionAddresses = (ULONG*)((ULONG_PTR)MapBase + ExportTable->AddressOfFunctions);
                FunctionNames = (ULONG*)((ULONG_PTR)MapBase + ExportTable->AddressOfNames);
                FunctionIndexs = (USHORT*)((ULONG_PTR)MapBase + ExportTable->AddressOfNameOrdinals);
                for(i = 0; i < ExportTable->NumberOfNames; i++)
                {
                    szFunctionName = (LPSTR)((ULONG_PTR)MapBase + FunctionNames[i]);
                    if (_stricmp(szFunctionName, szFindFunctionName) == 0) 
                    {
                        ulIndex = FunctionIndexs[i]; 
                        ulFunctionAddress = (ULONG_PTR)((ULONG_PTR)MapBase + FunctionAddresses[ulIndex]);
                        ulIndex=*(ULONG*)(ulFunctionAddress+IndexOffsetOfFunction);
                        break;
                    }
                }
            }
        }__except(EXCEPTION_EXECUTE_HANDLER)
        {

        }
    }

    if (ulIndex == -1)
    {
        DbgPrint("%s Get Index Error\n", szFindFunctionName);
    }

    ZwUnmapViewOfSection(NtCurrentProcess(), MapBase);
    return ulIndex;
}

NTSTATUS 
    MapFileInUserSpace(WCHAR* wzFilePath,IN HANDLE hProcess OPTIONAL,
    OUT PVOID *BaseAddress,
    OUT PSIZE_T ViewSize OPTIONAL)
{
    NTSTATUS Status = STATUS_INVALID_PARAMETER;
    HANDLE   hFile = NULL;
    HANDLE   hSection = NULL;
    OBJECT_ATTRIBUTES oa;
    SIZE_T MapViewSize = 0;
    IO_STATUS_BLOCK Iosb;
    UNICODE_STRING uniFilePath;

    if (!wzFilePath || !BaseAddress){
        return Status;
    }

    RtlInitUnicodeString(&uniFilePath, wzFilePath);
    InitializeObjectAttributes(&oa,
        &uniFilePath,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        NULL,
        NULL
        );

    Status = IoCreateFile(&hFile,
        GENERIC_READ | SYNCHRONIZE,
        &oa,
        &Iosb,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ,
        FILE_OPEN,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0,
        CreateFileTypeNone,
        NULL,
        IO_NO_PARAMETER_CHECKING
        );

    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    oa.ObjectName = NULL;
    Status = ZwCreateSection(&hSection,
        SECTION_QUERY | SECTION_MAP_READ,
        &oa,
        NULL,
        PAGE_WRITECOPY,
        SEC_IMAGE,
        hFile
        );
    ZwClose(hFile);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    if (!hProcess){
        hProcess = NtCurrentProcess();
    }

    Status = ZwMapViewOfSection(hSection, 
        hProcess, 
        BaseAddress, 
        0, 
        0, 
        0, 
        ViewSize ? ViewSize : &MapViewSize, 
        ViewUnmap, 
        0, 
        PAGE_WRITECOPY
        );
    ZwClose(hSection);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    return Status;
}

ULONG_PTR GetFunctionAddressByIndexFromSSDT32(ULONG_PTR ulIndex,ULONG_PTR SSDTDescriptor)
{
    ULONG_PTR ServiceTableBase= 0 ;
    PSYSTEM_SERVICE_TABLE32 SSDT = (PSYSTEM_SERVICE_TABLE32)SSDTDescriptor;

    ServiceTableBase=(ULONG)(SSDT ->ServiceTableBase);

    return (*(PULONG_PTR)(ServiceTableBase + 4 * ulIndex));
}

VOID WPOFF()
{
    ULONG_PTR cr0 = 0;
    Irql = KeRaiseIrqlToDpcLevel();
    cr0 =__readcr0();
    cr0 &= 0xfffffffffffeffff;
    __writecr0(cr0);
    //_disable();
}

VOID WPON()
{
    ULONG_PTR cr0=__readcr0();
    cr0 |= 0x10000;
    //_enable();
    __writecr0(cr0);
    KeLowerIrql(Irql);
}


