우리가 유저모드 App에서 CreateFile함수를 호출했다 치자.
그러면, 얘는 현재 UNICODE가 정의 되어있는지 확인한 다음에 CreateFileW를 호출하던지,
CreateFileA를 호출한 다음에 CreateFileA에서 CreateFileW를 호출하는 진행(어차피 CreateFileW호출)을
하게된다.
그러면, 얘는 몇가지 일을 한 다음에 ZwCreateFile을 호출하게 된다.
ZwCreateFile중에서 몇개 신경써야 할 인자는, PHANDLE과 POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK
정도가 될거 같다.
PIO_STATUS_BLOCK는 결과값을 의미하고, PHANDLE은 커널 객체의 핸들, POBJECT_ATTRIBUTES는 내가
잘 모르는 그 무엇(!.?)이다.
ZwCreateFile은 NtCreateFile을 호출하고(걍 Alias일뿐..), 그 다음으로 I/O Manager가 IRP를 만들어 낸다.
그리고 아마도 IoCallDriver()를 호출해서, IRP를 해당 디바이스 스택에 전송할 것이고.
디바이스 스택의 디바이스 객체에 해당하는 드라이버의 디스패치 루틴에서 처리를 해 주겠지.
IRP와 IO_STACK_LOCATION구조체 선언부를 보면, 우리가 CreateFile과 ZwCreateFile에 주었던 인자들이
포함되어 있다는것을 어렵지 않게 알수 있을것이다. (하지만, 실제 값을 비교해 보지는 못해서 장담할수는 없다.)
즉
CreateFile->ZwCreateFile->I/O Manager-IRP/IO_STACK_LOCATION생성->DriverDispatchRoutine
이 될것 같다.
CreateFileW(
__in LPCWSTR lpFileName, //파일명
__in DWORD dwDesiredAccess, //객체에 접근하기 위한 권한 (읽기, 쓰기, 둘다)
__in DWORD dwShareMode, //0으로 설정하면 공유 안됨.
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, //보안 서술자의 포인터. NULL이면 상속 안됨.
__in DWORD dwCreationDisposition, //파일 생성시 처리(항상 새로 생성, 등)
__in DWORD dwFlagsAndAttributes, //파일 속성과 플래그들
__in_opt HANDLE hTemplateFile
);
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; //sizeof
LPVOID lpSecurityDescriptor; //NULL이면, 기본 보안 지정자.
BOOL bInheritHandle; //상속 여부
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
ZwCreateFile(
__out PHANDLE FileHandle, //파일을 가리키는 핸들 CreateFile의 리턴값
__in ACCESS_MASK DesiredAccess, //객체에 접근하기 위한 권한
__in POBJECT_ATTRIBUTES ObjectAttributes, //
__out PIO_STATUS_BLOCK IoStatusBlock, //요청 처리된 결과값
__in_opt PLARGE_INTEGER AllocationSize, //초기 할당 크기를 포함하고 있는 라지 인티저의 포인터
__in ULONG FileAttributes, //dwFlagsAndAttributes
__in ULONG ShareAccess, //dwShareMode
__in ULONG CreateDisposition, //
__in ULONG CreateOptions,
__in_bcount_opt(EaLength) PVOID EaBuffer,
__in ULONG EaLength
);
typedef DWORD ACCESS_MASK;
typedef ACCESS_MASK* PACCESS_MASK;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
//FILE_CREATED, FILE_OPENED, FILE_OVERWRITTEN, FILE_SURPERSEDED, FILE_EXISTS, FILE_DOES_NOT_EXIST중 하나.
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#define FILE_SUPERSEDED 0x00000000
#define FILE_OPENED 0x00000001
#define FILE_CREATED 0x00000002
#define FILE_OVERWRITTEN 0x00000003
#define FILE_EXISTS 0x00000004
#define FILE_DOES_NOT_EXIST 0x00000005
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length; //sizeof
HANDLE RootDirectory;
PUNICODE_STRING ObjectName; //열 핸들의 유니크 객체 이름
ULONG Attributes; //속성
PVOID SecurityDescriptor; //보안 서술자의 포인터
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
※InitializeObjectAttributes() 매크로를 통해 초기화 할수 있다.
VOID InitializeObjectAttributes(
OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN HANDLE RootDirectory,
IN PSECURITY_DESCRIPTOR SecurityDescriptor);
typedef struct _IRP {
. .
PMDL MdlAddress;
ULONG Flags;
union {
struct _IRP *MasterIrp;
. .
PVOID SystemBuffer;
} AssociatedIrp;
. .
IO_STATUS_BLOCK IoStatus;
KPROCESSOR_MODE RequestorMode;
BOOLEAN PendingReturned;
. .
BOOLEAN Cancel;
KIRQL CancelIrql;
. .
PDRIVER_CANCEL CancelRoutine;
PVOID UserBuffer;
union {
struct {
. .
union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct { PVOID DriverContext[4]; };
};
. .
PETHREAD Thread;
. .
LIST_ENTRY ListEntry;
. .
} Overlay;
. .
} Tail;
} IRP, *PIRP;
typedef struct _IO_STACK_LOCATION {
UCHAR MajorFunction;
UCHAR MinorFunction;
UCHAR Flags;
UCHAR Control;
union {
//
// Parameters for IRP_MJ_CREATE
//
struct {
PIO_SECURITY_CONTEXT SecurityContext;
ULONG Options;
USHORT POINTER_ALIGNMENT FileAttributes;
USHORT ShareAccess;
ULONG POINTER_ALIGNMENT EaLength;
} Create;
} Parameters;
. .
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
. .
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;
그러면, 얘는 현재 UNICODE가 정의 되어있는지 확인한 다음에 CreateFileW를 호출하던지,
CreateFileA를 호출한 다음에 CreateFileA에서 CreateFileW를 호출하는 진행(어차피 CreateFileW호출)을
하게된다.
그러면, 얘는 몇가지 일을 한 다음에 ZwCreateFile을 호출하게 된다.
ZwCreateFile중에서 몇개 신경써야 할 인자는, PHANDLE과 POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK
정도가 될거 같다.
PIO_STATUS_BLOCK는 결과값을 의미하고, PHANDLE은 커널 객체의 핸들, POBJECT_ATTRIBUTES는 내가
잘 모르는 그 무엇(!.?)이다.
ZwCreateFile은 NtCreateFile을 호출하고(걍 Alias일뿐..), 그 다음으로 I/O Manager가 IRP를 만들어 낸다.
그리고 아마도 IoCallDriver()를 호출해서, IRP를 해당 디바이스 스택에 전송할 것이고.
디바이스 스택의 디바이스 객체에 해당하는 드라이버의 디스패치 루틴에서 처리를 해 주겠지.
IRP와 IO_STACK_LOCATION구조체 선언부를 보면, 우리가 CreateFile과 ZwCreateFile에 주었던 인자들이
포함되어 있다는것을 어렵지 않게 알수 있을것이다. (하지만, 실제 값을 비교해 보지는 못해서 장담할수는 없다.)
즉
CreateFile->ZwCreateFile->I/O Manager-IRP/IO_STACK_LOCATION생성->DriverDispatchRoutine
이 될것 같다.
CreateFileW(
__in LPCWSTR lpFileName, //파일명
__in DWORD dwDesiredAccess, //객체에 접근하기 위한 권한 (읽기, 쓰기, 둘다)
__in DWORD dwShareMode, //0으로 설정하면 공유 안됨.
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, //보안 서술자의 포인터. NULL이면 상속 안됨.
__in DWORD dwCreationDisposition, //파일 생성시 처리(항상 새로 생성, 등)
__in DWORD dwFlagsAndAttributes, //파일 속성과 플래그들
__in_opt HANDLE hTemplateFile
);
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; //sizeof
LPVOID lpSecurityDescriptor; //NULL이면, 기본 보안 지정자.
BOOL bInheritHandle; //상속 여부
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
ZwCreateFile(
__out PHANDLE FileHandle, //파일을 가리키는 핸들 CreateFile의 리턴값
__in ACCESS_MASK DesiredAccess, //객체에 접근하기 위한 권한
__in POBJECT_ATTRIBUTES ObjectAttributes, //
__out PIO_STATUS_BLOCK IoStatusBlock, //요청 처리된 결과값
__in_opt PLARGE_INTEGER AllocationSize, //초기 할당 크기를 포함하고 있는 라지 인티저의 포인터
__in ULONG FileAttributes, //dwFlagsAndAttributes
__in ULONG ShareAccess, //dwShareMode
__in ULONG CreateDisposition, //
__in ULONG CreateOptions,
__in_bcount_opt(EaLength) PVOID EaBuffer,
__in ULONG EaLength
);
typedef DWORD ACCESS_MASK;
typedef ACCESS_MASK* PACCESS_MASK;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
//FILE_CREATED, FILE_OPENED, FILE_OVERWRITTEN, FILE_SURPERSEDED, FILE_EXISTS, FILE_DOES_NOT_EXIST중 하나.
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#define FILE_SUPERSEDED 0x00000000
#define FILE_OPENED 0x00000001
#define FILE_CREATED 0x00000002
#define FILE_OVERWRITTEN 0x00000003
#define FILE_EXISTS 0x00000004
#define FILE_DOES_NOT_EXIST 0x00000005
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length; //sizeof
HANDLE RootDirectory;
PUNICODE_STRING ObjectName; //열 핸들의 유니크 객체 이름
ULONG Attributes; //속성
PVOID SecurityDescriptor; //보안 서술자의 포인터
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
※InitializeObjectAttributes() 매크로를 통해 초기화 할수 있다.
VOID InitializeObjectAttributes(
OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN HANDLE RootDirectory,
IN PSECURITY_DESCRIPTOR SecurityDescriptor);
typedef struct _IRP {
. .
PMDL MdlAddress;
ULONG Flags;
union {
struct _IRP *MasterIrp;
. .
PVOID SystemBuffer;
} AssociatedIrp;
. .
IO_STATUS_BLOCK IoStatus;
KPROCESSOR_MODE RequestorMode;
BOOLEAN PendingReturned;
. .
BOOLEAN Cancel;
KIRQL CancelIrql;
. .
PDRIVER_CANCEL CancelRoutine;
PVOID UserBuffer;
union {
struct {
. .
union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct { PVOID DriverContext[4]; };
};
. .
PETHREAD Thread;
. .
LIST_ENTRY ListEntry;
. .
} Overlay;
. .
} Tail;
} IRP, *PIRP;
typedef struct _IO_STACK_LOCATION {
UCHAR MajorFunction;
UCHAR MinorFunction;
UCHAR Flags;
UCHAR Control;
union {
//
// Parameters for IRP_MJ_CREATE
//
struct {
PIO_SECURITY_CONTEXT SecurityContext;
ULONG Options;
USHORT POINTER_ALIGNMENT FileAttributes;
USHORT ShareAccess;
ULONG POINTER_ALIGNMENT EaLength;
} Create;
} Parameters;
. .
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
. .
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;
덧글