系列文章目录
展示了如何利用专有命名空间,以一种更安全的方式来实现单例应用程序。Ddos攻击
文章目录
/*
展示了如何利用专有命名空间,以一种更安全的方式来实现单例应用程序。Ddos攻击
*/
#include "CmnHdr.h" //编译配置文件
#include <windowsx.h>
#include <tchar.h>
#include "Resource.h"
#include <sddl.h> //for SID mamagment此表头由安全和身份使用
#include <strsafe.h>
HWND g_hDlg;//对话框句柄
//互斥量,边界和命名空间,用于检测以前运行的实例
HANDLE g_hSingleton = NULL;
HANDLE g_hBoundary = NULL;
HANDLE g_hNamespace = NULL;
//跟踪命名空间是否被创建和打开以进行清理
BOOL g_bNamespaceOpened = FALSE;
//边界和私有命名空间的名称
PCTSTR g_szBoundary = TEXT("3-Boundary");
PCTSTR g_szNamespace = TEXT("3-Namespace");
//获取编辑控制句柄
#define DETAILS_CTRL GetDlgItem(g_hDlg, IDC_EDIT_DETAILS)
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
VOID Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotify);
VOID CheckInstances();
void AddText(PCTSTR pszFormat, ...);
void ShowErrMsg()
{
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
MessageBox(NULL, (LPCWSTR)lpMsgBuf, L"系统错误", MB_OK | MB_ICONSTOP);
LocalFree(lpMsgBuf);
}
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);
}
//核心代码
VOID CheckInstances()
{
//第一步:创建boundary descriptor
g_hBoundary = CreateBoundaryDescriptor(g_szBoundary, 0);
//第二步:创建与“”组对应的SID
BYTE localAdminSID[SECURITY_MAX_SID_SIZE];//安全描述符SID值得最大长度。目前是68
PSID pLocalAdminSID = &localAdminSID;
DWORD cbSID = sizeof(localAdminSID);
//常见一个用于预定义别名SID,NULL表示本地计算机
if (!CreateWellKnownSid(
WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID))//指定与管理员匹配得SID
{
AddText(TEXT("AddSIDToBoundaryDescriptor failed:%u\r\n"), GetLastError());
return;
}
//第三步:将本地管理SID关联到边界描述符
//---->仅用于管理员用户下运行的应用程序
//将能够访问同一个命名空间的内核对象
if (!AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID))
{
AddText(TEXT("AddSIDToBoundaryDescriptor failed:%u\r\n"), GetLastError());
return;
}
//第四步:仅“Local Adminstators"创建namespace
SECURITY_ATTRIBUTES sa;//安全描述符
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;//新进程不会继承句柄
//将一个安全描述符格式的字符串抓好换成一个有效的安全描述符结构
//安全描述符字符串的格式:ACE strings
//语法:ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_side;(resource_attribute
//"D"访问拒绝ace类型,"A"允许访问ace类型 “GA”所有泛型,“BA”内置管理元
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);
//不要忘记为为安全描述符释放内存
LocalFree(sa.lpSecurityDescriptor);
//查看私有namespace的创建结果
DWORD dwLastError = GetLastError();
if (g_hNamespace == NULL)
{
//如果访问被拒绝,则不做任何事情//--->此代码必须在本地管理员账户下运行
if (dwLastError == ERROR_ACCESS_DENIED)
{
AddText(TEXT("Access denied when creating the namespace.\r\n"));
AddText(TEXT(" You must be running as adminstror,\r\n\r\n"));
}
else
{
if (dwLastError == ERROR_ALREADY_EXISTS)
{
//如果另一个实例已经创建了命名空间,我们需要打开他
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;
}
}
}
//第五步:尝试创建一个带有名称的互斥对象
//基于私有命名空间
TCHAR szMuxteName[64];
StringCchPrintf(szMuxteName, _countof(szMuxteName), TEXT("%s\\%s"),
g_szNamespace, TEXT("Singleton"));
g_hSingleton = CreateMutex(NULL, FALSE, szMuxteName);
/*
if (GetLastError()!=0)
{
ShowErrMsg();
}
*/
if (dwLastError == ERROR_ALREADY_EXISTS)
{
//这个singleton对象已经有一个实例了。
ShowErrMsg();
AddText(TEXT("Another instance of Singleton is running:\r\n"));
AddText(TEXT("-->Impossible to access application features无法访问应用程序特征。\r\n"));
}
else
{
//第一次创建Singleton对象
AddText(TEXT("First instance of Singleton:\r\n"));
AddText(TEXT("--> Access application features now.\r\n"));
}
}
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
chSETDLGICONS(hwnd, IDI_SINGLETON);
//跟踪主对话框装口句柄
g_hDlg = hwnd;
//检查是否有其他实例正在运行
CheckInstances();
return(TRUE);
}
VOID Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotify)
{
switch (id)
{
case IDOK:
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
}
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
}
return FALSE;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//展开传递的参数和表达式。其目的是避免编译器关于未引用参数的警告
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
//创建对话框窗口
DialogBox(hInstance, MAKEINTRESOURCE(IDD_SINGLETON), NULL, Dlg_Proc);
//不要忘记清理和释放内核资源
if (g_hSingleton != NULL)
{
CloseHandle(g_hSingleton);
}
if (g_hNamespace != NULL)
{
//关闭一个打开的命名空间句柄
if (g_bNamespaceOpened)
{
ClosePrivateNamespace(g_hNamespace,0);//已打开--->关闭
}
else
{
ClosePrivateNamespace(g_hNamespace, PRIVATE_NAMESPACE_FLAG_DESTROY);//未打开,销毁
}
}
if (g_hBoundary != NULL)
{
DeleteBoundaryDescriptor(g_hBoundary);
}
return 0;
}