[하루한줄] Windows: Out-of-bounds write in WindowsCodecsRaw!COlympusE300LoadRaw
URL
Issue 2137: Windows: Out-of-bounds write in WindowsCodecsRaw!COlympusE300LoadRaw
Target
Windows 10 20H1
Explain
Windows에서는 Olympus E300의 raw 이미지 파일을 처리할 때, Windows Imaging Component (WIC)
를 통해 처리합니다. 이 때 WindowsCodecsRaw.dll
의 COlympusE300LoadRaw::olympus_e300_load_raw()
함수가 실행됩니다. 취약점이 발생한 함수의 코드는 다음과 같습니다.
void CLASS olympus_e300_load_raw()
{
uchar *data, *dp;
ushort *pixel, *pix;
int dwide, row, col;
dwide = raw_width * 16 / 10; // (1)
data = malloc (dwide + raw_width*2);
merror (data, "olympus_e300_load_raw()");
pixel = (ushort *) (data + dwide);
for (row=0; row < height; row++) {
fread (data, 1, dwide, ifp);
for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { // (2)
if (((dp-data) & 15) == 15) dp++;
pix[0] = dp[1] << 8 | dp[0]; // (3)
pix[1] = dp[2] << 4 | dp[1] >> 4; // (4)
}
for (col=0; col < width; col++)
BAYER(row,col) = (pixel[col] & 0xfff);
}
free (data);
}
먼저 (1)에서 디코딩된 데이터를 저장할 메모리를 할당합니다. 디코딩은 열 단위로 디코딩을 진행하는데, 한 열에는 height
만큼의 픽셀이 존재하며 픽셀은 각각 2 bytes의 데이터로 디코딩 됩니다. 그리고 (2)에서부터 실질적인 디코딩 작업이 진행됩니다. 조건문을 pix < pixel+raw_width
로 설정함으로써 디코딩 과정에서 OOB가 발생하지 않도록 신경썼지만 raw_width
가 0xd79
같이 홀수일 경우, 한 픽셀 당 2 bytes 씩 디코드하기 때문에 해당 loop의 마지막에서 (3)에서는 버퍼의 마지막에 데이터를 쓰지만 (4)에서 버퍼 밖의 메모리 영역에 데이터를 쓰게 되어 1 byte 의 OOB Write가 발생하게 됩니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.