目录
MS10-015
摘要
我们这里分析的是 Windows 内核异常处理程序漏洞 - CVE-2010-0232
网上常说的MS10-015是Windows 内核双重释放漏洞 - CVE-2010-0233,很少有人分析这个0232,实际上微软是把这两个漏洞共同定义为MS10-015。
官方说明里面写着:
- windows 7 32位才有这个CVE-2010-0232漏洞,并且windows 7 32位没有CVE-2010-0233这个漏洞
- windows7 64位不受这两个漏洞影响
补丁分析
我们这里以windows 7的x86的补丁分析,补丁解开之后的目录列表如下:
重点查看补丁文件为:
- \x86\a…ence-infrastructure_6.1.7600.16481
- apphelp.dll
- \x86\kernel32_6.1.7600.16481
- kernel32.dll
apphelp.dll
主要包括三个更新函数:
- ApphelpCheckModule
- InternalCheckRunApp
- SdbIsValidQueryResultLight
ApphelpCheckModule
更新前
int __stdcall ApphelpCheckModule(const WCHAR *a1, int a2, int a3, int a4, int a5, char a6)
{
int v6; // eax
char v8; // [esp+0h] [ebp-1F8h]
char v9; // [esp+4h] [ebp-1F4h]
int v10; // [esp+Ch] [ebp-1ECh] BYREF
_UNICODE_STRING NtName; // [esp+10h] [ebp-1E8h] BYREF
PCWSTR DosName; // [esp+18h] [ebp-1E0h]
int v13; // [esp+1Ch] [ebp-1DCh] BYREF
int v14; // [esp+20h] [ebp-1D8h]
PVOID P; // [esp+24h] [ebp-1D4h]
int v16; // [esp+28h] [ebp-1D0h]
int v17[114]; // [esp+2Ch] [ebp-1CCh] BYREF
DosName = a1;
NtName.Length = 0;
*(_DWORD *)&NtName.MaximumLength = 0;
HIWORD(NtName.Buffer) = 0;
v14 = 1;
v13 = 0;
v10 = 456;
v16 = 0;
if ( gdwInfrastructureFlags >= 0 )
v6 = CheckAppcompatInfrastructureFlags() & 1;
else
v6 = gdwInfrastructureFlags & 1;
if ( !v6 )
{
if ( RtlDosPathNameToRelativeNtPathName_U(DosName, &NtName, 0, 0)
&& BaseCheckAppcompatCacheEx(NtName.Buffer, -1, 0, &v13, &v10, v17) )
{
if ( (v13 & 0x100) != 0 )
{
v16 = 1;
}
else
{
if ( (v13 & 0x200) == 0 )
goto LABEL_8;
memset(v17, 0, sizeof(v17));
}
}
P = (PVOID)SdbInitDatabaseEx(0, 0, 332);
if ( P )
{
if ( v16 && !SdbIsValidQueryResultLight(v17) )
{
v16 = 0;
memset(v17, 0, sizeof(v17));
}
v14 = ApphelpQueryExe(P, DosName, a2, a6, v17, v16);
if ( !a5 )
{
v17[43] = 0;
memset(&v17[32], 0, 0x20u);
}
if ( v14 && a3 )
ApphelpFixExe((int)P, (wchar_t *)DosName, (int)v17, a4, a6);
SdbReleaseDatabase(P);
}
else if ( g_iShimDebugLevel )
{
ShimDbgPrint(1, (int)"ApphelpCheckExe", "Failed to initialize database.\n", v8, v9);
}
}
LABEL_8:
RtlFreeUnicodeString(&NtName);
return v14;
}
更新后
int __stdcall ApphelpCheckModule(const WCHAR *a1, int a2, int a3, int a4, int a5, char a6)
{
int v6; // eax
void *v8; // ebx
char v9; // [esp+0h] [ebp-1F4h]
char v10; // [esp+4h] [ebp-1F0h]
int v11; // [esp+Ch] [ebp-1E8h] BYREF
_UNICODE_STRING NtName; // [esp+10h] [ebp-1E4h] BYREF
int v13; // [esp+18h] [ebp-1DCh]
int v14; // [esp+1Ch] [ebp-1D8h] BYREF
int v15; // [esp+20h] [ebp-1D4h]
PCWSTR DosName; // [esp+24h] [ebp-1D0h]
int v17[114]; // [esp+28h] [ebp-1CCh] BYREF
DosName = a1;
NtName.Length = 0;
*(_DWORD *)&NtName.MaximumLength = 0;
HIWORD(NtName.Buffer) = 0;
v15 = 1;
v14 = 0;
v11 = 456;
v13 = 0;
if ( gdwInfrastructureFlags >= 0 )
v6 = CheckAppcompatInfrastructureFlags() & 1;
else
v6 = gdwInfrastructureFlags & 1;
if ( !v6 )
{
if ( RtlDosPathNameToRelativeNtPathName_U(DosName, &NtName, 0, 0)
&& BaseCheckAppcompatCacheEx(NtName.Buffer, -1, 0, &v14, &v11, v17) )
{
if ( (v14 & 0x100) != 0 )
{
v13 = 1;
}
else
{
if ( (v14 & 0x200) == 0 )
goto LABEL_8;
memset(v17, 0, sizeof(v17));
}
}
v8 = (void *)SdbInitDatabaseEx(0, 0, 332);
if ( v8 )
{
v15 = ApphelpQueryExe(v8, DosName, a2, a6, v17, v13);
if ( !a5 )
{
v17[43] = 0;
memset(&v17[32], 0, 0x20u);
}
if ( v15 && a3 )
ApphelpFixExe((int)v8, (wchar_t *)DosName, (int)v17, a4, a6);
SdbReleaseDatabase(v8);
}
else if ( g_iShimDebugLevel )
{
ShimDbgPrint(1, (int)"ApphelpCheckExe", "Failed to initialize database.\n", v9, v10);
}
}
LABEL_8:
RtlFreeUnicodeString(&NtName);
return v15;
}
InternalCheckRunApp
更新前
BOOL __stdcall InternalCheckRunApp(void *a1, int a2, int a3, const WCHAR *a4, WCHAR *a5, int a6, unsigned int *a7, int a8, int a9, _DWORD *a10, _DWORD *a11, _DWORD *a12, int a13, int a14, _WORD *a15, int a16, void *a17, _DWORD *a18, void *a19)
{
_DWORD *v19; // esi
_DWORD *v20; // esi
int *v21; // esi
int v22; // ecx
int v23; // eax
int v24; // eax
char *v26; // eax
char v27; // di
PVOID v28; // eax
unsigned int *v29; // edi
void *v30; // eax
unsigned int v31; // edi
_DWORD *v32; // edi
int v33; // eax
_DWORD