windows driver AddDevice

wangki·2026년 3월 27일

windows driver

목록 보기
3/10

장치를 추가할 때 DeviceStack에 참여하는 콜백함수를 등록하고 windbg로 디버깅을 했다.


DriverEntry


NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
{
	pRegPath = pRegPath;

    pDrvObj->MajorFunction[IRP_MJ_PNP] 
        = SampleDriverPnPDispatch;  

    pDrvObj->DriverExtension->AddDevice = SampleDriverAddDevice; 
    pDrvObj->DriverUnload = SampleDriverUnload;

	return STATUS_SUCCESS;
}

AddDevice Callback 함수


NTSTATUS SampleDriverAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pPhysicalDeviceObject)
{
    PDEVICE_OBJECT pDeviceObject = NULL;
    PDEVICE_EXTENSION pDeviceExtension = NULL;
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

    // DeviceObject 생성
    ntStatus = IoCreateDevice(
        pDrvObj,
        sizeof(DEVICE_EXTENSION),
        NULL,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDeviceObject
    );
    if (!NT_SUCCESS(ntStatus))
    {
        goto exit;
    }

    pDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;

    pDeviceExtension->pNextLayerDeviceObject = 
        IoAttachDeviceToDeviceStack(pDeviceObject, pPhysicalDeviceObject);

    pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    ntStatus = STATUS_SUCCESS;

exit:
    return ntStatus;
}

windbg 디버깅


장치 관리자의 시스템 장치에 등록한 SampleDevice를 사용하기로 누르면 windbg에 설정한 break point를 히트하게 된다.

DrvierEntry 함수에 브레이크 포인트를 걸었다.
bp pnpsample!DriverEntry

SampleDriverAddDevice함수를 탔다. 로컬 변수인 pDeviceObject가 무엇을 가르키는지 windbg에서 확인하려면 dv 명령어를 입력하면 된다.


현재는 NULL을가르키는 것을 확인할 수 있다.

 ntStatus = IoCreateDevice(
        pDrvObj,
        sizeof(DEVICE_EXTENSION),
        NULL,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDeviceObject
    );
    if (!NT_SUCCESS(ntStatus))
    {
        goto exit;
    }

IoCreateDevice를 호출하여 pDeviceObject에 값을 넣어준 뒤, 다시 dv 명령어로 확인하면 주소값이 들어간 것을 확인할 수 있다.

다음은 DEVICE_EXTENSION의 주소값을 가져와서 PDEVICE_OBJECT pNextLayerDeviceObject 의 값을 채워준다.

    pDeviceExtension->pNextLayerDeviceObject = 
        IoAttachDeviceToDeviceStack(pDeviceObject, pPhysicalDeviceObject);

IoAttachDeviceToDeviceStack의 반환 값은 현재 추가한 디바이스 오브젝트 이전 최상위 디바이스 오브젝트를 반환해준다.

그전에 PDO의 구조체를 확인하기 위해서 dt _DEVICE_OBJECT 0xffffb78f20289860 명령어를 입력해주면 PDO에 대한 필드들이 나온다.

PDO가 root stack으로 쌓이기 때문에 만약에 PDOAttachedDevice 필드가 NULL이라면 현재 추가하려는 DeviceObjectPDO위에 올라가게 될 것이다.

windbg로 확인결과 null인 것을 확인할 수 있다.

IoAttachDeviceToDeviceStack 호출 후 필드 확인 결과 생성한 pDeviceObject인 것을 확인할 수 있다. 또한 반환된 pDeviceExtension->pNextLayerDeviceObject 이 값을 확인하면 PDO의 주소와 같은 것을 확인할 수 있다.

    pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

플래그 값을 위와 같이 설정해주는 이유는 생성한 디바이스위에도 올라갈 수 있도록 하는 것이라고 한다. FLAGS 필드를 확인하면 아래와 같이 0으로 변하는것을 확인할 수 있다.

결론


간단한 pnp 드라이버를 만들고 하드웨어 스택이 어떻게 생성되는지 windbg를 통해 실제 동작을 확인하였다. 좀 어렵고 생소하지만 계속해봐야겠다.

0개의 댓글