[CVE] CVE 분석 · 작성: 2026-07-19 19:39:08 · 수정: 2026-07-21 23:17:42 · 조회 20
srv.sys)MS17-010 패치는 srv.sys의 FEA 크기 변환 경로에 입력 크기 필드에 대한 명시적 상한/일관성 검증을 추가하는 방식으로 이뤄졌다. 공개된 분석 자료를 바탕으로 재구성한 핵심 로직은 다음과 같다.
SrvOs2FeaListSizeToNt() — 변환 크기 계산의 정수 처리 오류Before
// OS/2 FEA 리스트를 순회하며 NT 포맷 기준 필요한 총 크기를 누적 계산
ULONG SrvOs2FeaListSizeToNt(FEALIST *os2FeaList) {
ULONG ntSize = 0;
PFEA fea = os2FeaList->list;
while (/* 리스트 순회 조건 */) {
// NameLength, ValueLength는 클라이언트가 보낸 필드
ntSize += sizeof(FEA) + fea->NameLength + fea->ValueLength + 1;
fea = NEXT(fea);
}
return ntSize; // 이 값을 기준으로 이후 버퍼가 할당됨
}
NameLength/ValueLength는 네트워크로 전달된 Trans2 요청의 필드값이라 클라이언트가 임의로 조작할 수 있다. 특정 조합(오버플로우를 유발하는 큰 값들의 합)을 넣으면 ntSize 계산 자체가 실제 데이터 크기보다 작은 값으로 wrap — 정수 오버플로우가 일어난다.
Before
buffer = ExAllocatePoolWithTag(NonPagedPool, ntSize, TAG); // 과소 계산된 ntSize로 할당
Os2FeaListToNt(os2FeaList, buffer); // 원본 FEA 데이터를 buffer에 복사 — 실제 크기 기준으로 씀
할당은 (오버플로우로 왜곡된) ntSize 기준, 복사는 원본 데이터의 실제 길이 기준으로 이뤄지며 할당된 커널 풀 청크 경계를 넘어 인접 풀 메모리를 덮어쓴다.
After (MS17-010)
ULONG SrvOs2FeaListSizeToNt(FEALIST *os2FeaList) {
ULONGLONG ntSize64 = 0; // 64비트로 누적해 오버플로우 여부를 별도 확인
...
ntSize64 += (ULONGLONG)fea->NameLength + fea->ValueLength + sizeof(FEA) + 1;
if (ntSize64 > MAXULONG || ntSize64 > MAX_ALLOWED_FEA_SIZE) {
return STATUS_INVALID_PARAMETER; // 명시적으로 거부
}
...
}
계산을 더 넓은 정수 폭(64비트)으로 수행해 wrap 여부를 사전에 감지하고, 상한값을 넘으면 요청 자체를 거부하도록 검증이 추가됐다.
NameLength/ValueLength 조합을 담은 Trans2 FEA 리스트 요청 전송ntSize로 과소 할당된 버퍼를 준비, 이어지는 변환 루틴이 실제 데이터 크기만큼 복사하며 인접 커널 풀 오버플로우 발생