[0x00] Concept
I/O Control Code(IOCTLs) 는 유저모드 애플리케이션과 드라이버 간의 통신 또는 드라이버 스택 내 드라이버 간의 내부 통신에 사용됩니다. I/O Control Code 는 IRP
를 이용하여 전송됩니다.
유저모드 애플리케이션은 DeviceIoControl
이라는 함수를 호출하여 IOCTL
을 드라이버로 전송합니다. I/O Manager 가 IRP
의 스택 로케이션에 IRP_MJ_DEVICE_CONTROL
요청을 만들고 디바이스 스택 내 최상단 드라이버로 전송하게 됩니다.
위의 설명은 MSDN
에 설명되어 있습니다. 또한 해당 내용에서 사용되는 드라이버 스택, 디바이스 스택, 스택 로케이션 등은 해당 블로그 내 IRP
챕터에서 확인할 수 있습니다.
[0x01] I/O Control Code
I/O Control Code는 32비트로 아래와 같은 레이아웃을 지니고 있습니다.
wdm.h
, ntddk.h
에 정의 된 CTL_CODE
매크로로 새로운 IOCTL 코드를 정의할 수 있습니다.
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
IOCTL_Device_Function
은 이름에 대한 규칙으로 IOCTL_Audio_VolumeControl
같은 식으로 표현할 수 있습니다.
- DeviceType
- 해당 값은 드라이버의 디바이스 오브젝트의
DeviceType
의 값과 일치해야 합니다.(0x8000 보다 높은 값을 사용해야 하며 이보다 작은 값은 MS에서 예약 된 값으로 사용됩니다.
- 해당 값은 드라이버의 디바이스 오브젝트의
- FunctionCode(Function)
- 수행 할 기능에 대한 식별 값입니다. 0x800 미만은 MS의 예약 값이며 0x800 이상의 값을 사용해야 합니다.
- TransferType(Method)
- 드라이버 호출자와 드라이버 간의 데이터를 전달하는 방법에 대한 식별 값입니다.
- METHOD_BUFFERED : 시스템 버퍼를 이용
- METHOD_IN_DIRECT, OUT_DIRECT :
MDL
을 이용 - METHOD_NEITHER : 유저모드 버퍼의 VA 를 전달
- 드라이버 호출자와 드라이버 간의 데이터를 전달하는 방법에 대한 식별 값입니다.
- Access(RequiredAccess)
- I/O Manager는 IRP를 만들고 호출자가 지정된 권한을 요청한 경우에만 해당하는 IOCTL 코드로 드라이버를 호출합니다.
- FILE_ANY_ACCESS, READ_DATA, WRITE_DATA
- I/O Manager는 IRP를 만들고 호출자가 지정된 권한을 요청한 경우에만 해당하는 IOCTL 코드로 드라이버를 호출합니다.