2P by GN⁺ 4일전 | ★ favorite | 댓글 1개
  • Windows에서는 드라이브 문자로 A~Z 외의 기호나 비ASCII 문자도 사용할 수 있음
  • 내부적으로 Win32 경로(C:\foo)는 NT 네임스페이스 경로(\??\C:\foo) 로 변환되어 처리됨
  • 이 구조는 Object Manager가 관리하며, C: 같은 드라이브 문자는 단순한 심볼릭 링크 객체로 존재함
  • subst 명령어를 이용하면 +:€: 같은 비표준 드라이브 문자를 생성할 수 있으나, Explorer나 PowerShell은 이를 인식하지 못함
  • 이러한 동작은 Windows 경로 처리의 내부 구조와 인코딩 방식(WTF-16 등) 을 이해하는 데 중요한 단서가 됨

드라이브 문자의 내부 구조

  • Windows의 일반 경로(C:\foo)는 Win32 네임스페이스 경로이며, API 호출 시 NT 네임스페이스 경로로 변환됨
    • 예: CreateFileW("C:\foo") 호출 시 내부적으로 NtCreateFile("\??\C:\foo")로 변환
  • \??는 Object Manager의 가상 폴더로, \GLOBAL?? 및 사용자별 DosDevices 폴더를 결합한 형태
  • C: 객체는 \GLOBAL?? 내의 심볼릭 링크로 존재하며, 실제 장치 경로 \Device\HarddiskVolume4로 연결됨
  • 따라서 C:는 특별한 예약 문자가 아니라, 일반적인 심볼릭 링크 이름으로 취급됨

드라이브 문자의 정의

  • 드라이브 문자는 Win32 경로를 NT 경로로 변환하는 과정의 산물
    • 변환 함수 RtlDosPathNameToNtPathName_UC:\foo\??\C:\foo로 변환
  • 이 함수는 +: 같은 비표준 문자도 동일하게 처리하므로, +: 객체가 존재하면 +:\ 경로도 정상 작동
  • subst +: C:\foo 명령으로 생성된 +: 객체는 사용자별 DosDevices 폴더에 저장됨

비표준 드라이브 문자의 동작

  • Explorer.exe는 A~Z 범위만 탐색하므로 +: 드라이브는 표시되지 않음
  • PowerShell도 비ASCII 드라이브를 인식하지 못하고 오류를 반환
  • 그러나 cmd.exe에서는 +:€: 같은 드라이브가 정상 작동

비ASCII 및 유니코드 드라이브 문자

  • subst €: C:\foo 명령으로 유로 기호(€) 드라이브 생성 가능
    • 대소문자 구분 없이 작동 (Λ:λ: 동일 인식)
  • 드라이브 문자는 단일 WTF-16 코드 유닛(U+FFFF 이하) 로 제한됨
    • 𤭢:처럼 U+FFFF를 초과하는 문자는 subst에서 오류 발생
    • MountPointManager를 직접 호출하면 생성은 가능하지만, Win32 경로 변환이 실패하여 접근 불가
  • 이는 Windows가 UTF-16 서러게이트 쌍을 완전 지원하지 않음을 보여줌

경로 판별 및 인코딩 문제

  • 언어별 경로 처리 구현이 RtlDosPathNameToNtPathName_U와 다를 수 있음
    • 예: Rust는 A-Z만 절대 경로로 인식 (C:\는 true, +:\는 false)
  • 인코딩 방식(WTF-8 vs WTF-16)에 따라 path[0], path[1] 등의 인덱스가 달라져 절대 경로 판별 결과가 달라질 수 있음
  • Zig 표준 라이브러리는 이 차이를 고려해 <= U+FFFF 범위까지 인식하도록 구현

SetVolumeMountPointW의 비ASCII 처리 버그

  • SetVolumeMountPointW("€:\", volume) 호출 시 성공하지만, 실제 생성된 링크는 ¬:로 나타남
  • 이는 0x20AC(€)가 0xAC잘려서 저장되는 현상으로 추정
  • 비ASCII 드라이브 문자를 처리하지 못하는 API의 한계를 보여주는 사례

결론

  • Windows는 내부적으로 드라이브 문자를 A~Z로 제한하지 않음
  • 제한은 Explorer, PowerShell 등 상위 레벨 도구의 구현 차이에서 발생
  • Win32와 NT 네임스페이스의 변환 구조, 인코딩 처리, Object Manager의 동작을 이해하면
    Windows 파일 시스템의 내부 메커니즘을 더 깊이 파악할 수 있음
Hacker News 의견
  • NT 경로는 Object Manager가 리소스를 참조하는 방식임
    예를 들어 HKEY_LOCAL_MACHINE\Registry\Machine의 별칭임
    NT는 전역 VFS 네임스페이스를 사용하는 점에서 Unix와 유사함
    드라이브 문자로 시작하는 경로는 DOS 호환성을 위한 “DOSPath”로, 커널 모드에서도 일부 서브시스템이 여전히 이를 사용함
    PowerShell에서는 다양한 리소스를 “드라이브”로 노출하며, hklm:\ 같은 기본 드라이브 외에도 커스텀 드라이브를 만들 수 있음
    관련 문서: PowerShell Drive 관리 샘플
    Linux/Bash에서는 인증서를 파일 경로로 접근할 수 없지만, PowerShell/Windows에서는 가능함
    NtObjectManager PowerShell 모듈을 설치해 ls NtObject:\로 탐색해보길 추천함
    모듈 링크

    • 30년이 지나도 Windows가 여전히 80년대식 디렉터리 구조에 묶여 있는 게 놀라움. 플로피 드라이브도 없는데 말임
    • PnP PowerShell의 PSDrive 프로바이더를 사용하면 SharePoint Online도 드라이브처럼 탐색 가능함
      Connect-PnPOnline 문서
    • Linux에서도 /usr/share/ca-certificates/etc/ssl/certs를 통해 인증서를 파일로 접근할 수 있음
      다만 Windows Registry만큼 통합되어 있지는 않음
    • ReactOS에는 NT Object 브라우저가 있어서 전체 Registry 계층을 GUI로 탐색할 수 있음
      Windows에서도 작동함
      ReactOS NT Object Browser 예시
    • Linux에서도 인증서는 단순한 파일 형태로 접근 가능함
      /etc/ca-certificates/extracted/cadir 아래에서 PEM 파일들을 직접 볼 수 있음
  • Windows는 파티션을 드라이브 문자 없이도 접근할 수 있음
    Linux처럼 디렉터리 아래에 마운트 가능하며, PowerShell의 Add-PartitionAccessPath 명령으로 설정 가능함
    재부팅 후에도 유지됨

    • 이 기능을 이용해 게임 설치 경로를 SD 카드로 우회한 적이 있음
      설치 프로그램은 SD 카드를 거부하지만, NTFS 마운트 포인트를 사용하면 속일 수 있음
      다만 일부 설치 프로그램은 상위 디스크의 여유 공간을 확인해 혼란스러워함
      영구 마운트에는 심볼릭 링크가 더 유용함
    • PowerShell 없이도 디스크 관리 도구에서 “드라이브 문자 및 경로 변경” 메뉴로 설정 가능함
    • NTFS 마운트 포인트는 경로를 커스터마이즈할 수 없는 소프트웨어를 우회할 때 유용함
      서로 다른 성능 정책의 VM 디스크를 하나의 경로로 묶을 수 있음
    • 단, NTFS 간에만 가능함. exFAT이나 ReFS는 지원하지 않음
      GUI에서 파티션을 만들 때 “드라이브 문자 할당” 대신 “경로로 마운트”를 선택할 수 있음
    • 일부 프로그램(예: Steam)은 상위 디스크의 여유 공간을 확인해 설치를 거부할 수 있음
  • “€:\” 같은 드라이브 문자는 저주스럽지만 멋진 예시임
    NT 커널은 사용자에게 노출된 것보다 훨씬 유연함

    • 대부분의 사람들은 Windows NT의 DOS 외피만 알고 있음
      내부에는 GUID 매핑 기반의 복잡한 구조가 숨어 있음
      예를 들어 {GUID} 이름의 바로가기를 만들면 숨겨진 기능으로 연결되기도 함
      이런 구조 덕분에 Windows는 멀웨어의 온상이 되기도 함
    • 코드페이지에 따라 이런 드라이브 문자는 접근조차 불가능할 수 있음
    • 진짜 유연하려면 드라이브 문자를 이모지로 쓸 수 있어야 함
  • File Explorer는 A~Z 이외의 드라이브 문자를 인식하지 않음
    그래서 드라이브 문자를 전부 이모지로 바꾸는 꿈은 불가능함

    • 대부분의 이모지는 UTF-16 한 코드 유닛으로 표현되지 않아 제한적임
    • 일부 스마일 이모지는 코드페이지에 따라 가능함
      대신 autorun.inf로 드라이브 아이콘을 이모지로 바꾸는 편이 낫고, 라벨에도 이모지를 넣을 수 있음
    • 컴퓨터 이름에는 이모지를 쓸 수 있음
  • Win9x 시절 ALT + 255 트릭으로 탐색기에서 접근 불가한 폴더를 만들 수 있었음

    • 그 방법으로 기숙사 컴퓨터에 Duke Nukem을 숨겨두곤 했음
    • 최근까지도 Registry 키에 같은 방식으로 접근을 막을 수 있었음
    • 지금은 더 심각함. Windows 10/11 보안 취약점 사례
  • Xbox 360 개발 환경에서는 드라이브 문자가 문자열 형태였음
    예: Game:\foo, Hdd0:\foo

    • 맞음, 실제로 존재했음
      Xenia 에뮬레이터는 이를 심볼릭 링크 기반 가상 파일 시스템으로 처리함
      Xenia 코드 예시
  • Linux에는 비슷한 개념으로 Abstract Domain Socket이 있음
    첫 문자가 NUL(\0)인 Unix 도메인 소켓으로, 권한 제약을 우회할 수 있음
    게임 서버에서 각 플레이어의 리소스를 분리하면서도 통신을 유지하기 위해 사용 중임

    • /proc/net/unix에서 해당 소켓을 찾을 수도 있음
  • 이런 기능은 악성코드를 만들기 좋은 환경처럼 들림
    숨겨진 마운트나 이상한 드라이브 이름으로 시스템을 교란할 수 있을 듯함

    • 하지만 실제로는 NT 경로가 실제 볼륨에 매핑되어야 하므로, 완전히 숨기기는 어려움
    • Alternate Data Streams를 알게 되면 더 놀랄 것임
    • 드라이브를 조작하려면 관리자 권한이 필요함
  • 여러 장의 디스크 이미지를 마운트해야 하는 경우, 드라이브 문자가 매우 혼란스러워짐
    예를 들어 36개의 DVD ISO를 마운트하면 명령줄 인용부호 지옥을 경험하게 됨

  • 예전 DOS(아마 3.3 버전)에서는 Z 다음 드라이브 문자가 AA였음
    작은 RAM 드라이브를 여러 개 만들어 확인했었음

    • Netware에서도 Z를 넘어서는 드라이브 매핑이 가능했음을 기억함