运行单一实例

运行单一实例

0x00 前言

诸如上线后的维权操作,运行过多的进程可能会造成c/s端通讯异常,而过多的危险程序进程也会增加暴露风险,所以说可以给程序加一个api,通过创建一个系统命名互斥对象来实现。又比如在自启维权操作时,可以保证马已经在运行的时候,不用再次运行payload加载部分,避免过多的操作造成暴露风险。

0x01 函数介绍

1.CreateMutex函数

创建或打开一个已命名或者未命名的护持对象。

2.函数定义

HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);

3.参数与返回值

参数

lpMutexAttributes [in, optional]
指向SECURITY_ATTRIBUTES结构的指针。如果此参数为NULL,则该句柄不能由子进程继承。
bInitialOwner [in]
如果此值为TRUE并且调用者创建了互斥锁,则调用线程将获得互斥锁对象的初始所有权。否则,调用线程不会获得互斥锁的所有权。
lpName [in, optional]
互斥对象的名称。该名称仅限于MAX_PATH字符。名称比较区分大小写。如果lpName为NULL,则会创建不带名称的互斥体对象。
如果lpName与现有事件,信号量,等待定时器,作业或文件映射对象的名称匹配,则该函数将失败,并且GetLastError函数返回ERROR_INVALID_HANDLE。这是因为这些对象共享相同的名称空间。
该名称可以具有“Global”或“Local”前缀以在全局或会话名称空间中显式创建对象。名称的其余部分可以包含除反斜杠字符(\)以外的任何字符。

返回值

如果函数成功,则返回值是新创建的互斥对象的句柄。
如果函数失败,返回值为NULL。 要获得扩展的错误信息,请调用GetLastError。
如果互斥锁是一个已命名的互斥锁,并且该对象在此函数调用之前就存在,则返回值是现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS。

0x02 编码实现

#include <iostream>
#include <Windows.h>

// 判断是否重复运行
BOOL IsAlreadyRun()
{
	HANDLE hMutex = NULL;
	hMutex = ::CreateMutex(NULL, FALSE, "TEST");
	if (hMutex)
	{
		if (ERROR_ALREADY_EXISTS == ::GetLastError())
		{
			return TRUE;
		}
	}
	return FALSE;
}
int main()
{
	// 判断是否重复运行
	if (IsAlreadyRun())
	{
		printf("Already Run!!!!\n");
	}
	else
	{
		printf("NOT Already Run!\n");
	}

	system("pause");
	return 0;
}

0x03 关于报错

Tips:

关于如果Visual Studio 2019 出现const char *“ 类型的实参与 “LPCWSTR“ 类型的形参不兼容这类错误。

解决方法:

右击项目文件 — 单击属性 — 配置属性 — 高级 — 高级属性 — 字符集

使用 Unicode 字符集”改为“使用多字节字符集

image

0x04 实测

image

0x05 关于原理思考与学习记录

CreateMutex函数一共的三个参数,主要起作用的是第三个,第三个参数表示互斥对象的名称,程序的主要逻辑就是通过互斥对象来判断进程实例是否重复运行,而如果实现该参数必须设置并保证唯一性。

而第一个参数表示互斥对象的安全设置,是一个指向SECURITY_ATTRIBUTES结构的指针,在该程序中直接设置为NULL即可。

第二个参数表示线程是否获得互斥锁对象的初始所有权,在该程序中,无论该参数为TRUE或者FALSE,均不影响程序的正常执行。

我们编写运行单一实例时,可以通过if判断语句判断程序是否已经在运行。

首先通过CreateMutex创建一个被命名的互斥对象,其次通过调用GetLastError函数获取的返回码的值是否为ERROR_ALREADY_EXISTS,如果是则表示该命名互斥对象存在,即程序重复运行,否则认为是首次运行程序。

另外就是通过CreateMutex创建完进程互斥对象,不能通过CloseHandle等方法关闭进程句柄,否则就相当于关闭了互斥对象的句柄,释放资源没有任何作用了。

0x06 参考

https://www.write-bug.com/article/1602.html

posted @ 2021-08-19 02:34  cunren  阅读(98)  评论(0编辑  收藏  举报