ETC

Kernel Memory Read/Write Primitive using NalDrv.sys

wsoh9812 2022. 5. 17. 10:29

CVE-2015-2291(NalDrv.sys)

 


취약한 드라이버

  • NalDrv.sys

분석환경

  • Windows10 1909 x64 (빌드 18363.418)

분석

 

 

개요

 

이 취약점은 드라이버에 사용자가 커널 모드 메모리의 임의 주소에 임의의 데이터를 Read/Write 할 수 있도록 하는 IOCTL 코드가 존재한다는 것이다.

 

 

상세분석

https://github.com/hfiref0x/KDU

 

GitHub - hfiref0x/KDU: Kernel Driver Utility

Kernel Driver Utility. Contribute to hfiref0x/KDU development by creating an account on GitHub.

github.com

코드를 바탕으로 분석을 진행하였다.

 

 

`IRP_MJ_DEVICE_CONTROL` IRP가 발생했을때 실행되는 함수를 보면 위 사진과 같다.

 

이때 사용자가 보낸 `ControlCode`를 통해 코드흐름이 제어되게 되는데, `ControlCode`가 0x80862007일때 취약한 함수로 진입하게 된다.

 

 

즉, `ControlCode`를 0x80862007으로 두고 함수를 호출하게되면 취약한 함수로 진입할 수 있다.

 

sub_113c0() 함수

취약한 `sub_113c0()`함수로 진입해 보면 또 다시 switch case문을 볼 수 있다.

 

여기서 `FunctionId`로 다양한 기능들을 수앵하게 되는데 우리가 눈여겨 보아야할 곳은 4곳이다.

 

 

이 4가지 FunctionId로 Read/Write Primitive가 이루어 질 것이다.

 

 

먼저, `FunctionId`에 매칭되는 내부 코드를 하나씩 살펴보자.

 

1.

 

`FunctionId = 0x19`일때 `MmMapIoSpace()`함수를 사용해서 물리메모리를 가상메모리로 매핑시켜준다.

 

2.

`FunctionId = 0x20MmMapIoSpace에서 매핑한 지정된 물리적 주소 범위의 매핑을 해제한다.

 

 

3.

`FunctionId = 0x25` 일때 `MmGetPhysicalAddress()` 함수를 통해 가상메모리를 물리메모리로 바꿀 수 있다.

 

 

4.

`FunctionId = 0x33`일때 `memmov()`를 통해서 특정 메모리 영역에 값을 Read/Write할 수 있다.

 

 

 

그림으로 1~4번의 흐름을 살펴보자.

(*우리는 DSE 변수의 값을 Read/Write하는 것이 목적이다.*)

 

 

위 그림을 함수의 인자는 일부 생략하여 작성하였고, 1~4번 순서로 Read Primitive가 이루어 진다.

 

 

 

위 1-3번 과정을 메모리 주소로 보면 다음과 같다.

Windbg 메모리 확인

이렇게 커널 영역의 가상메모리 주소에 복사가된 데이터를 유저 영역에 복사를 해야한다.

 

 

`FunctionId = 0x33`일때 내부적으로 `memmove()`을 통해서 유저 영역으로 데이터를 복사해 올 수 있다.

 

 

이후 mapping된 공간은 unmapping해준다.

 

[참고] 메모리로 표한한 흐름

 

 

 

참고

https://github.com/hfiref0x/KDU

 

GitHub - hfiref0x/KDU: Kernel Driver Utility

Kernel Driver Utility. Contribute to hfiref0x/KDU development by creating an account on GitHub.

github.com