zoukankan      html  css  js  c++  java
  • 关于在驱动当中使用__try __finally的问题

    今天调试一个驱动发现了一些平时没有考虑过的问题,在驱动当中使用__try和__finally时,在__try块直接使用return时会出现什么情况!

    我用wdk里面的例子做为我的测试代码,通过逆向发现在__try块执行return不会被执行到__finally中,而是马上就返回了。因此在__try块中直接使用return会非常的危险,强烈建议不要这样做!我今天就吃了大苦头。

    下面是我用来测试的代码,反汇编如下代码可看出一些端倪来:

     

    NTSTATUS DriverEntry(__in PDRIVER_OBJECT  DriverObject, __in PUNICODE_STRING RegistryPath)
    {
    
        
    
        PDEVICE_OBJECT      deviceObject;
        PDEVICE_EXTENSION   deviceExtension;
        UNICODE_STRING      ntDeviceName;
        UNICODE_STRING      symbolicLinkName;
        NTSTATUS            status;
    
        UNREFERENCED_PARAMETER(RegistryPath);
    
        DebugPrint(("==>DriverEntry\n"));
        
        __try
        {
    
            //
            // Create the device object
            //
            RtlInitUnicodeString(&ntDeviceName, NTDEVICE_NAME_STRING);
    
            status = IoCreateDevice(DriverObject,               // DriverObject
                                    sizeof(DEVICE_EXTENSION), // DeviceExtensionSize
                                    &ntDeviceName,              // DeviceName
                                    FILE_DEVICE_UNKNOWN,        // DeviceType
                                    FILE_DEVICE_SECURE_OPEN,    // DeviceCharacteristics
                                    FALSE,                      // Not Exclusive
                                    &deviceObject               // DeviceObject
                                   );
            if (!NT_SUCCESS(status))
            {
                DebugPrint(("\IoCreateDevice returned 0x%x\n", status));
                return status;
            }
            else
            {
                //
                // Set up dispatch entry points for the driver.
                //
                DriverObject->MajorFunction[IRP_MJ_CREATE]          = EventCreateClose;
                DriverObject->MajorFunction[IRP_MJ_CLOSE]           = EventCreateClose;
                DriverObject->MajorFunction[IRP_MJ_CLEANUP]         = EventCleanup;
                DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = EventDispatchIoControl;
                DriverObject->DriverUnload                          = EventUnload;
    
                //
                // Create a symbolic link for userapp to interact with the driver.
                //
                RtlInitUnicodeString(&symbolicLinkName, SYMBOLIC_NAME_STRING);
                status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName);
    
                //
                // Initialize the device extension.
                //
                deviceExtension = deviceObject->DeviceExtension;
    
                InitializeListHead(&deviceExtension->EventQueueHead);
    
                KeInitializeSpinLock(&deviceExtension->QueueLock);
    
                deviceExtension->Self = deviceObject;
    
                //
                // Establish user-buffer access method.
                //
                deviceObject->Flags |= DO_BUFFERED_IO;
    
                DebugPrint(("<==DriverEntry\n"));
    
                ASSERT(NT_SUCCESS(status));        
            }
        }
        __finally
        {
            if (!NT_SUCCESS(status))
            {
                IoDeleteDevice(deviceObject);
                DebugPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status));
            }
        }
    
        return status;
    }

     

    上面的函数当中__try块中会直接返回,我们用IDA看一下汇编代码是什么样子。

    我把它分成checked和free两个版本来看一下

     

    先看Checked版本的汇编:

     

    c_1

    ……………

    c_2

    从上面可以看出这儿直接就返回了,并没有执行到__finally当中的代码,return的代码被先执行到了!

     

     

    再看看free版本的汇编是什么样子:

    f_1

    上图中当IoCreateDevice失败之后就直接返回了,并没有执行到__finally当中

    f_2

    而真正的__finally块则是被放在最后执行了一下,__try块中间有任何返回都不会执行到__finally当中。

     

     

    因此,在__try中直接返回,不管是checked还是free版本,都不会执行到__finally块中的代码,这样使用会非常危险。我的结论是最好不要在驱动当中使用异常处理。今天写下来做一个备忘!

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    ES数据导入导出
    python Elasticsearch5.x使用
    http://elasticsearch-py.readthedocs.io/en/master/api.html
    Python Elasticsearch api
    es批量索引
    Razor字符串处理
    [.NET] ConfuserEx脱壳工具打包
    查看网页源码的时候找不到数据绑定
    HearthBuddy decompile
    Quickstart: Create and publish a package using Visual Studio (.NET Framework, Windows)
  • 原文地址:https://www.cnblogs.com/russinovich/p/2080139.html
Copyright © 2011-2022 走看看