欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]枚举系统全局原子表

[原创]枚举系统全局原子表

之前写着玩的一个小DEMO, 能枚举或者监控系统全局原子信息
对于系统资源的枚举常规方式一般是设法得到该资源的链表头或者数组首地址等等
这可以通过在代码中搜索或者将自身加入到资源列表中而进一步定位到它
这次枚举原子表的实验中我是通过HOOK方式来进行的, 因为内核的导出函数RtlAddAtomToAtomTable中直接引用了原子表的首地址


NTSYSAPI

NTSTATUS

NTAPI

RtlAddAtomToAtomTable(

    __in PVOID AtomTableHandle,

    __in PWSTR AtomName,

    __inout_opt PRTL_ATOM Atom

    );


这样只要勾住这个函数, 等该函数被调用时就能得到原子表地址了进而将它的元素表都枚举出来
实际操作中我目前只发现了两个系统级原子表, 一个是常规的原子表, 由GlobalAddAtom可以触发RtlAddAtomToAtomTable的调用,
另一个是与窗口有关的原子表, 由RegisterWindowMessage可以触发RtlAddAtomToAtomTable的调用
在进行枚举操作时, 我就是先勾住RtlAddAtomToAtomTable, 再在应用层调用这两个函数来进行的
很幸运的是在内核中记录原子表及其原子表项的内部结构在XP和WIN7下是一样的

typedef struct _RTL_ATOM_TABLE_ENTRY{

	struct _RTL_ATOM_TABLE_ENTRY *HashLink;

	USHORT		HandleIndex;

	USHORT		Atom;

	USHORT		ReferenceCount;

	UCHAR		Flags;

	UCHAR		NameLength;

	WCHAR		Name[1];

}RTL_ATOM_TABLE_ENTRY, *PRTL_ATOM_TABLE_ENTRY;

typedef struct _RTL_ATOM_TABLE{

	DWORD		Signature;

	//DWORD		FillA[6];		// +0x04	// CriticalSection

	//DWORD		FillB[8];		// +0x1C	// RtlHandleTable

	DWORD		FillA;

	DWORD		FillB;

	DWORD		NumberOfBuckets;// +0x3C

	PRTL_ATOM_TABLE_ENTRY Buckets[1];

}RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;


NumberOfBuckets描述了有多少个Buckets入口点, 每个Buckets链的最后一项为NULL, 这样就很方便遍历了

BOOLEAN IsAtomTableExist(__in DWORD TableAddress)

{

	if ( TableAddress == 0 ) return TRUE;

	for ( DWORD i = 0; i < 100; i++ )

	{

		DWORD ThisTable = g_AtomTables[i];

		if ( ThisTable == TableAddress )

		{

			return TRUE;

		}

		if ( ThisTable == 0 )

		{

			g_AtomTables[i] = TableAddress;

			return FALSE;

		}

	}

	return TRUE;

}

VOID EnumAtomTableEntrys(__in DWORD TableAddress)

{

	PRTL_ATOM_TABLE TableInfo = (PRTL_ATOM_TABLE)TableAddress;

	DWORD dw = TableInfo->NumberOfBuckets;

	for ( DWORD i = 0; i < dw; i++ )

	{

		PRTL_ATOM_TABLE_ENTRY Entry = (PRTL_ATOM_TABLE_ENTRY)TableInfo->Buckets[i];

		while ( Entry )

		{

			// 回传数据

			PATOMDATAINFO DataEntry = (PATOMDATAINFO)ExAllocatePoolWithTag(PagedPool, sizeof(AtomDataInfo), 'fff');

			RtlZeroMemory(DataEntry, sizeof(AtomDataInfo));

			DataEntry->AtomValue = (DWORD)Entry->Atom;

			DataEntry->ReferenceCount = (DWORD)Entry->ReferenceCount;

			DataEntry->TableAddress = TableAddress;

			DataEntry->TotalBuckets = TableInfo->NumberOfBuckets;

			DWORD len = (DWORD)Entry->NameLength * sizeof(WCHAR);

			if ( len > sizeof(DataEntry->AtomName) - sizeof(WCHAR) ) len = sizeof(DataEntry->AtomName) - sizeof(WCHAR);

			RtlMoveMemory(DataEntry->AtomName, Entry->Name, len);

			ExAcquireFastMutex(&g_EnumDataListFM);

			InsertTailList(&g_EnumDataList, &DataEntry->DataList);

			ExReleaseFastMutex(&g_EnumDataListFM);

			if ( Entry->HashLink == NULL ) break;

			Entry = Entry->HashLink;

		}

	}

}

BOOLEAN __stdcall AddAtomFilter(__in PVOID AtomTableHandle, __in PWCHAR AtomName, __inout_opt PUSHORT Atom)

{

	// 监控

	if ( g_DriverState.ControlMask & CONTROL_MASK_MONITOR )

	{

		// 回传数据

		PATOMDATAINFO Entry = (PATOMDATAINFO)ExAllocatePoolWithTag(PagedPool, sizeof(AtomDataInfo), 'ddd');

		if ( Entry )

		{

			RtlZeroMemory(Entry, sizeof(AtomDataInfo));

			Entry->ProcId = (DWORD)PsGetCurrentProcessId();

			PEPROCESS eprocess = PsGetCurrentProcess();

			PUCHAR pc = PsGetProcessImageFileName(eprocess);

			RtlMoveMemory(Entry->ProcName, pc, 16);

			DWORD		len = 0;

			RtlStringCbLengthW(AtomName, sizeof(Entry->AtomName) * sizeof(WCHAR), (size_t *)&len);

			RtlMoveMemory(Entry->AtomName, AtomName, len);

			Entry->TableAddress = (DWORD)AtomTableHandle;

			ExAcquireFastMutex(&g_MonDataListFM);

			InsertTailList(&g_MonDataList, &Entry->DataList);

			ExReleaseFastMutex(&g_MonDataListFM);

			if ( g_DriverState.EventForMon )

				KeSetEvent(g_DriverState.EventForMon, 0, FALSE);

		}

	}

	// 枚举

	if ( g_DriverState.ControlMask & CONTROL_MASK_ENUM )

	{

		if ( !IsAtomTableExist((DWORD)AtomTableHandle) )

		{

			EnumAtomTableEntrys((DWORD)AtomTableHandle);

			if ( g_DriverState.EventForEnum )

				KeSetEvent(g_DriverState.EventForEnum, 0, FALSE);

		}

	}

	return TRUE;

}


程序只在XP WIN7下运行过, 其他系统请慎用
WIN7下运行请使用管理员权限运行
loadatomenum.rar

上传的附件 loadatomenum.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功