《windows核心编程》笔记(三)

命名内核对象有一种问题:任何程序都可以创建一个命名对象,这样如果某个程序要实现单例运行而创建了一个内核对象,这种情况下另一程序也创建了同名的内核对象时,该单例程序就无法正常运行了。这是DoS攻击的一种。

Vista中有一种机制使得用户创建的命名内核对象永远不会和其它程序创建的对象冲突,要使用定制的前缀并把它作为人的私有命名空间,如GlobalLocal,服务进程会确保为内核对象定义一边界描述符来保护命名空间。
下面是检查实例的代码:

void CheckInstances() 
{//检查实例
   
// Create the boundary descriptor
   g_hBoundary = CreateBoundaryDescriptor(g_szBoundary, 0);

   
// Create a SID corresponding to the Local Administrator group
   BYTE localAdminSID[SECURITY_MAX_SID_SIZE];
   PSID pLocalAdminSID 
= &localAdminSID;
   DWORD cbSID 
= sizeof(localAdminSID);
   
if (!CreateWellKnownSid(
      WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, 
&cbSID)
      ) 
{
      AddText(TEXT(
"AddSIDToBoundaryDescriptor failed: %u\r\n"), 
         GetLastError());
      
return;
   }

   
   
// Associate the Local Admin SID to the boundary descriptor
   
// --> only applications running under an administrator user
   
//     will be able to access the kernel objects in the same namespace
   if (!AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID)) {
      AddText(TEXT(
"AddSIDToBoundaryDescriptor failed: %u\r\n"), 
         GetLastError());
      
return;
   }


   
// Create the namespace for Local Administrators only
   SECURITY_ATTRIBUTES sa;
   sa.nLength 
= sizeof(sa);
   sa.bInheritHandle 
= FALSE;
   
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
      TEXT(
"D:(A;;GA;;;BA)"), 
      SDDL_REVISION_1, 
&sa.lpSecurityDescriptor, NULL)) {
      AddText(TEXT(
"Security Descriptor creation failed: %u\r\n"), GetLastError());
      
return;
   }


   g_hNamespace 
= 
      CreatePrivateNamespace(
&sa, g_hBoundary, g_szNamespace);

   
// Don't forget to release memory for the security descriptor
   LocalFree(sa.lpSecurityDescriptor);


   
// Check the private namespace creation result
   DWORD dwLastError = GetLastError();
   
if (g_hNamespace == NULL) 
   
{
      
// Nothing to do if access is denied
      
// --> this code must run under a Local Administrator account
      if (dwLastError == ERROR_ACCESS_DENIED) 
      
{
         AddText(TEXT(
"Access denied when creating the namespace.\r\n"));
         AddText(TEXT(
"   You must be running as Administrator.\r\n\r\n"));
         
return;
      }

      
else 
      

         
if (dwLastError == ERROR_ALREADY_EXISTS) 
         
{
         
// If another instance has already created the namespace, 
         
// we need to open it instead. 
            AddText(TEXT("CreatePrivateNamespace failed: %u\r\n"), dwLastError);
            g_hNamespace 
= OpenPrivateNamespace(g_hBoundary, g_szNamespace);
            
if (g_hNamespace == NULL) 
            
{
               AddText(TEXT(
"   and OpenPrivateNamespace failed: %u\r\n"), 
               dwLastError);
               
return;
            }
 
            
else 
            
{
               g_bNamespaceOpened 
= TRUE;
               AddText(TEXT(
"   but OpenPrivateNamespace succeeded\r\n\r\n"));
            }

         }
 
         
else
         
{
            AddText(TEXT(
"Unexpected error occured: %u\r\n\r\n"),dwLastError);
            
return;
         }

      }

   }

   
   
// Try to create the mutex object with a name 
   
// based on the private namespace 
   TCHAR szMutexName[64];
   StringCchPrintf(szMutexName, _countof(szMutexName), TEXT(
"%s\\%s"), g_szNamespace, TEXT("Singleton"));

   g_hSingleton 
= CreateMutex(NULL, FALSE, szMutexName);//创建互斥量
   if (GetLastError() == ERROR_ALREADY_EXISTS) 
   
{
      
// There is already an instance of this Singleton object
      AddText(TEXT("Another instance of Singleton is running:\r\n"));
      AddText(TEXT(
"--> Impossible to access application features.\r\n"));
   }

   
else  
   
{
      
// First time the Singleton object is created
      AddText(TEXT("First instance of Singleton:\r\n"));
      AddText(TEXT(
"--> Access application features now.\r\n"));
   }

}




void AddText(PCTSTR pszFormat, {

   va_list argList;
   va_start(argList, pszFormat);

   TCHAR sz[
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);
}

posted on   Phinecos(洞庭散人)  阅读(1897)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2007-06-08 OnDraw()和OnPaint()的区别
2006-06-08 《Java编程思想》读书笔记(11)
2006-06-08 TOJ_1002解题报告
2006-06-08 TOJ_1001解题报告
2006-06-08 《Java编程思想》读书笔记(10)

导航

统计

点击右上角即可分享
微信分享提示