심플스 - 프로그램과 책 이야기로 가득한 곳, (Simples.Kr)

  

DosPathNameToNtPathName

Windows Research 조회 수 10008 추천 수 0 2010.09.03 17:36:03
 

Win32와 드라이버간에 통신을 할 때 Win32에서 드라이버에게 파일경로를 넘겨주어야 할 때가 있었는데 Win32에서
C 드라이브를 경로에 경우 "C:\\"와 같이 접근하면 되지만 드라이버에서는 "\\??\\C:\\" 와 같이 접근을 해야 합니다.

간단하게 위와 같은 경우에는 앞에 "\\??\\" 를 붙여주면 되지만 네트워크 공유 폴더에 경우에는
또 다른 방식으로 이름을 지정해 주어야 합니다.

즉, 상황에 따라 Win32에서 파일 이름을 파싱하여 드라이버에서 인식 할 수 있는 이름으로 변환 후 드라이버에 넘겨주곤 하였는데
좀 더 깔끔한 방법을 소개하려고 합니다.

사실 조금만 생각해보면 Kernel32.CreateFileA는 Kernel32.CreateFileW를 호출하게 되고
( Win32에서 유니코드와 그렇지 않은 API로 나뉘어지는데 유니코드가 아닌 함수는 내부적으로 유니코드로 변환하여
  유니코드용 함수를 호출하게 됩니다. 그래서 유니코드로 만들어진 프로그램이 빠르다는 말이 있죠.. )
Kernel32.CreateFileW는 내부적으로 NtDll.NtCreateFile 를 호출할 것입니다.

그리고 여기서 NtCreateFile은 파일이름을 인자로 받지 않습니다.
즉, 그 전에 파일 이름이 NtPathName으로 변환된다는 말입니다.

IDA로 Kernel32.DLL를 열어본 후 Export 된 CreateFileW에서 호출하는 함수들을 보면 다음과 같이 바로 눈에 띄는 함수가 있습니다.
( 해당 Kernel32.DLL은 Windows XP SP2 입니다. 버전이 다른 운영체제에 경우에는 다른 함수를 사용하는 경우도 있습니다. )


b0072382_4971b1f3078e5.png 


함수 이름에서 이미 무엇을 하는 함수인지 설명이 다 되어 있습니다.
구글링을 조합한 해당 함수를 사용하는 예제코드는 다음과 같습니다.

#include <Windows.h>
typedef struct _UNICODE_STRING {
    USHORT  Length;
    USHORT  MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef BOOLEAN (__stdcall *RtlDosPathNameToNtPathName_U)(PCWSTR DosName,
                                                          PUNICODE_STRING NtName, 
                                                          PCWSTR *DosFilePath OPTIONAL, 
                                                          PUNICODE_STRING NtFilePath );
typedef void (__stdcall *RtlFreeUnicodeString)(     
    PUNICODE_STRING UnicodeString
    );
int _tmain(int argc, _TCHAR* argv[])
{
    RtlDosPathNameToNtPathName_U pRtlDosPathNameToNtPathName_U;
    RtlFreeUnicodeString pRtlFreeUnicodeString;
    HMODULE hModule;
    UNICODE_STRING NtName;
    hModule = ::LoadLibrary(_T("NtDLL.DLL"));
    if (hModule == NULL)
    {
        printf("NTDLL을 로드 할 수 없습니다.\n");
        return (-1);
    }
    pRtlDosPathNameToNtPathName_U = (RtlDosPathNameToNtPathName_U)::GetProcAddress(hModule, "RtlDosPathNameToNtPathName_U");
    if (pRtlDosPathNameToNtPathName_U == NULL)
    {
        printf("RtlDosPathNameToNtPathName_U API를 찾을 수 없습니다.\n");
        return (-1);
    }
    pRtlFreeUnicodeString = (RtlFreeUnicodeString)::GetProcAddress(hModule, "RtlFreeUnicodeString");
    if (pRtlFreeUnicodeString == NULL)
    {
        printf("RtlFreeUnicodeString API를 찾을 수 없습니다.\n");
        return (-1);
    }
    if (pRtlDosPathNameToNtPathName_U(_T("\\\\10.1.26.15"), &NtName, NULL, NULL) == FALSE)
    {
        printf("pRtlDosPathNameToNtPathName_U 실패\n");
        return 0;
    }
    // 가져온 이름을 출력
    ::MessageBoxW(0, NtName.Buffer, _T("확인"), 0);
    pRtlFreeUnicodeString(&NtName);
    return 0;
}

위에 코드를 통해서 DosPathName을 NtPathName으로 변경할 수 있습니다.
예제 코드에서는 _T("\\\\10.1.26.15") 에 NtPathName를 얻으려고 하였습니다.

실행결과는 다음과 같습니다.


b0072382_4971b1f3078e5.png 



참고로 이 함수는 유저레벨에서만 사용 할 수 있고 인자로 넘겨주는 경로가 존재하지 않아도 상관이 없습니다.
즉, 경로를 드라이버에서 사용가능한 경로로 변환할 뿐 경로가 올바른지는 확인하지 않습니다.

해당 함수가 Undocumented 된 API이긴 하지만 제가 테스트해봤을 때는 거의 모든 운영체제에서 돌아갔습니다.
테스트한 운영체제는..
Windows XP SP2, Windows 2003 Server, Windows XP 64Bit, Windows Vista 64Bit, Windows 7 64Bit 입니다.
( 그냥 다 된다고 보시면 됩니다.-_- )

List of Articles
번호 제목 글쓴이 날짜 조회 수
163 Linux Tip 리눅스 기반 오픈 소스 사이트 모음 삽질신 2009-11-16 76960
162 Linux Tip VirtualBox에 우분투 설치 후에 내부 네트워크 접속 설정하기 file esniper 2010-09-10 36788
161 Windows Research IE Cache 경로 변경하기 lain 2011-06-09 33390
160 Windows Research VMWare 탐지 기법 우회 - 2 [2] lain 2011-04-04 31529
159 Windows Research 화면캡쳐방지는 어떻게 구현될까? [3] lain 2010-09-04 31485
158 Linux Tip Directory index forbidden by Options directive 삽질신 2009-11-16 21933
157 PHP Tip php 파싱 라이브러리 - snoopy esniper 2009-03-26 21778
156 Linux Tip VirtualBox에서 오른쪽 CTRL키 사용하기(VitualBox 호스트키) file [2] esniper 2010-09-10 20990
155 Windows Tip SSH 터널링 - putty의 plink 사용예 esniper 2009-03-26 20593
154 문서자료 고품질의 무료 아이콘들 [3] esniper 2010-09-08 20518
153 문서자료 json 문법 체크 사이트 Lyn 2012-02-28 20476
152 Windows Research 커널레벨에서 IAT Hook lain 2011-06-11 19522
151 PHP Tip mysql_insert_id() - 마지막 insert 된 아이디 값 esniper 2009-03-26 19454
150 Windows Research SetEvent 함수는 언제 실패할까? lain 2010-09-04 18885
149 Linux Tip 우분투 설치 후 putty에서 한글 안 깨지도록 설정하기 file esniper 2010-09-10 18346
148 Windows Research Sysinternals - Regmon source code file [1] lain 2010-09-04 17992
147 Linux Tip 우분투 ssh or mysql 서버 접속지연이 있는 경우 해결책 esniper 2010-09-10 17875
146 Windows Research 유저 레벨에서 API Hook 1부 file [1] lain 2010-09-03 17811
145 Windows Research Sysinternals - Filemon source code file [5] lain 2010-09-04 17583
144 Linux Tip Wget 완벽 정리 esniper 2009-03-26 17559

  • 이용약관
  • 개인정보취급방침
  • 사이트맵