2014年6月14日星期六

内核(对象管理器)中的systemroot

#include <ntifs.h>
#include <windef.h>

#define TAG 'tset' //test

/*
用户层常用%systemroot%,很是方便,驱动呢?
在对象目录的根目录下有个符号链接systemroot,其值是:"\Device\Harddisk0\Partition1\Windows"。
但是在XP的应用层和驱动都没有导出RtlExpandEnvironmentStrings_U。
本文就是演示这些东西的。

注意:
"\Device\Harddisk0\Partition1"
"\Device\HarddiskVolume1" 
"\\.\Harddisk0Partition1"
"\\.\PhysicalDrive0"
的关系。

如果不转换去打开文件的结果是://C0000034 系统找不到指定的文件。
用L"systemroot"或者L"%systemroot%"后面加文件去打开文件,返回的结果是:C000003b 指定的路径无效。

注意:
这个可以在系统启动的很早的时候获取,那时候文件驱动可能还没有加载,但是对象管理器已经初始化了。

made by correy
made at 2014.06.14
homepage:http://correy.webs.com
*/


DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{   
    
}


#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{ 
    ULONG ActualLength;
    HANDLE LinkHandle = 0;
    WCHAR NameBuffer[MAX_PATH];
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING LinkString, NameString, file_name, temp;
    NTSTATUS status = STATUS_SUCCESS;
    USHORT x = 0;

    KdBreakPoint();

    DriverObject->DriverUnload = Unload; 

    LinkString.Buffer = NameBuffer;
    LinkString.MaximumLength = sizeof(NameBuffer);
    RtlZeroMemory(NameBuffer, sizeof(NameBuffer));

    RtlInitUnicodeString(&NameString, L"\\systemroot");//注意格式。
    InitializeObjectAttributes(&ObjectAttributes, &NameString, OBJ_KERNEL_HANDLE, NULL, NULL);
    status = ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY | GENERIC_READ , &ObjectAttributes);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ZwOpenSymbolicLinkObject fail with 0x%X\n",status));
        ZwClose(LinkHandle);
        return status;
    }

    status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkString, &ActualLength);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ZwQuerySymbolicLinkObject fail with 0x%X\n",status));
        ZwClose(LinkHandle);
        return status;
    }

    KdPrint(("%wZ \n",&LinkString));//得到的值形如:"\Device\Harddisk0\Partition1\Windows"。
    ZwClose(LinkHandle);


    /*
    还得对这个路径进行解析,对象管理器在下面的情况(ZwOpenFile)是不会解析的,而是返回C0000034 系统找不到指定的文件。
    注意:这是这偷懒不好的解析方式,仅仅演示用的。实际的工程要改进。
    */
    for (x = LinkString.Length; x > 0; x -= 2)
    {
        if (LinkString.Buffer[x/2] == L'\\')
        {
            break;
        }
    }

    temp.Buffer = &LinkString.Buffer[x/2];
    temp.Length = LinkString.Length - x;
    temp.MaximumLength = LinkString.MaximumLength - x;

    LinkString.Length = x; 
    //以上是把UNICODE_STRING以最后的斜杠一分为二。主要是因为转换后的数据也写入这里但是不会造成破坏。这是假定。

    InitializeObjectAttributes(&ObjectAttributes, &LinkString, OBJ_KERNEL_HANDLE, NULL, NULL);
    status = ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY | GENERIC_READ , &ObjectAttributes);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ZwOpenSymbolicLinkObject fail with 0x%X\n",status));
        ZwClose(LinkHandle);
        return status;
    }

    status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkString, &ActualLength);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ZwQuerySymbolicLinkObject fail with 0x%X\n",status));
        ZwClose(LinkHandle);
        return status;
    }

    KdPrint(("%wZ \n",&LinkString));//得到的值形如:"\Device\Harddisk0\Partition1\Windows"。
    ZwClose(LinkHandle);

    
    /*status = RtlAppendUnicodeToString(&LinkString, &LinkString.Buffer[x]);
    if (!NT_SUCCESS (status)) {
        KdPrint(("RtlAppendUnicodeToString fail with 0x%X!\n", status));
        return status;
    }*/

    status = RtlAppendUnicodeStringToString(&LinkString, &temp );
    if (!NT_SUCCESS (status)) {
        KdPrint(("RtlAppendUnicodeStringToString fail with 0x%X!\n", status));
        return status;
    }


    /*
    测试用例一:
    这个应该是成功的。
    */
    {
        UNICODE_STRING file_name, temp ;
        OBJECT_ATTRIBUTES ob;
        HANDLE FileHandle = 0;
        IO_STATUS_BLOCK  IoStatusBlock = {0};

        file_name.Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG);
        if (file_name.Buffer == NULL) { 
            DbgPrint("发生错误的文件为:%s, 代码行为:%d\n", __FILE__, __LINE__);
            return STATUS_UNSUCCESSFUL ;
        }
        RtlZeroMemory(file_name.Buffer, MAX_PATH);
        RtlInitEmptyUnicodeString(&file_name, file_name.Buffer,MAX_PATH);

        RtlCopyUnicodeString(&file_name, &LinkString);
        status = RtlAppendUnicodeToString(&file_name, L"\\regedit.exe");
        if (!NT_SUCCESS (status)) {
            KdPrint(("RtlAppendUnicodeToString fail with 0x%X!\n", status));
            if (file_name.Buffer)
            {
                ExFreePoolWithTag(file_name.Buffer, TAG);
                file_name.Buffer = NULL;
            }
            return status;
        }

        InitializeObjectAttributes(&ob, &file_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
        status = ZwOpenFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ob, &IoStatusBlock, FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
        if (!NT_SUCCESS (status)) 
        {
            KdPrint(("ZwOpenFile fail with 0x%x.\n", status));
            if (file_name.Buffer)
            {
                ExFreePoolWithTag(file_name.Buffer, TAG);
                file_name.Buffer = NULL;
            }
            return status;
        }

        //测试结束的扫尾工作。

        if (file_name.Buffer)
        {
            ExFreePoolWithTag(file_name.Buffer, TAG);
            file_name.Buffer = NULL;
        }

        if (FileHandle)
        {
            status = ZwClose(FileHandle);
            if (!NT_SUCCESS (status)) {
                KdPrint(("ZwClose fail with 0x%x.\n", status));
            } else {
                FileHandle = NULL;
            }
        }
    }

    return status;
} 

没有评论:

发表评论