WindowsDriver

WindowsDriver Develop Basic2 [정리중]

wsoh9812 2020. 9. 23. 21:23

#inlcude <ntddk.h> // nt legacy style 디바이스 스택을 사용하지 않음

#include <wdm.h> // wdm style 디바이스 스택을 사용하는 경우



 windbg 명령어 
 원하는 문맥으로 전환 
( eip컨트롤이라고 생각)
명령 순서  : .process 주소 -> .thread 주소

.process [프로세스 주소] = 전환하려는 프로세스의 주소값을 사용

.thread [쓰레드 주소] = 전환하려는 쓰레드의 주소값 


1. 프로세스가 실행될때, 종료될때는 어떻게 알 수 있을까???
새로운 프로세스가 실행되거나 종료될때마다 운영체제가 커널 드라이버의 루틴을 호출해줍니다.
즉 , PsSetCcreateProcessNotifyRoutine을 호출해준다.

2. 드라이버 또는 동적라이브러리가 메모리에 상주하는 시기를 드라이버는 어떻게 알 수 있을까??
드라이버 또는 동적라이브러리가 메모리에 상주할때마다 운영체제가 커널 드라이버의 루틴을 호출해준다.
즉 , PsSetLoadImageNotifyRoutine을 호출해준다.


wdm style vs nt legacy 스타일 
wdm :  디바이스 스택 기반으로 동작하는 드라이버

nt legacy : 커널 레벨에서 동작하는 코드를 개발자가 가지는 목적을 가진 드라이버

DRIVER_OBJECT vs DEVICE_OBJECT
DRIVER_OBJECT <-드라이버를 상징하는 자료구조
DEVICE_OBJECT <- 드라이버가 관여하는 디바이스를 상징하는 자료구조


 

 

 

연결된 화살표 방향 중요

 

 

 

디바이스 스택 형성과정

 

 

 

내가 만든 DeviceObject를 기존의 DeviceObject위에 attach하겠다. 

return 값으로 바로 아래의 device object 주소를 반환한다.

 

 

 

[중요] DeviceExtension->NextDeviceObject IoAttachDeviceToDeviceStack의 return 값을 담는데 사용한다.

[참고]  PhysicalDeviceObject버스(bus)드라이버가 만든 디바이스 오브젝트이다.

 

flag를 다음과 같이 설정해 주지 않으면 

시스템이 볼때 우리가 만든 디바이스 오브젝트가 초기화가 진행중이라고 생각하고,

리 디바이스 오브젝트 위로는 스택이 형성되지 않는다.

( 우리가 만든 디바이스 오브젝트가 탑이 된다. -> 잘 응용하면 악성코드?)

 

 

 

IRP의 핵심 필드

- StackSize는 IO Stack의 최대 크기

- CurrentLocation은 현재의 위치 인덱스 : 3

- CurrentStackLocation은 현재 위치메모리 주소

 

 

 

 

 

IoSetCompletionRoutine()

      해당 함수는 현재 스택 위치가 4번이면 그 위에 존재하는 3번 위치에 CompletionRoutine을 등록

     IoCompleteRequest() 함수가 호출되면 3번 위치까지 스택의 값이 제거(pop)됨

     CompletionRoutine을 설정했다는 것은 IRP 를 전달하고 그 결과가 나올때 처리 함



 

 

[중요]

IoSkipCurrentIrpStackLocation()을 호출함으로서

IRP_MJ_XXX의 내용을 지우는 것이 아니라 '팝'한다고 생각.

즉, '주소와 인덱스 위치를 아래로 옮겨준다' 라고 생각하면된다.

그리고

현재 내가 사용하고 있는 스택의 위치를

IoCallDriver했을때 받은 드라이버가 해당 위치를 사용할 수 있게 해준다. 

음,,, 내 스택위치를 포기한다? 다른 드라이버에게 양보한다? 라고 생각면될 것같다.

다음 드라이버가 그 스택을 사용할 수 있게 해준다.

 

 

IoCompleteRequest()를 호출하면 IRP 처리를 완료하겠다. 원 호출자에게 돌아가겠다 라는 뜻인데.

이전에  IO StackLocation에서 CompletionRountine을 설정해놓은 것을 기억하는가

CompletionRoutine이 설정 된 위치 바로 밑 

그림으로 보면 2번에서 4번까지 팝이 된다.

 

 

 

만약 해당 드라이버가 IRP를 종료하지 않겠다! 하면 무조건 IoCallDriver()을 호출해 

다른 드라이버로 irp를 넘겨서 그 드라이버가 irp 처리를 완료하게 만들어야한다.

 

 

 

 

IoCallDriver()은 IRP를 다른 드라이버에게 전달한다는 함수인데.

전달과 동시에 IRP 처리를 맡긴다. 라고 생각.

 

 

 

 

 

 

 

 

 

출처 : www.youtube.com/watch?v=1E5Y64CPH00&list=PLbXk0UYjHOuG_-h2sEkOTXGAGVtOGXBN5&index=4