[하루한줄] CVE-2021–40449: Windows 커널의 UAF 취약점

URL

Target

  • Microsoft Windows 10 build 14393
  • Microsoft Windows 10 build 17763

Explain

Windows의 win32kfull.sys 커널 함수에서 발생하는 UAF 취약점의 세부 정보가 공개되었습니다.

취약점은 GreResetDCInternal에 존재합니다.

BOOL GreResetDCInternal(HDC hdc,DEVMODEW *pdmw,BOOL 
								*pbBanding,DRIVER_INFO_2W *pDriverInfo2,PVOID ppUMdhpdev){
..
    HDC hdcNew;
    {
        // 매개변수 hdc로부터 DCOBJ dco 생성
        DCOBJ dco(hdc);

        if (!dco.bValid())
            SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
        else {
            // dco로부터 PDEVOBJ po 생성
            PDEVOBJ po(dco.hdev());
...
	          // new DC 생성 
						// 이때 유저 모드 콜백으로 ResetDC를 호출해 컨텍스트 파괴
            hdcNew = hdcOpenDCW(L"", pdmw, DCTYPE_DIRECT, po.hSpooler, 
																	prton, pDriverInfo2, ppUMdhpdev);
            if (hdcNew)
            {
                po->hSpooler = NULL;
                DCOBJ dcoNew(hdcNew);
                if (!dcoNew.bValid())
                    SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
                else {
                    // Transfer any remote fonts
                    dcoNew->pPFFList = dco->pPFFList;
                    dco->pPFFList = NULL;

                    // Transfer any color transform
                    dcoNew->pCXFList = dco->pCXFList;
                    dco->pCXFList = NULL;

                    PDEVOBJ poNew((HDEV)dcoNew.pdc->ppdev())

                    // 파괴된 기존 컨텍스트에 접근, UAF 트리거
                    PFN_DrvResetPDEV rfn = po->ppfn[INDEX_DrvResetPDEV];
                    if (rfn != NULL)
                        (*rfn)(po->dhpdev, poNew->dhpdev);
...
                }
            }
        }
    }
    // Destroy old DC
...
}

hdcOpenDCW 호출 과정에서 DrvEnablePDEV를 후킹해 ResetDC를 유저모드 콜백으로 호출할 수 있으며 이를 이용해 GreResetDCInternal에서 사용되는 디바이스 컨텍스트 객체를 해제할 수 있습니다. GreResetDCInternal 는 객체가 해제되었는지 확인하지 않고 접근을 시도하기 때문에 UAF가 트리거됩니다.

취약점을 악용하는 방법은 아래와 같습니다.

  1. KernelCallbackTable 에 유저모드 콜백 설정합니다.
  2. 전역 DC 객체를 만들고 핸들을 저장합니다.
  3. ResetDC 함수를 호출해 전역 DC의 핸들을 전달하고, ResetDC 함수는 내부적으로 GreResetDCInternal 을 호출합니다.
  4. GreResetDCInternalhdcOpenDCW 함수 호출직후 유저모드 콜백으로 인해 ResetDC 를 다시 호출합니다.
  5. 컨텍스트를 해제하고 GreResetDCInternal로 복귀하지만 해당 함수에서 해제된 컨텍스트인지 확인하지 않고 접근해 UAF가 트리거됩니다.