大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
ps 以下代码均在win10 X64下实现,其他系统不兼容
反调试
#include <windows.h>
# include<stdio.h>
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
详情
/// <summary>
/// 内核对象可变对象头之一,描述了一个内核对象的名称信息
/// </summary>
typedef struct _HEADER_NAME_INFO
{
PVOID Directory;
UNICODE_STRING Name;
INT32 ReferenceCount;
UINT32 Reserved;
} HEADER_NAME_INFO,* PHEADER_NAME_INFO;
/// <summary>
/// 句柄
/// </summary>
typedef struct _EXHANDLE
{
//32位
union
{
struct
{
ULONG TagBits : 2;
ULONG Index : 30;
};
HANDLE GenericHandleOverlay;
ULONG_PTR Value;
};
} EXHANDLE, * PEXHANDLE;
/// <summary>
/// 句柄表项
/// </summary>
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;
/// <summary>
/// _HANDLE_TABLE的成员之一
/// </summary>
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;
/// <summary>
/// EPROCESS的成员之一,描述了指向局部句柄表的相关信息,其中的TableCode指向局部句柄表
/// </summary>
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;
/// <summary>
/// 线程信息结构体,进程信息结构体的成员之一
/// </summary>
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;
/// <summary>
/// //进程信息结构体
/// </summary>
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;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185809.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...