CreateMutex防多开

CreateMutex防多开include windows h include stdio h intmain intargc char argv 初始化临界区全局原子变量 HANDLEMutexH CreateMutex NULL FALSE TEXT AAA 创建互斥体 信号量为 0 有信号的状态 wait 可以等待 DWORDErrorCo 0 ErrorCode GetLastError stdio h windows h

#include  
     # include 
     int main(int argc, char* argv[]) { 
    //初始化临界区全局原子变量 HANDLE MutexHandle = CreateMutex(NULL, FALSE, TEXT("AAA")); //创建互斥体. 信号量为0. 有信号的状态.wait可以等待 DWORD ErrorCode = 0; ErrorCode = GetLastError(); if (ERROR_ALREADY_EXISTS == ErrorCode) { 
    printf("禁止多开\r\n"); CloseHandle(MutexHandle); system("pause"); } if (NULL == MutexHandle) { 
    return 0; //表示句柄获取失败 } static int i = 0; while(1) { 
    Sleep(1000); printf("当前程序运行中. EIP 位置 等于 %d \r\n", i++); } system("pause"); return 0; } 

反反调试
HandleCount清0
PointCount清0
Name替换
HandleTableEntry清0








用到的相关结构体

_HEADER_NAME_INFO _EXHANDLE _HANDLE_TABLE_ENTRY _HANDLE_TABLE_FREE_LIST _HANDLE_TABLE _SYSTEM_INFORMATION_CLASS _SYSTEM_THREADS _SYSTEM_PROCESSES 

详情

///  /// 内核对象可变对象头之一,描述了一个内核对象的名称信息 ///  typedef struct _HEADER_NAME_INFO { 
    PVOID Directory; UNICODE_STRING Name; INT32 ReferenceCount; UINT32 Reserved; } HEADER_NAME_INFO,* PHEADER_NAME_INFO; 
///  /// 句柄 ///  typedef struct _EXHANDLE { 
    //32位 union { 
    struct { 
    ULONG TagBits : 2; ULONG Index : 30; }; HANDLE GenericHandleOverlay; ULONG_PTR Value; }; } EXHANDLE, * PEXHANDLE; 
///  /// 句柄表项 ///  typedef struct _HANDLE_TABLE_ENTRY { 
    union { 
    LONG_PTR VolatileLowValue; LONG_PTR LowValue; PVOID InfoTable; LONG_PTR RefCountField; struct { 
    ULONG_PTR Unlocked : 1; ULONG_PTR RefCnt : 16; ULONG_PTR Attributes : 3; ULONG_PTR ObjectPointerBits : 44;//长度为 44 位的数据,指向一个内核对象 }; }; union { 
    LONG_PTR HighValue; struct _HANDLE_TABLE_ENTRY* NextFreeHandleEntry; EXHANDLE LeafHandleValue; struct { 
    ULONG32 GrantedAccessBits : 25;//长度为 25 位的数据,表示对象权限 ULONG32 NoRightsUpgrade : 1; ULONG32 Spare1 : 6; }; ULONG32 Spare2; }; } HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY; 
///  /// _HANDLE_TABLE的成员之一 ///  typedef struct _HANDLE_TABLE_FREE_LIST { 
    ULONG_PTR FreeListLock; PHANDLE_TABLE_ENTRY FirstFreeHandleEntry; PHANDLE_TABLE_ENTRY lastFreeHandleEntry; LONG32 HandleCount; ULONG32 HighWaterMark; ULONG32 Reserved[8]; } HANDLE_TABLE_FREE_LIST, * PHANDLE_TABLE_FREE_LIST; 
///  /// EPROCESS的成员之一,描述了指向局部句柄表的相关信息,其中的TableCode指向局部句柄表 ///  typedef struct _HANDLE_TABLE { 
    ULONG32 NextHandleNeedingPool; LONG32 ExtraInfoPages; ULONG_PTR TableCode; PEPROCESS QuotaProcess; LIST_ENTRY HandleTableList; ULONG32 UniqueProcessId; union { 
    ULONG32 Flags; struct { 
    BOOLEAN StrictFIFO : 1; BOOLEAN EnableHandleExceptions : 1; BOOLEAN Rundown : 1; BOOLEAN Duplicated : 1; BOOLEAN RaiseUMExceptionOnInvalidHandleClose : 1; }; }; ULONG_PTR HandleContentionEvent; ULONG_PTR HandleTableLock; union { 
    HANDLE_TABLE_FREE_LIST FreeLists[1]; BOOLEAN ActualEntry[32]; }; PVOID DebugInfo; } HANDLE_TABLE, * PHANDLE_TABLE; 
/* * 下面是一个枚举结构,每一个枚举值对应一类系统信息, * 比如 SystemPerformanceInformation 代表所有的进程信息。 */ typedef enum _SYSTEM_INFORMATION_CLASS { 
    SystemBasicInformation, // 0 Y N  SystemProcessorInformation, // 1 Y N  SystemPerformanceInformation, // 2 Y N  SystemTimeOfDayInformation, // 3 Y N  SystemNotImplemented1, // 4 Y N  SystemProcessesAndThreadsInformation, // 5 Y N  SystemCallCounts, // 6 Y N  SystemConfigurationInformation, // 7 Y N  SystemProcessorTimes, // 8 Y N  SystemGlobalFlag, // 9 Y Y  SystemNotImplemented2, // 10 Y N  SystemModuleInformation, // 11 Y N  SystemLockInformation, // 12 Y N  SystemNotImplemented3, // 13 Y N  SystemNotImplemented4, // 14 Y N  SystemNotImplemented5, // 15 Y N  SystemHandleInformation, // 16 Y N  SystemObjectInformation, // 17 Y N  SystemPagefileInformation, // 18 Y N  SystemInstructionEmulationCounts, // 19 Y N  SystemInvalidInfoClass1, // 20  SystemCacheInformation, // 21 Y Y  SystemPoolTagInformation, // 22 Y N  SystemProcessorStatistics, // 23 Y N  SystemDpcInformation, // 24 Y Y  SystemNotImplemented6, // 25 Y N  SystemLoadImage, // 26 N Y  SystemUnloadImage, // 27 N Y  SystemTimeAdjustment, // 28 Y Y  SystemNotImplemented7, // 29 Y N  SystemNotImplemented8, // 30 Y N  SystemNotImplemented9, // 31 Y N  SystemCrashDumpInformation, // 32 Y N  SystemExceptionInformation, // 33 Y N  SystemCrashDumpStateInformation, // 34 Y Y/N  SystemKernelDebuggerInformation, // 35 Y N  SystemContextSwitchInformation, // 36 Y N  SystemRegistryQuotaInformation, // 37 Y Y  SystemLoadAndCallImage, // 38 N Y  SystemPrioritySeparation, // 39 N Y  SystemNotImplemented10, // 40 Y N  SystemNotImplemented11, // 41 Y N  SystemInvalidInfoClass2, // 42  SystemInvalidInfoClass3, // 43  SystemTimeZoneInformation, // 44 Y N  SystemLookasideInformation, // 45 Y N  SystemSetTimeSlipEvent, // 46 N Y  SystemCreateSession, // 47 N Y  SystemDeleteSession, // 48 N Y  SystemInvalidInfoClass4, // 49  SystemRangeStartInformation, // 50 Y N  SystemVerifierInformation, // 51 Y Y  SystemAddVerifier, // 52 N Y  SystemSessionProcessesInformation // 53 Y N  } SYSTEM_INFORMATION_CLASS; 
///  /// 线程信息结构体,进程信息结构体的成员之一 ///  typedef struct _SYSTEM_THREADS { 
    LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientIs; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; #ifdef _WIN64 ULONG Reserved; //Add #endif }SYSTEM_THREADS, * PSYSTEM_THREADS; 
///  /// //进程信息结构体  ///  typedef struct _SYSTEM_PROCESSES { 
    ULONG NextEntryDelta; //链表下一个结构和上一个结构的偏移 ULONG ThreadCount; //线程数目; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; //用户模式(Ring 3)的CPU时间; LARGE_INTEGER KernelTime; //内核模式(Ring 0)的CPU时间; UNICODE_STRING ProcessName; //进程名字 KPRIORITY BasePriority; HANDLE ProcessId; //进程的pid号 HANDLE InheritedFromProcessId; //父进程的标识符; ULONG HandleCount; ULONG SessionId; ULONG_PTR PageDirectoryBase; VM_COUNTERS VmCounters; #ifdef _WIN64 SIZE_T PrivatePageCount; #endif IO_COUNTERS IoCounters; //windows 2000 only  SYSTEM_THREADS Threads[1]; }SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; 

用到的相关函数

/* * --------------------------------函数声明 */ typedef BOOLEAN (*PHANDLE_TABLE_ENTRY_FUNC)(PHANDLE_TABLE_ENTRY pHandleTableEntry, PVOID pObject, POBJECT_TYPE pObjectType); PHANDLE_TABLE_ENTRY SearchHandleTableEntry(PHANDLE_TABLE pObjectTable, EXHANDLE HandleIndex); NTKERNELAPI PVOID NTAPI ObGetObjectType(IN PVOID pObject); BOOLEAN KillMutex(PHANDLE_TABLE_ENTRY pHandleTableEntry, PVOID pMutex, POBJECT_TYPE pObjectType); NTKERNELAPI PVOID ObQueryNameInfo(IN PVOID Object); void PrintPrivateTable(PEPROCESS pEprocess, PHANDLE_TABLE_ENTRY_FUNC func); NTSTATUS ZwQuerySystemInformation( IN ULONG SystemInformationClass, //处理进程线程信息,只需要处理类别为5的即可 OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength ); NTSTATUS PsLookupProcessByProcessId( HANDLE ProcessId, PEPROCESS* Process ); CHAR GetRandomNumber(); /* * --------------------------------函数声明 */ 

详情

#pragma warning(disable:4100) #pragma warning(disable:4214) #pragma warning(disable:4201) #pragma warning(disable:4189) # define HANDLE_VALUE_INC 4 # define HANDLE_TABLE_OFFSET 0x418 
//================================================================== //函数名:GetEprocessByExeName  //功能:根据进程的名字,例如L"xxx.exe",获取进程的EPROCESS数组(进程名相同的进程不唯一)  //输入参数1:ExeName,IN,进程的名字字符串 //输入参数2:Process,OUT,获取到的进程的EPROCESS数组 //返回值:NTSTATUS ,返回PsLookupProcessByProcessId的返回值 //================================================================== NTSTATUS GetEprocessByExeName(wchar_t*ExeName, PEPROCESS* Process) { 
    NTSTATUS nStatus; ULONG retLength; //缓冲区长度 PVOID pProcInfo;//缓冲区指针 PSYSTEM_PROCESSES pProcIndex; //调用函数,获取进程信息 nStatus = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, //获取进程信息,宏定义为5 NULL, 0, &retLength //返回的长度,即为我们需要申请的缓冲区的长度 ); if (!retLength) { 
    DbgPrint("ZwQuerySystemInformation error!\n"); return nStatus; } //DbgPrint("retLength = %u\n", retLength); //申请空间 pProcInfo = ExAllocatePool(NonPagedPool, retLength); if (!pProcInfo) { 
    DbgPrint("ExAllocatePool error!\n"); return STATUS_UNSUCCESSFUL; } nStatus = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, //宏定义为5 pProcInfo, retLength, &retLength ); if (NT_SUCCESS(nStatus)/*STATUS_INFO_LENGTH_MISMATCH == nStatus*/) { 
    pProcIndex = (PSYSTEM_PROCESSES)pProcInfo; //第一个进程应该是 pid 为 0 的进程 /* if (pProcIndex->ProcessId == 0) DbgPrint("ProcName: %-20ws pid: %u\n", L"System Idle Process",0);*/ //循环打印所有进程信息,因为最后一天进程的NextEntryDelta值为0,所以先打印后判断 do { 
    pProcIndex = (PSYSTEM_PROCESSES)((char*)pProcIndex + pProcIndex->NextEntryDelta); //进程名字字符串处理,防止打印时,出错 /* if (pProcIndex->ProcessName.Buffer == NULL) { pProcIndex->ProcessName.Buffer = L"NULL"; }*/ if (wcscmp(pProcIndex->ProcessName.Buffer, ExeName) == 0) { 
    DbgPrint("ProcName: %-20ws pid: %u\n", pProcIndex->ProcessName.Buffer, pProcIndex->ProcessId); PsLookupProcessByProcessId(pProcIndex->ProcessId, Process); Process++; } } while (pProcIndex->NextEntryDelta != 0); *Process = NULL; } else { 
    DbgPrint("error code : %u!!!\n", nStatus); } ExFreePool(pProcInfo); return nStatus; } 
//================================================================== //函数名: PrintPrivateTable //功能: 遍历一个进程所有的句柄表项,并执行自定义的回调函数 //输入参数1:IN,pEprocess 指定要遍历的局部句柄表的进程EPROCESS //输入参数2:IN,func 自定义的回调函数 //返回值:null //注意:根据句柄表项找到内核对象的步骤 //Object = Entry->ObjectPointerBits; //Object <<= 4; //Object |= 0xFFFF000000000000; //Object += 0x30; //================================================================== void PrintPrivateTable(PEPROCESS pEprocess, PHANDLE_TABLE_ENTRY_FUNC func) { 
    POBJECT_TYPE pObjectType = NULL; PHANDLE_TABLE_ENTRY pHandleTableEntry = NULL; UINT64 pObject =0; ULONG_PTR Handle = 0; for (Handle = 0;; Handle += HANDLE_VALUE_INC) { 
    pHandleTableEntry = SearchHandleTableEntry(*(PHANDLE_TABLE*)((PUCHAR)pEprocess + HANDLE_TABLE_OFFSET), *(PEXHANDLE)&Handle); if ((PVOID)pHandleTableEntry == NULL) { 
    break; } pObject = pHandleTableEntry->ObjectPointerBits; pObject = pObject <<= 4; //DbgPrint("pObject=%p\n", pObject); if ((PVOID)pObject == NULL) { 
    continue; } pObject = pObject |= 0xFFFF000000000000; pObject = pObject + 0x30; pObjectType = ObGetObjectType((PVOID)pObject); if (pObjectType == NULL) { 
    continue; } //DbgPrint("pObjectType=%p\n", pObjectType); //DbgPrint("pObjectType=%ws\n", *(PCWSTR*)((PUCHAR)pObjectType + 0x18)); //do something ... if (func(pHandleTableEntry, (PVOID)pObject, pObjectType)) { 
    break; } /* if (Handle >= 0x20) break;*/ } DbgPrint("PHANDLE_TABLE_ENTRY打印结束,Handle=%x\n", Handle); } 
//================================================================== //函数名: SearchHandleTableEntry  //功能: 根据句柄索引搜索对应的句柄表项 //输入参数1:IN,pObjectTable ObjectTable表的地址 //输入参数2:IN,HandleIndex 句柄索引,13+9+10 //返回值:PHANDLE_TABLE_ENTRY,句柄表项 //================================================================== PHANDLE_TABLE_ENTRY SearchHandleTableEntry(PHANDLE_TABLE pObjectTable, EXHANDLE HandleIndex) { 
    UINT64 var_TableBase;//TableCode表 UINT64 var_TableLevel;//TableCode表的层数 UINT64 var_HandleIndex;//清0属性位之后的HandleIndex的值 UINT64 var_PageOffset;//表的偏移 UINT64 temp;//临时指针 //将HandleIndex的属性位清0 HandleIndex.TagBits = 0; var_HandleIndex = (UINT32)HandleIndex.Value; //超出最大索引值,说明该索引无效,返回NULL if (HandleIndex.Value >= pObjectTable->NextHandleNeedingPool) return NULL; //判断私有句柄表的层数 var_TableBase = pObjectTable->TableCode; //DbgPrint("var_TableBase=%p\n", var_TableBase); var_TableLevel = var_TableBase & 0x3; switch (var_TableLevel) { 
    //只有1层 case 0: var_PageOffset = var_HandleIndex; // 先除以4知道返回第几个HandleTableEntry,再乘以10得到HandleTableEntry的索引 temp = var_TableBase + (var_PageOffset / 0x4) * 0x10; return (PHANDLE_TABLE_ENTRY)temp; //有两层 case 1: //获取前一层表的偏移 var_PageOffset = (var_HandleIndex >> 10) ; //进入到后一层表 temp = *(PUINT64)((var_PageOffset * 8-1) + var_TableBase); //需要-1 //获取后一层表的偏移 var_PageOffset = var_HandleIndex & 0x3FF ; return (PHANDLE_TABLE_ENTRY)(temp + (var_PageOffset / 0x4) * 0x10); //有三层 case 2: //获取前一层表的偏移 var_PageOffset = (var_HandleIndex >> 19); //进入到中间那一层表 temp = *(PUINT64)((var_PageOffset * 8-2) + var_TableBase); //需要-2 //获取中间那层表的偏移 var_PageOffset = (var_HandleIndex >> 10) &0x1FF; //进入到后一层表 temp = *(PUINT64)(var_PageOffset * 8 + temp); //获取后一层表的偏移 var_PageOffset = var_HandleIndex & 0x3FF; return (PHANDLE_TABLE_ENTRY)(temp + (var_PageOffset / 0x4) * 0x10); default: return NULL; } } 
//================================================================== //函数名: KillMutex //功能: 杀死指定的互斥体,实现多开 //输入参数1:IN,pHandleTableEntry,句柄表项 //输入参数2:IN,pMutex,句柄表项指向的内核对象的body //输入参数3:IN,pObjectType,句柄表项指向的内核对象所属的OBJECT_TYPE的首地址 //返回值: //================================================================== BOOLEAN KillMutex(PHANDLE_TABLE_ENTRY pHandleTableEntry,PVOID pMutex, POBJECT_TYPE pObjectType) { 
    if (wcscmp(*(PCWSTR*)((PUCHAR)pObjectType + 0x18), L"Mutant") != 0) { 
    return FALSE; } //ObQueryNameInfo是通过对象获得对象可变对象头之一的HEADER_NAME_INFO头 PHEADER_NAME_INFO pHeaderNameInfo = ObQueryNameInfo(pMutex); if (pHeaderNameInfo==NULL) { 
    DbgPrint("ObQueryNameInfo调用失败\n"); return FALSE; } //DbgPrint("MutexName=%ws", pHeaderNameInfo->Name.Buffer); if (0 == wcscmp(pHeaderNameInfo->Name.Buffer, L"AAA")) { 
    //找到对应名字的对象,将其关闭 DbgPrint("MutexName=%ws", pHeaderNameInfo->Name.Buffer); //DbgPrint("PointCount=%d,pMutex-0x30", *(PINT64)((INT64)pMutex-0x30)); //DbgPrint("HandleCount=%d,pMutex-0x28", *(PINT64)((INT64)pMutex-0x28)); pHeaderNameInfo->Name.Buffer[0] = GetRandomNumber(); DbgPrint("MutexName=%ws", pHeaderNameInfo->Name.Buffer); *(PINT64)((INT64)pMutex - 0x30) = 0; *(PINT64)((INT64)pMutex - 0x28) = 0; pHandleTableEntry->HighValue = 0; pHandleTableEntry->LowValue = 0; return TRUE; } return FALSE; } 
//================================================================== //函数名:GetRandomNumber  //功能: 获取一个大小为8位的数字,使每次获取的数字不重复 //输入参数:void //返回值:CHAR 返回获取到的数字 //================================================================== CHAR GetRandomNumber() { 
    ULONG inc; LARGE_INTEGER CurrentTime; inc = KeQueryTimeIncrement(); KeQueryTickCount(&CurrentTime); CurrentTime.QuadPart *=inc; return (CHAR)CurrentTime.QuadPart; } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218687.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午11:41
下一篇 2026年3月17日 下午11:41


相关推荐

  • [Python3]pandas.merge用法详解

    [Python3]pandas.merge用法详解摘要数据分析与建模的时候大部分时间在数据准备上,包括对数据的加载、清理、转换以及重塑。pandas提供了一组高级的、灵活的、高效的核心函数,能够轻松的将数据规整化。这节主要对pandas合并数据集的merge函数进行详解。(用过SQL或其他关系型数据库的可能会对这个方法比较熟悉。)1.merge函数的参数一览表2.创建两个DataFrame3.pd.merge()方法设置连接字段。…

    2022年5月31日
    52
  • window 启动tomcat闪退 查看日志方法

    window 启动tomcat闪退 查看日志方法window启动tomcat闪退查看日志方法找到bin下面的startup.bat用文本方式打开找到末尾start改为run然后打开cmd窗口cd到tomcatbin路径执行startup.bat下图本来该报错会闪退,catalina日志文件也没记录该报错,导致我们看不到报错信息,设置后可清晰看到报错原因,端口号超出范围,改小就行了…

    2022年5月29日
    63
  • Hadoop官网查看手册

    Hadoop官网查看手册1 进入官网 http hadoop apache org 2 找到需要查看的 Hadoop 版本 或者接近版本 如安装的 Hadoop2 7 2 也可以查看 2 7 3 版本的手册 3 如需要查看以前版本 找到页面左下角 查找对应版本 或者相近的版本手册 如

    2026年3月18日
    2
  • Android中添加CallStack

    Android中添加CallStack1 Java 中添加 Java 中添加 callstack 常见以下几种方式 importandroi util Log 1 Exceptione newException thisisalog e printStackTr 2 Thread currentThrea getStackTrac 3 Log e dump test Log getStackTrac newThrowable 2

    2026年3月19日
    2
  • java中hashcode的用法_javahashcode作用

    java中hashcode的用法_javahashcode作用hashcode()是干什么用的?首先hashcode是哈希算法的一中简单实现,他是一个对象的哈希吗值。一般和equals一起使用。 hashcode也是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有 例如内存中有这样的位置 01234567 而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,

    2025年8月28日
    8
  • Java神操作之利用Mybatis的resultMap的id标签进行分组映射「建议收藏」

    Java神操作之利用Mybatis的resultMap的id标签进行分组映射「建议收藏」SQL<!–分组测试–><selectid=”test”resultMap=”test”>select*frommall_shoppingcartwherecompany_id=”companyIdTest”</select>resultMap<resultMaptype=”co…

    2025年8月9日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号