FileSystemFilterDriver 파일숨기기
2009/06/14 13:19

ZwQueryDirectoryFile

Window XP이후 버전 에서 폴더내 파일 또는 폴더의 정보를 얻기 위한 과정은 ZwCreateFile 또는 ZwOpenFile을 통해 얻어진 handle을 통해 ZwQueryDirectoryFile 에서 디렉토리에 대한 파일 또는 폴더 정보를 query하여 얻는다.
즉 윈도우에서 탐색기 혹은 cmd 창에서 dir 명령어도 Win32 API 에서 파일 및 폴더 정보를 얻어오는 과정과 사용된 API가 다르겠지만 결국 Native API 인 ZwQueryDirectoryFile 을 통해서 디렉토리내 파일 또는 폴더명을 얻는다는 이야기다.
따라서 파일 또는 폴더를 숨기기 위해서는 ZwQueryDirectoryFile 함수를 Hooking 하여 원하는 파일 또는 폴더를 숨길수 있다는 이야기다.

IRP_MJ_DIRECTORY_CONTROL

Hooking을 하지 않고 파일필터 드라이버에서 파일 및 폴더를 숨기는 기능을 수행하기 위해서는 아래의 IRP funtion code를 참고하면 된다.

IRP stack의 Major Function 이 IRP_MJ_DIRECTORY_CONTROL
IRP stack의 Minor Function 이 IRP_MN_QUERY_DIRECTORY

위의 두가지 Funtion code외에 FileInformationClass 를 조사하여야 한다.

IRP stack의 Parameters->FileInformationClassFileBothDirectoryInformation

대부분의 win32에서의 폴더내의 파일 및 파일 열거에 대한 호출은 FileBothDirectoryInformation(VISTA에서는 FileIdBothDirectoryInformation 로 변경)이다. 따라서 대부분 FileBothDirectoryInformation로 원하는 처리(파일 또는 풀더 숨김)가 가능하지만 보다 강력한(?) 숨기기 기능을 원하다면 FilFullDirectoryInformation, FileNameInformation, FileDirectoryInfomation class도 대한 처리도 필요하지 않을까 싶다.

전처리

원하는 조건은 다 충족되었다.
이제 파일 또는 폴더 숨기는 작업을 수행하여야 하는데 그전에 알아두어야 할 것이있다.

조건이 만족된 지금 현재 상태는 File System Driver로 IRP를 넘겨 주기 전 이기 때문에 파일 및 폴더에 어떤 정보도 알지 못한다. 따라서 지금 처리할수 있는 작업은 폴더에 대한 접근 거부(STATUS_ACCESS_DENIED) 또는 폴더내 어떤 파일도 보여주지 않는 작업(STATUS_NO_SUCH_FILE)만이 가능하다.

후처리

조건이 만족한 상태라면 파일 숨기는 기능을 처리해야 하지만 위의 전처리에서 설명했다시피 폴더 및 파일에 대한 정보를 아직 얻지 못한 상태이기때문에 어떠한 가공(?)도 할수 없다.
따라서 IoSetCompletionRoutine 을 통해 IRP가 완료한 시점에 다시 호출받도록 설정하여 File System Driver가 모든 작업을 완료하고 나서 다시 호출될수 있도록 해야 한다.
그래야만 File System Driver에서 얻어지 파일 또는 폴더에 대한 정보를 가공(?) 할수 있다.

완료루틴

IoSetCompletionRoutine 에서 설정한 대로 File System Driver에서 작업을 완료하고 완료루틴이 호출되면 원하는 파일 또는 폴더에 대한 작업을 수행한다.
파일 또는 폴더에 대한 정보는 Irp->UserBuffer 에 넘겨져 온다.
이 정보를 제대로 파악하기 위해서는 아래의 parameter를 참고해야한다.

IrpSp->Parameters.QueryDirectory.Length
버퍼의 길이 - METHOD_NEITHER를 사용하기 때문에 Irp->UserBuffer 의 크기
IrpSp->Parameters.QueryDirectory.FileName
파일 열거를 위한 매칭패턴을 위해 사용됨. 첫 호출에만 제공됨. 그 이후 NULL이면 *, *.* 패턴과 동일시 됨
IrpSp->Parameters.QueryDirectory.FileInformationClass
결과에 대한 데이타 구조체 형식, MSDN 참고
IrpSp->Parameters.QueryDirectory.FileIndex
열거가 발생할 시작 index

처음에 언급했던바처럼 FileBothDirectoryInformation 에 대한 class 만 참고하다면
pFileInfo = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer 와 같은 casting 을 통해 pFileInfo 를 통해 파일 정보를 구할수 있다.(PFILE_BOTH_DIR_INFORMATION 는 각각의 파일에 대한 정보를 담고 있으며 NextEntryOffset으로 다음 정보에 대한 offset값을 가지고 있다.)
파일정보에서 특정파일을 숨기기 위해서는 NextEntryOffset 값을 건너 뛰도록 offset 값을 조작하여 파일을 숨긴다.

주의해야 할점이라면 버퍼의 용량이 그다지 크지 않기 때문에 특정 폴더에 대한 query 시 폴더내 모든 파일(폴더)의 정보가 한번에 넘어오지 않는다. (경험상 약 30개 파일의 정보 단위로 넘어오는듯)
한 폴더에 약 100개의 파일이 존재한다면 30개씩 약 4번에 걸쳐 모든 정보가 넘어온다.

또한 Irp->Flags parameter도 참고하여야 한다.

SL_RESTART_SCAN 첫번째 부터 스캔
SL_RETURN_SINGLE_ENTRY 한개만 스캔
SL_INDEX_SPECIFIED FileIndex 에서 부터 스캔

FindFirst/FindNext 과 같은 win api에서는 flags가 SL_RETURN_SINGLE_ENTRY 가 설정되어 파일이 한개만 조사되기 때문에구조체에 한개 파일의 정보만 담겨진다.
따라서 NextEntryOffset 값을 조작하는데 유의해야한다. 이는 여러개의 파일정보가 있으나 숨기고자 하는 파일정보가 마지막에 위치하였을때도 마찬가지다.
(편법으로 파일이름을 . 으로 대체하기도 했음)

code snippet

FileInformationClass 에 따라 FileName 및 FileNameLength 얻기
[code c++]
switch(irpsp->Parameters.QueryDirectory.FileInformationClass)
{
 case FileBothDirectoryInformation:
  p = ((PFILE_BOTH_DIR_INFORMATION)buf)->FileName;
  len = &(((PFILE_BOTH_DIR_INFORMATION)buf)->FileNameLength);  
  sp = ((PFILE_BOTH_DIR_INFORMATION)buf)->ShortName;  
  slen = ((PFILE_BOTH_DIR_INFORMATION)buf)->ShortNameLength;  
  break;  
 case FileFullDirectoryInformation:   
  p = ((PFILE_FULL_DIR_INFORMATION)buf)->FileName;  
  len = &(((PFILE_FULL_DIR_INFORMATION)buf)->FileNameLength);  
  break;  
 case FileDirectoryInformation:   
  p = ((PFILE_DIRECTORY_INFORMATION)buf)->FileName;  
  len = &(((PFILE_DIRECTORY_INFORMATION)buf)->FileNameLength);  
  break;  
 case FileIdBothDirectoryInformation:  
  p = ((PFILE_ID_BOTH_DIR_INFORMATION )buf)->FileName;  
  len = &(((PFILE_ID_BOTH_DIR_INFORMATION )buf)->FileNameLength);  
  sp = ((PFILE_BOTH_DIR_INFORMATION)buf)->ShortName;  
  slen = ((PFILE_BOTH_DIR_INFORMATION)buf)->ShortNameLength;  
  break;
...
}
[/code]

2009/06/14 13:19 2009/06/14 13:19
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다

  • TWEETY 2009/06/29 10:29  댓글주소  수정/삭제  댓글쓰기
    그림이 안보여~~
  • 오곡 2013/07/04 10:57  댓글주소  수정/삭제  댓글쓰기
    잘배우고 갑니다 ^^