首页
社区
课程
招聘
[求助]关于NtOpenFile和NtCreateFile
发表于: 2014-7-18 00:07 17902

[求助]关于NtOpenFile和NtCreateFile

2014-7-18 00:07
17902
今天用CreateFile打开一个分区目录下的文件,然后用NtQueryObject查询了ObjectNameInformation,获得了文件对应的NT路径。
然后现在想把对应的NT路径转换为Dos路径,就是我们常用的C:\a.txt

查看过网上资料
http://bbs.pediy.com/showthread.php?t=149851
RtlNtPathNameToDosPathName这个函数真心不会用,如果有前辈高人会用的,请指点一二

然后还是参照该贴4楼的话,自己做一张表,问题来了。
做表前首先要知道机器上各分区根目录(C:\)对于的 NT路径(\Device\harddiskvolume?)
参考资料应是用NtOpenFile或者NtCreateFile 打开分区目录,然后获得相应句柄,获取\Device\harddiskvolume? 但为什么我总是调用不成功了,返回的句柄总是0。

基本代码操作就是
UNICODE_STRING string;
RtlInitUnicodeString(&string,L"\\\\.\\C:\\");
OBJECT_ATTRIBUTES  os;
InitializeObjectAttributes(&os,
&string, OBJ_CASE_INSENSITIVE, NULL, NULL);

NtCreateFile(&Handle, FILE_TRAVERSE|FILE_LIST_DIRECTORY,&os,&ioStatusBlock, NULL,FILE_ATTRIBUTE_NORMAL,0,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL, 0);

疑问有几处,第一个就是UnicodeString的初始化根目录的写法L"\\\\.\\C:\\" 是这样吗?第二个就是NtCreateFIle的各个参数有写得不妥的吗?再在就是NtOpenFile基本情况和NtCreateFile一样,handle一直返回0。

到最后就是,这样直接打开根目录获取句柄的做法对吗?但是为什么操作文件就可以呢

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
是不是放错板块呢?还是都休息去了?
2014-7-18 00:40
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
附上自己写的代码

首先是普通文件的dos转nt

HANDLE keyhandle
=CreateFile(L"C:\\MyServiceLog.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);

                NTSTATUS Status = NtQueryObject((HANDLE)keyhandle,ObjectNameInformation,cInfoBuffer,0,&Size);
                if(Size > 0)
                {
                        Status = NtQueryObject((HANDLE)keyhandle,ObjectNameInformation,cInfoBuffer,Size,&Size);
                        if(NT_SUCCESS(Status))
                        {
                                pNameInfo = (POBJECT_NAME_INFORMATION)cInfoBuffer;
                                wprintf(L"%s\r\n",pNameInfo->Name.Buffer);
                        }
                }

然后就是想打开打开各分区根目录,用上面的方法获取NT路径

                OBJECT_ATTRIBUTES obj;
                UNICODE_STRING string;
                IO_STATUS_BLOCK IoStatusBlock;
                RtlInitUnicodeString(&string, L"\\\\.\\C\\MyService");
                //string.Length = wcslen(L"\\\\.\\C:");
                //string.MaximumLength = wcslen(L"\\\\.\\C:") + 1;
                //string.Buffer = (PWCH)malloc(sizeof(WCHAR)*string.Length);

                InitializeObjectAttributes(&obj,&string, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL);

                //NtOpenFile(&keyhandle,DIRECTORY_ALL_ACCESS,&obj,&IoStatusBlock,NULL,NULL);
                //NtCreateFile(&keyhandle,FILE_TRAVERSE |FILE_LIST_DIRECTORY, &obj, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0,FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT,NULL, 0);
(以上两函数句柄返回都是0)
2014-7-18 09:04
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
再给一段RtlNtPathNameToDosPathName的代码
                HMODULE hNTDLL = LoadLibrary(L"ntdll.dll");
                if(hNTDLL == NULL) return ;
                RtlNtPathNameToDosPathName = (_RtlNtPathNameToDosPathName)GetProcAddress(hNTDLL, "RtlNtPathNameToDosPathName");
                if(RtlNtPathNameToDosPathName == NULL) return ;
                //RtlGetProcessHeap = (_RtlGetProcessHeap)GetProcAddress(hNTDLL,"RtlGetProcessHeap");
                //if(RtlGetProcessHeap == NULL) return ;

                PWCHAR puBuffer = (PWCHAR)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, pNameInfo->Name.Length * sizeof(PWCHAR));
                PWCHAR  _puBuffer = (PWCHAR)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, pNameInfo->Name.Length * sizeof(PWCHAR));

                if(puBuffer == NULL || _puBuffer == NULL) return ;

                //RtlCopyMemory(puBuffer, pNameInfo->Name.Buffer, pNameInfo->Name.Length);
                //RtlCopyMemory(_puBuffer, pNameInfo->Name.Buffer, pNameInfo->Name.Length);

                RTL_UNICODE_STRING_BUFFER DosPath;
                DosPath.String.Buffer = pNameInfo->Name.Buffer;
                DosPath.String.Length = pNameInfo->Name.Length;
                DosPath.String.MaximumLength = pNameInfo->Name.MaximumLength;
                DosPath.ByteBuffer.Buffer = puBuffer;
                DosPath.ByteBuffer.StaticBuffer = _puBuffer;
                DosPath.ByteBuffer.Size = MAX_PATH;
                DosPath.ByteBuffer.StaticSize = MAX_PATH;
                DosPath.ByteBuffer.ReservedForAllocatedSize = 0;
                DosPath.ByteBuffer.ReservedForIMalloc = NULL;

                ULONG Disposition = 0;                  //(Disposition返回1)
                Status = RtlNtPathNameToDosPathName(0, &DosPath, &Disposition, NULL);
                if(NT_SUCCESS(Status))
                {
                        wprintf(L"DosPath.String.Buffer = %s\n",DosPath.String.Buffer);
                        wprintf(L"DosPath.ByteBuffer.Buffer = %s\n",DosPath.ByteBuffer.Buffer);
                        wprintf(L"DosPath.ByteBuffer.StaticBuffer = %s\n", DosPath.ByteBuffer.StaticBuffer);
                }
        }

真心求各位大神指导。
2014-7-18 09:06
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
上面RtlNtPathNameToDosPathName用到的结构体定义
typedef struct _RTL_BUFFER {
    PWCHAR    Buffer;
    PWCHAR    StaticBuffer;
    SIZE_T    Size;
    SIZE_T    StaticSize;
    SIZE_T    ReservedForAllocatedSize;
    PVOID     ReservedForIMalloc;
} RTL_BUFFER, *PRTL_BUFFER;

typedef struct _RTL_UNICODE_STRING_BUFFER {
    UNICODE_STRING String;
    RTL_BUFFER     ByteBuffer;
    WCHAR          MinimumStaticBufferForTerminalNul[sizeof(WCHAR)];
} RTL_UNICODE_STRING_BUFFER, *PRTL_UNICODE_STRING_BUFFER;

typedef        NTSTATUS
(NTAPI* _RtlNtPathNameToDosPathName)(
    __in ULONG Flags,
    __inout PRTL_UNICODE_STRING_BUFFER Path,
    __out_opt PULONG Disposition,
    __inout_opt PWSTR* FilePart
   );

_RtlNtPathNameToDosPathName RtlNtPathNameToDosPathName;
2014-7-18 09:07
0
雪    币: 69
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
6
....
2014-7-18 09:58
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
今天早上逆向了WDK里面的FilterGetDosName,发现
GetVolumeNameForVolumeMountPoint 和 GetVolumePathNamesForVolumeName
发现FilterGetDosName通过把NT路径拼接成 \\\\?\\Gobal\\Device\\HarddiskVolume3\\, 传入GetVolumeNameForVolumeMountPoint 获得Guid,得到的Guid再传入GetVolumePathNamesForVolumeName就获得对应的Dos路径。
问题虽然可以这样解决,但是NtCreateFile和NtOpenFile还是打不开分区目录,获取不了句柄!

最后windbg逆向知道NtOpenFile的第二个参数是0x00100080对应FILE_SEQUENTIAL_WRITE_ONCE|FILE_SUPPORTS_REPARSE_POINTS
目录句柄返回成功!
2014-7-18 10:03
0
雪    币: 249
活跃值: (196)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
楼主研究精神值得赞
2014-7-19 03:56
0
雪    币: 138
活跃值: (306)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
9
楼主到底是在驱动里转换还是在应用层转换?
之前写的一段,供参考.

上传的附件:
2014-7-19 12:46
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
[QUOTE=xSpy;1302099]楼主到底是在驱动里转换还是在应用层转换?
之前写的一段,供参考.

[/QUOTE]

其实我也不知道我自己写的算是r3 or r0    纯粹是不懂研究研究,多谢知识分享
2014-7-19 23:24
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
MARK,学习了。也学习楼主的钻研精神。
2014-8-11 09:25
0
游客
登录 | 注册 方可回帖
返回
//