#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
