⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 restoreshadow.c

📁 Ring0下恢复SSDT Shadow。
💻 C
字号:
/*
RestoreShadow.C
Author: <your name>
Last Updated: 2007-07-06

This framework is generated by EasySYS 0.3.0 Modify
This template file is copying from QuickSYS 0.3.0 written by Chunhua Liu
//=============================================
Modified by PLK_XiaoWei[0GiNr]
http://www.0GiNr.com
//=============================================
*/
#include <ntddk.h>
#include "RestoreShadow.h"
#include "dbghelp.h"
#include "LDasm.h"

NTKERNELAPI
NTSTATUS
KeAddSystemServiceTable(
			IN PULONG_PTR Base,
			IN PULONG Count OPTIONAL,
			IN ULONG Limit,
			IN PUCHAR Number,
			IN ULONG Index
			);

typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
	PULONG_PTR	Base;
	PULONG	Count;
	ULONG	Limit;
	PUCHAR	Number;
}
KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;

typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	USHORT LoadCount;
	USHORT TlsIndex;
	union {
		LIST_ENTRY HashLinks;
		struct
		{
			PVOID SectionPointer;
			ULONG CheckSum;
		};
	};
	union {
		struct
		{
			ULONG TimeDateStamp;
		};
		struct
		{
			PVOID LoadedImports;
		};
	};
	struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
	PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;



PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow = NULL;

PVOID	pWin32kBase = NULL;

//===========================================
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObj);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DispatchCreate)
#pragma alloc_text(PAGE, DispatchClose)
#pragma alloc_text(PAGE, DriverUnload)
#endif // ALLOC_PRAGMA 
//////////////////////////////////////////////////////////////////////////
VOID GetWin32kBase(PDRIVER_OBJECT pDriverObj);
VOID GetSSDTShadowBase();
NTSTATUS RestoreShadow();
ULONG RVAToRaw(PVOID lpBase,ULONG VirtualAddress);
//==========================================
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING ustrLinkName;
	UNICODE_STRING ustrDevName;
	PDEVICE_OBJECT pDevObj;

	dprintf("DriverEntry: %S\n", pRegistryString->Buffer);

	// Create dispatch points for device control, create, close.
	pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	pDriverObj->DriverUnload = DriverUnload;
	//

	RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);

	status = IoCreateDevice(pDriverObj,
		0,
		&ustrDevName,
		FILE_DEVICE_UNKNOWN,
		0,
		FALSE,
		&pDevObj);

	dprintf("Device Name %S", ustrDevName.Buffer);

	if (!NT_SUCCESS(status))
	{
		dprintf("IoCreateDevice = 0x%x\n", status);
		return status;
	}


	RtlInitUnicodeString(&ustrLinkName, LINK_NAME);

	status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
	if (!NT_SUCCESS(status))
	{
		dprintf("IoCreateSymbolicLink = 0x%x\n", status);
		IoDeleteDevice(pDevObj);
		return status;
	}

	dprintf("SymbolicLink:%S", ustrLinkName.Buffer);

	GetWin32kBase(pDriverObj);
	GetSSDTShadowBase();
	dprintf("Win32k Base : 0x%X",pWin32kBase);
	dprintf("KeServiceDescriptorTableShadow : 0x%X", KeServiceDescriptorTableShadow);

	return STATUS_SUCCESS;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
	UNICODE_STRING strLink;
	RtlInitUnicodeString(&strLink, LINK_NAME);
	//
	// Delete the symbolic link
	//
	IoDeleteSymbolicLink(&strLink);
	//
	// Delete the device object
	//
	IoDeleteDevice(pDriverObj->DeviceObject);
	dprintf("Unloaded\n");
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	RestoreShadow();
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	dprintf("IRP_MJ_CREATE\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	dprintf("IRP_MJ_CLOSE\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}


VOID GetSSDTShadowBase()
{
	UCHAR *cPtr;
	UCHAR *pOpcode;
	ULONG Length;
	for (cPtr = (PUCHAR)KeAddSystemServiceTable;
		cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;
		cPtr += Length)
	{
		Length = SizeOfCode(cPtr, &pOpcode);

		if (!Length) break;

		if ( *(PUSHORT)cPtr == 0x888D )
		{
			KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR)(*(ULONG *)((ULONG)pOpcode + 2));
			break;
		}
	}
}

VOID GetWin32kBase(PDRIVER_OBJECT pDriverObj)
{
	PLIST_ENTRY pList = NULL;
	PLDR_DATA_TABLE_ENTRY Ldr = NULL;
	pList = ( (PLIST_ENTRY)pDriverObj->DriverSection )->Flink;
	do {
		Ldr = CONTAINING_RECORD(
			pList,
			LDR_DATA_TABLE_ENTRY,
			InLoadOrderLinks);
		if (Ldr->EntryPoint &&
			Ldr->FullDllName.Buffer) {
				if ( !_wcsicmp(Ldr->FullDllName.Buffer, L"\\systemroot\\system32\\win32k.sys") ) {
					//比较模块名字,应该比较FullDllName,单单比较BaseDllName很可能会遇到同名文件。
					pWin32kBase = Ldr->DllBase;//保存模块基址
					break;
				}
		}
		pList = pList->Flink;//下一个链表
	} while ( pList != ((LIST_ENTRY*)pDriverObj->DriverSection)->Flink );
}


NTSTATUS RestoreShadow()
{
	NTSTATUS status;
	HANDLE hFile;//文件句柄
	OBJECT_ATTRIBUTES ObjAttr;
	UNICODE_STRING ustrWin32k;
	IO_STATUS_BLOCK ioStatus;
	ULONG ulShadowRaw = 0;
	ULONG ulShadowBase = 0;
	PVOID PoolArea = NULL;
	FILE_POSITION_INFORMATION fpi;
	LARGE_INTEGER Offset;
	ULONG OrigAddress = 0;
	ULONG CurAddress = 0;
	ULONG i = 0;
	ULONG ulCount = 0;
	PULONG pAddr;

	if ( pWin32kBase == NULL ||
		KeServiceDescriptorTableShadow == NULL)
	{
		dprintf("Error.");
		return STATUS_UNSUCCESSFUL;
	}

	ulCount = KeServiceDescriptorTableShadow[1].Limit;//Linit就是表中函数的个数

	dprintf("Count Of Shadow : %d\n", ulCount );

	ulShadowBase = *(ULONG*)&KeServiceDescriptorTableShadow[1].Base;//得到基址

	dprintf("ulShadowBase = 0x%X\n",ulShadowBase);

	ulShadowRaw = ulShadowBase - (ULONG)pWin32kBase;
	//ulShadowRaw = RVAToRaw(pWin32kBase,ulShadowBase);

	dprintf("ulShadowRaw = 0x%X\n",ulShadowRaw);

	RtlInitUnicodeString(&ustrWin32k, L"\\SystemRoot\\System32\\win32k.sys");

	PoolArea = ExAllocatePool( PagedPool, sizeof(ULONG) * ulCount );
	//分配空间,用于保存读取到的数据,因为每个地址的长度sizeof(ULONG),个数是ulCount,所以相乘

	if (!PoolArea) {
		dprintf("PoolArea is null\n");
		return STATUS_UNSUCCESSFUL;
	}

	RtlZeroMemory(&ObjAttr, sizeof(ObjAttr) );

	InitializeObjectAttributes(
		&ObjAttr,
		&ustrWin32k,
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
		NULL,
		NULL);
	//打开文件
	status = IoCreateFile(
		&hFile,
		FILE_READ_ATTRIBUTES,
		&ObjAttr,
		&ioStatus,
		0,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		0,
		NULL,
		0,
		0,
		NULL,
		IO_NO_PARAMETER_CHECKING);

	if ( !NT_SUCCESS(status) ) {
		dprintf("IoCreateFile Error : 0x%X", status);
		goto __exit;
	}

	//设置文件偏移
	Offset.LowPart = ulShadowRaw;
	Offset.HighPart = 0;
	//开始读取数据
	status = ZwReadFile (
		hFile,
		NULL,
		NULL,
		NULL,
		&ioStatus,
		PoolArea,
		ulCount*sizeof(ULONG),
		&Offset,
		NULL);

	if ( !NT_SUCCESS(status) ) {
		dprintf("ZwReadFile Error : 0x%X");
		goto __exit;
	}

	pAddr = (PULONG)PoolArea;
	//比较原始地址与当前的地址并且输出调试
	for (i=0;i<ulCount;i++) {
		OrigAddress = *pAddr;//指向原始地址
		CurAddress = KeServiceDescriptorTableShadow[1].Base[i];//读取当前地址
		if ( OrigAddress != CurAddress ) {
			dprintf("ID:%-3d.OrigAddr : 0x%X CurAddr : 0x%X---Hooked!\n",i,OrigAddress,CurAddress);
		} else {
			dprintf("ID:%-3d.OrigAddr : 0x%X.CurAddr : 0x%X\n",i,OrigAddress,CurAddress);
		}
		pAddr++;//指针指向下一个函数
	}

__exit:
	if (PoolArea) {
		ExFreePool(PoolArea);
		//释放空间
	}
	if (hFile) {
		ZwClose(hFile);
		//关闭句柄
	}
	return status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -