본문 바로가기

reversing/Windows Driver

IRP, I/O Stack 관련 내용 정리 [3]

SMALL
[코드 출처] : https://www.youtube.com/watch?v=6gIbmod6Dpo&t=3807s

코드 설명 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <wdm.h>
#pragma once
#include "FIRST_WDM.H"
 
// 1. FIRST_WDM 드라이버가 메모리에서 내려올때 호출됩니다
void MyDriverUnload(
    IN PDRIVER_OBJECT     DriverObject
    )
{
    UNREFERENCED_PARAMETER(DriverObject);
 
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0"FIRST_WDM Driver Unloading...\n");
}
 
// 2. 디바이스 스택이 형성될때 호출되는 함수입니다
NTSTATUS MyAddDevice(
    IN PDRIVER_OBJECT     DriverObject,
    IN PDEVICE_OBJECT    PhysicalDeviceObject
    )
{
 
    /*
     * DeviceExtensionSize  드라이버가 개인적으로 사용할 공간의 크기
     * 드라이버가 디바이스 오브젝트에서 개인적으로 사용할 공간의 크기 할당
     */
    PMYDEVICE_EXTENSION    pMyDeviceExtension = NULL;
 
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
 
    PDEVICE_OBJECT MyDeviceObject;
 
    DbgPrint("Add Device\n");
 
    /*
     * 디바이스 오브젝트를 생성
     * 단지 생성만 할 뿐, 디바이스 스택과 연관은 없는 상태
     */
    ntStatus = IoCreateDevice
        (
        DriverObject,                /* 해당 디바이스 오브젝트를 생성하는 드라이버 오브젝트 */
        sizeof(MYDEVICE_EXTENSION), /* 디바이스 오브젝트에 드라이버가 개인적으로 사용할 공간*/
        NULL,
        FILE_DEVICE_UNKNOWN,
        FILE_AUTOGENERATED_DEVICE_NAME,
        FALSE,
        &MyDeviceObject              /*_Out_ 인자로 생성된 디바이스 오브젝트의 포인터를 가지는 값*/
        );
 
 
 
    if (!NT_SUCCESS(ntStatus)){
        DbgPrint("Create Device Object Error %08x\n", ntStatus);
        return ntStatus;
    }
 
 
 
 
    /*
     * 생성된 디바이스 오브젝트의 DeviceExtenstion[드라이버의 개인 저장공간]의 값을 가져옴
       */
 
    pMyDeviceExtension = MyDeviceObject->DeviceExtension;
    //초기화
    RtlZeroMemory(pMyDeviceExtension, sizeof(MYDEVICE_EXTENSION));
 
    /*
     *    DEVICE_OBJECT를 디바이스 스택에 추가
     */
    pMyDeviceExtension->NextDeviceObject =
        IoAttachDeviceToDeviceStack(
        MyDeviceObject,            // SRC 추가 시킬 디바이스 오브젝트
        PhysicalDeviceObject    // 추가 시킬 다바이스 오브젝트의 밑에 주소
        // PhysicalDeviceObject는 드라이버 오브젝트가 생성한 디바이스 오브젝트
        );
    /*          Device STACK
     *
     *      [1] MyDeviceObject
     *      [0] PhysicalDeviceObject
     */
 
    /*
     * DEVICE_OBJECT의 초기화가 끝났다는것을 알림
     */ 
    MyDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
exit:
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0"FIRST_WDM MyAddDevice --, %8X\n", ntStatus);
    return ntStatus;
}
 
// 3. FIRST_WDM 드라이버가 플러그엔플레이 명령을 처리합니다
NTSTATUS MyPnPIRPDispatch(
    IN PDEVICE_OBJECT     MyDevObj,
    IN PIRP                Irp
    )
{
    NTSTATUS ntStatus = STATUS_NOT_SUPPORTED;
 
    PMYDEVICE_EXTENSION pDeviceExtension;
 
    PDEVICE_OBJECT pNextDevObj;
 
    /*현재의 Stack 위치값을 가져옴*/
    PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp); 
 
    /*해당 드라이버에서 디바이스 오브젝트에서 사용할 자료공간*/
    pDeviceExtension = (PMYDEVICE_EXTENSION)MyDevObj->DeviceExtension;
 
 
    pNextDevObj = pDeviceExtension->NextDeviceObject;
 
    /*             Device  STACK
     *      [2] NextDeviceObject
     *      [1] MyDeviceObject
     *      [0] PhysicalDeviceObject
     */
 
    /*PnP의 세부 내용 처리*/
 
    switch (pStack->MinorFunction) {
    case IRP_MN_REMOVE_DEVICE: // 디바이스 스택 제거 명령입니다
        IoDetachDevice(pNextDevObj); // 디바이스 스택으로부터 MyDevObj를 분리합니다
        IoDeleteDevice(MyDevObj); // MyDevObj를 제거합니다
 
        /*           Device STACK
        *      [1] NextDeviceObject
        *      --------------------------[1] MyDeviceObject  // 삭제
        *      [0] PhysicalDeviceObject
        */
        break;
    default:
        break;
    }
 
    /*IRP의 이전 스택 주소를 현재 스택 주소로 지정*/
    IoSkipCurrentIrpStackLocation(Irp);
 
    /*
     * 인자 디바이스 오브젝트를 생성한 드라이버에게 현재 IRP를 넘겨줌
     * 현재 드라이버가 IRP의 소유권을 포기하고 인자의 디바이스 오브젝트를 생성한
     * 드라이버에게 소유권을 넘겨줌
     */
 
    ntStatus = IoCallDriver(pNextDevObj, Irp);
 
    return ntStatus;
}
 
// 4. FIRST_WDM 드라이버가 메모리에 상주합니다
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT     DriverObject,
    IN PUNICODE_STRING    RegistryPath
    )
{
    UNREFERENCED_PARAMETER(RegistryPath);
 
    DbgPrint("WDM Test\n");
 
 
    /*Unload Routine*/
    DriverObject->DriverUnload = MyDriverUnload;
    
 
    /*
     * 드라이버가 디바이스 스택에 디바이스 오브젝트를 생성하는데 사용하는 함수를 설정
     * 디바이스 오브젝트를 어떠한 수행을 거쳐서 만들지 정의하는 함수
     * AddDevice역할을 MyAddDevice함수가 수행
     */
    
    DriverObject->DriverExtension->AddDevice = MyAddDevice;
    // 디바이스 스택이 형성될때 호출되는 콜백함수를 등록합니다
 
    /*PnP가 발생했을 때 처리할 콜백 함수*/
    DriverObject->MajorFunction[IRP_MJ_PNP] = MyPnPIRPDispatch;
    
    return STATUS_SUCCESS;
}
cs


LIST

'reversing > Windows Driver' 카테고리의 다른 글

MDL(Memory Descriptor List)[1]  (1) 2017.08.08
WinDBG 명령어 [CallStack]  (0) 2017.08.08
IRP, I/O Stack 관련 내용 정리 [2]  (0) 2017.08.04
Security Descriptors  (0) 2017.08.04
Minifilter - User Mode Communication  (0) 2017.08.04