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

  

 

( 주의 : 이 글에서 디스어셈블리되는 커널은 Windows XP SP2 이며 . ZwQueryInformationFile호출시 FileStandardInformation를 사용하였으므로 다른 인자를 사용하였다면 결과가 다르게 나타날 수 있습니다. )

ZwCreateFile을 이용해 파일 핸들을 열 때 비동기적으로 열어야 하는 경우가 생겼습니다.

이러한 경우 ZwReadFile로 파일을 읽을 때 두 번째 인자인 Event객체를 사용하여 WaitForSingleObject로 대기해야 하는 것으로 알고 있습니다.

그 러나 ZwQueryInformationFile에 경우에는 Event객체가 존재하지 않습니다. 그렇다면 윈도우즈 내부에서KeWaitForSingleObject을 호출 할 수도 있고 ( 만약에 비동기 모드로 파일의 핸들을 열었다면.. ),KeWaitForSingleObject 호출하지 않고 STATUS_PENDING을 리턴 할수도 있습니다.

내부적인 부분이라 알 수가 없고 STATUS_PENDING 리턴여부를 확실히 알아야 하기 때문에 WinDbg로 디버깅을 해보았습니다.

우선 파일을 비동기 모드로 연 후 ZwQueryInformationFile을 호출하기 바로 전에 브레이크 포인트를 걸어둡니다.


b0072382_4971b1f3078e5.png 


ZwQueryInformationFile은 내부적으로 NtQueryInformationFile 파일을 호출할 것이므로 다음과 같은 WinDbg명령줄을 이용해 브레이크 포인트를 겁니다.

bp nt!NtQueryInformationFile

그리고 F5를 눌러서 한 번 실행시킵니다.


b0072382_49a7de4994124.png 


위에 그림에서 보는 위치에서 멈추게 됩니다.
중요한건 콜스택을 잘 확인하여 내 드라이버에서 호출한 것이 맞는지 반드시 확인해보아야 합니다. ( 간혹 내 드라이버에서 호출하지 않은 경우가 있을 수 있습니다. )

F11를 눌르거나 계속해서 디버깅을 해보면 결국엔 IRP를 전송하기 위해 nt!IofCallDriver를 호출하게 되므로

bp nt!IofCallDriver

를 이용하여 다시 브레이크 포인트를 겁니다.

그리고 다시 F5를 누릅니다.


b0072382_4971b1f3078e5.png 


위와 마찬가지로 반드시 콜스택을 확인하여 내 드라이버에서 호출했는지 확인을 합니다. 이 상태에서 콜 스택을 보게 되면 이 함수를 호출 후 리턴되는 주소를 확인 할 수 있습니다.


b0072382_4971b1f3078e5.png 



그림에서 하이라이트 된 부분이 리턴되는 주소이며 해당 주소에 디스어셈블리 된 코드를 보면 다음과 같습니다.


b0072382_4971b1f3078e5.png 


위에서 보시면 KeWaitForSingleObject라는 함수를 어떠한 조건의 의해서 호출한다는 것을 알 수 있습니다.

8057bc3c 8b4dd4          mov     ecx,dword ptr [ebp-2Ch]
8057bc3f e87452f7ff      call    nt!IofCallDriver (804f0eb8)
8057bc44 8945d8          mov     dword ptr [ebp-28h],eax
8057bc47 817dd803010000  cmp     dword ptr [ebp-28h],103h
8057bc4e 0f85cc000000    jne     nt!NtQueryInformationFile+0x528 (8057bd20)
8057bc54 807de700        cmp     byte ptr [ebp-19h],0
8057bc58 745e            je      nt!NtQueryInformationFile+0x4c0 (8057bcb8)
8057bc5a 33ff            xor     edi,edi
8057bc5c 57              push    edi
8057bc5d 8b45dc          mov     eax,dword ptr [ebp-24h]
8057bc60 8b482c          mov     ecx,dword ptr [eax+2Ch]
8057bc63 c1e902          shr     ecx,2
8057bc66 81e101ffffff    and     ecx,0FFFFFF01h
8057bc6c 51              push    ecx
8057bc6d ff75cc          push    dword ptr [ebp-34h]
8057bc70 57              push    edi
8057bc71 83c05c          add     eax,5Ch
8057bc74 50              push    eax
8057bc75 e8300ff8ff      call    nt!KeWaitForSingleObject (804fcbaa)

이 부분은 IofCallDriver에 리턴값을 넣는 부분입니다.
리턴값은 NTSTATUS일 것 입니다.
8057bc44 8945d8          mov     dword ptr [ebp-28h],eax

그 후에 다음과 같이 0x103값과 비교하는데 이 값은
8057bc47 817dd803010000  cmp     dword ptr [ebp-28h],103h

다음과 같이 정의되어 있습니다.
#define STATUS_PENDING ((NTSTATUS)0x00000103L)    // winnt

즉, Pending여부를 체크한다는 것을 알 수 있습니다.
Pending이 아니라면 8057bd20주소로 점프하게 됩니다. Pedning이라면 다시 밑에서 무언가를 비교하게 되는데 byte ptr [ebp-19h]에 있는 이 값에 따라서 KeWaitForSingleObject를 호출할지 말지를 결정하게 됩니다. 중요한 것은 제 경우 테스트할 때 이 값은 0이 아니었으며 따라서 KeWaitForSingleObject를 호출하는 코드를 실행하게 됩니다. 또한 IofCallDriver호출 후 리턴한 후 강제적으로 eax레지스터에 STATUS_PENDING를 넣게 되면 KeWaitForSingleObject를 호출하게 됩니다.

참고로 만약 파일핸들을 동기화 모드로 열었다면 위에서 말한 코드 부분이 실행되지 않습니다.

결론은 ZwQueryInformationFile를 비동기 파일핸들로 호출 시에 내부적으로 STATUS_PENDING 여부를 체크하여
KeWaitForSingleObject로 대기합니다.

또한 ReactOS소스코드를 보시면 위와 비슷하게 구현되어 있는 것을 볼 수 있습니다. 물론 실제 윈도우즈 코드와 ReactOS소스코드가 완전히 같지는 않다는 것에 주의해야 할 것입니다.

List of Articles
번호 제목 글쓴이 날짜 조회 수
163 Linux Tip 리눅스 기반 오픈 소스 사이트 모음 삽질신 2009-11-16 70357
162 Linux Tip VirtualBox에 우분투 설치 후에 내부 네트워크 접속 설정하기 file esniper 2010-09-10 35105
161 Windows Research IE Cache 경로 변경하기 lain 2011-06-09 30603
160 Windows Research VMWare 탐지 기법 우회 - 2 [2] lain 2011-04-04 28574
159 Windows Research 화면캡쳐방지는 어떻게 구현될까? [3] lain 2010-09-04 28327
158 PHP Tip php 파싱 라이브러리 - snoopy esniper 2009-03-26 20530
157 Linux Tip Directory index forbidden by Options directive 삽질신 2009-11-16 20079
156 Linux Tip VirtualBox에서 오른쪽 CTRL키 사용하기(VitualBox 호스트키) file [2] esniper 2010-09-10 19500
155 Windows Tip SSH 터널링 - putty의 plink 사용예 esniper 2009-03-26 19403
154 문서자료 고품질의 무료 아이콘들 [3] esniper 2010-09-08 19270
153 문서자료 json 문법 체크 사이트 Lyn 2012-02-28 18693
152 PHP Tip mysql_insert_id() - 마지막 insert 된 아이디 값 esniper 2009-03-26 18237
151 Linux Tip 우분투 설치 후 putty에서 한글 안 깨지도록 설정하기 file esniper 2010-09-10 16983
150 Linux Tip 우분투 ssh or mysql 서버 접속지연이 있는 경우 해결책 esniper 2010-09-10 16348
149 Windows Research 커널레벨에서 IAT Hook lain 2011-06-11 16223
148 Linux Tip 우분투에 IRC서버 설치후 닉네임 길이와 동접자 조절. [1] 오랑캐꽃 2010-11-26 15896
147 Windows Research 유저 레벨에서 API Hook 1부 file [1] lain 2010-09-03 15626
146 Windows Research SetEvent 함수는 언제 실패할까? lain 2010-09-04 15529
145 Windows Research Sysinternals - Filemon source code file [5] lain 2010-09-04 15308
144 Windows Research Sysinternals - Regmon source code file [1] lain 2010-09-04 14877

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