让应用程序只启动一次
在编写应用程序,有时候会有 让应用程序只启动一次的 要求。
一. 命名的内核对象利用 内核中的命名对象 名称不能重复这一特性,来实现 应用程序的只启动一次的请求。
以Mutex为例,可以利用CreateMutex函数:
黑客很可能利用这个锁名,在应用服务程序启动之前,先创建这个锁,从而导致应用服务程序启动失败。
3.2 解决方法创建专有的命名空间,专有命名空间就类似于 在内核名称之前在加上一个目录名称,ProcessExplorer中显示为 "\..\锁名",而不会暴露专有命名空间名字。
专有命名空间关联一个 边界描述符 (Boundary Descriptor), 边界描述符 至少包含一个SID;
个人理解 边界描述符 就是 根据SID和边界描述符名称划分的一个域。
//参考<<windows核心编程>>#include<windows.h>#include <Sddl.h>#include<stdio.h>#include<string.h>#include <strsafe.h>int main (){//创建边界描述符PCTSTR g_szBoundary = TEXT("TestForBoundary");HANDLE g_hBoundary = CreateBoundaryDescriptor(g_szBoundary, 0);//添加管理员组SID到边界描述符BYTE localAdminSID[SECURITY_MAX_SID_SIZE];PSID pLocalAdminSID = &localAdminSID;DWORD cbSID = sizeof(localAdminSID);if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID)){printf("CreateWellKnownSid Failed!\n");return -1;}if (!AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID)){printf("AddSIDToBoundaryDescriptor Failed!\n");return -1;}//产生安全信息SECURITY_ATTRIBUTES sa;sa.nLength = sizeof(sa);sa.bInheritHandle = FALSE;if (!ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:(A;;GA;;;BA)"),SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)){printf("ConvertString Failed!\n");return -1;}//创建专有命名空间 "TestForNamespace"PCTSTR g_szNamespace = TEXT("TestForNamespace");HANDLE g_hNamespace = CreatePrivateNamespace(&sa, g_hBoundary, g_szNamespace);if (g_hNamespace == NULL) {//这里没有进行处理,如果已经创建,可以打开专有命名空间//OpenPrivateNamespace APIprintf("CreatePrivateNamespace Failed!\n");return -1;}LocalFree(sa.lpSecurityDescriptor);//创建锁TCHAR szMutexName[64];StringCchPrintf(szMutexName, _countof(szMutexName), TEXT("%s\\%s"),g_szNamespace, TEXT("TestForApp"));HANDLE g_hSingleton = CreateMutex(NULL, FALSE, szMutexName);if (GetLastError() == ERROR_ALREADY_EXISTS){printf("应用程序实例已经启动!\n");return -1;}return 0;}