命名内核对象有一种问题:任何程序都可以创建一个命名对象,这样如果某个程序要实现单例运行而创建了一个内核对象,这种情况下另一程序也创建了同名的内核对象时,该单例程序就无法正常运行了。这是DoS攻击的一种。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
在Vista中有一种机制使得用户创建的命名内核对象永远不会和其它程序创建的对象冲突,要使用定制的前缀并把它作为人的私有命名空间,如Global和Local,服务进程会确保为内核对象定义一边界描述符来保护命名空间。
下面是检查实例的代码:
voidCheckInstances()

{//检查实例
//Createtheboundarydescriptor
g_hBoundary=CreateBoundaryDescriptor(g_szBoundary,0);
//CreateaSIDcorrespondingtotheLocalAdministratorgroup
BYTElocalAdminSID[SECURITY_MAX_SID_SIZE];
PSIDpLocalAdminSID=&localAdminSID;
DWORDcbSID=sizeof(localAdminSID);
if(!CreateWellKnownSid(
WinBuiltinAdministratorsSid,NULL,pLocalAdminSID,&cbSID)
)
{
AddText(TEXT("AddSIDToBoundaryDescriptorfailed:%u/r/n"),
GetLastError());
return;
}
//AssociatetheLocalAdminSIDtotheboundarydescriptor
//-->onlyapplicationsrunningunderanadministratoruser
//willbeabletoaccessthekernelobjectsinthesamenamespace
if(!AddSIDToBoundaryDescriptor(&g_hBoundary,pLocalAdminSID))
{
AddText(TEXT("AddSIDToBoundaryDescriptorfailed:%u/r/n"),
GetLastError());
return;
}
//CreatethenamespaceforLocalAdministratorsonly
SECURITY_ATTRIBUTESsa;
sa.nLength=sizeof(sa);
sa.bInheritHandle=FALSE;
if(!ConvertStringSecurityDescriptorToSecurityDescriptor(
TEXT("D:(A;;GA;;;BA)"),
SDDL_REVISION_1,&sa.lpSecurityDescriptor,NULL))
{
AddText(TEXT("SecurityDescriptorcreationfailed:%u/r/n"),GetLastError());
return;
}
g_hNamespace=
CreatePrivateNamespace(&sa,g_hBoundary,g_szNamespace);
//Don'tforgettoreleasememoryforthesecuritydescriptor
LocalFree(sa.lpSecurityDescriptor);

//Checktheprivatenamespacecreationresult
DWORDdwLastError=GetLastError();
if(g_hNamespace==NULL)

{
//Nothingtodoifaccessisdenied
//-->thiscodemustrununderaLocalAdministratoraccount
if(dwLastError==ERROR_ACCESS_DENIED)

{
AddText(TEXT("Accessdeniedwhencreatingthenamespace./r/n"));
AddText(TEXT("YoumustberunningasAdministrator./r/n/r/n"));
return;
}
else

{
if(dwLastError==ERROR_ALREADY_EXISTS)

{
//Ifanotherinstancehasalreadycreatedthenamespace,
//weneedtoopenitinstead.
AddText(TEXT("CreatePrivateNamespacefailed:%u/r/n"),dwLastError);
g_hNamespace=OpenPrivateNamespace(g_hBoundary,g_szNamespace);
if(g_hNamespace==NULL)

{
AddText(TEXT("andOpenPrivateNamespacefailed:%u/r/n"),
dwLastError);
return;
}
else

{
g_bNamespaceOpened=TRUE;
AddText(TEXT("butOpenPrivateNamespacesucceeded/r/n/r/n"));
}
}
else

{
AddText(TEXT("Unexpectederroroccured:%u/r/n/r/n"),dwLastError);
return;
}
}
}
//Trytocreatethemutexobjectwithaname
//basedontheprivatenamespace
TCHARszMutexName[64];
StringCchPrintf(szMutexName,_countof(szMutexName),TEXT("%s//%s"),g_szNamespace,TEXT("Singleton"));
g_hSingleton=CreateMutex(NULL,FALSE,szMutexName);//创建互斥量
if(GetLastError()==ERROR_ALREADY_EXISTS)

{
//ThereisalreadyaninstanceofthisSingletonobject
AddText(TEXT("AnotherinstanceofSingletonisrunning:/r/n"));
AddText(TEXT("-->Impossibletoaccessapplicationfeatures./r/n"));
}
else

{
//FirsttimetheSingletonobjectiscreated
AddText(TEXT("FirstinstanceofSingleton:/r/n"));
AddText(TEXT("-->Accessapplicationfeaturesnow./r/n"));
}
}


voidAddText(PCTSTRpszFormat,
)
{
va_listargList;
va_start(argList,pszFormat);
TCHARsz[20*1024];
Edit_GetText(DETAILS_CTRL,sz,_countof(sz));
_vstprintf_s(
_tcschr(sz,TEXT('/0')),_countof(sz)-_tcslen(sz),
pszFormat,argList);
Edit_SetText(DETAILS_CTRL,sz);
va_end(argList);
}
本文介绍Windows Vista中一种防止应用程序被多次启动的技术。通过创建私有命名空间和边界描述符,仅允许管理员权限的应用访问特定内核对象,确保单例运行。提供了实现这一功能的示例代码。
2385

被折叠的 条评论
为什么被折叠?



