首页 > 代码库 > SSDT表的遍历

SSDT表的遍历

//VS2005创建的工程,系统xp sp2

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//stdafx.h文件
#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.
#endif						

#ifdef __cplusplus
extern "C" 
{

#endif

#include <ntddk.h>
#include <ntddstor.h>
#include <mountdev.h>
#include <ntddvol.h>

//注意:全局变量要在这里定义

//系统服务描述符表-在ntoskrnl.exe中导出KeServiceDescriptorTable这个表
#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
	//System Service Dispatch Table的基地址
	PVOID ServiceTableBase;		 
	//SSDT中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。
	PVOID ServiceCounterTable; 
	//由 ServiceTableBase 描述的服务的数目。
	unsigned int NumberOfServices;  
	//每个系统服务参数字节数表的基地址-系统服务参数表SSPT 
	PVOID ParamTableBase; 
}*PServiceDescriptorTable;  
#pragma pack()

//导出系统服务描述符表SSDT的指针
extern  PServiceDescriptorTable  KeServiceDescriptorTable; 

#ifdef __cplusplus
}
#endif

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//ReadSsdtForFuntion.cpp文件
#include "stdafx.h"

//由SSDT索引号获取当前函数地址,如:  
//NtOpenProcess  [[KeServiceDescriptorTable]+0x7A*4]  

void ReadSsdtForFuntionUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS ReadSsdtForFuntionCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS ReadSsdtForFuntionDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

//1.纯汇编读取内核函数的地址
LONG GetFunctionAddr_ASM(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex);

//2.用指针读取内核函数的地址
LONG GetFunticonAddr(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex);


#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
	UNICODE_STRING DeviceName,Win32Device;
	PDEVICE_OBJECT DeviceObject = NULL;
	NTSTATUS status;
	unsigned i;

	//SSDT表的范围
	LONG lgSsdtNumber = -1;

	RtlInitUnicodeString(&DeviceName,L"\\Device\\ReadSsdtForFuntion0");
	RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\ReadSsdtForFuntion0");

	//设置默认处理例程
	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
		DriverObject->MajorFunction[i] = ReadSsdtForFuntionDefaultHandler;

	//设置创建例程
	DriverObject->MajorFunction[IRP_MJ_CREATE] = ReadSsdtForFuntionCreateClose;
	//设置关闭例程
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = ReadSsdtForFuntionCreateClose;
	
	//设置卸载例程
	DriverObject->DriverUnload = ReadSsdtForFuntionUnload;

	//创建设备对象
	status = IoCreateDevice(DriverObject,
							0,
							&DeviceName,
							FILE_DEVICE_UNKNOWN,
							0,
							FALSE,
							&DeviceObject);
	if (!NT_SUCCESS(status))
		return status;
	if (!DeviceObject)
		return STATUS_UNEXPECTED_IO_ERROR;

	DeviceObject->Flags |= DO_DIRECT_IO;
	DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;

	//创建符号连接
	status = IoCreateSymbolicLink(&Win32Device, &DeviceName);
	if (!NT_SUCCESS(status))
		return status;

	//初始化完成,可以工作了
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

	//设置测试断点
	__asm int 3

	//获取SSDT表的范围
	lgSsdtNumber = KeServiceDescriptorTable->NumberOfServices;

	//使用方法1.遍历SSDT
	KdPrint(("使用方法1.遍历SSDT\r\n"));
	for (i = 0; i < lgSsdtNumber; i++)
	{
		KdPrint(("Index:%04X--FunAddr:%08X\r\n", i, GetFunctionAddr_ASM(KeServiceDescriptorTable, i)));
	}

	//使用方法2.遍历SSDT
	KdPrint(("使用方法2.遍历SSDT\r\n"));
	for (i = 0; i < lgSsdtNumber; i++)
	{
		KdPrint(("Index:%04X--FunAddr:%08X\r\n", i, GetFunticonAddr(KeServiceDescriptorTable, i)));
	}

	return STATUS_SUCCESS;
}


//1.使用汇编的方法读取内核函数的地址
LONG GetFunctionAddr_ASM(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex)
{
	LONG lgSsdtFunAddr = 0;

	//lgSsdtFunAddr = [[KeServiceDescriptorTable]+lgSsdtIndex*4]
	__asm
	{    
		push ebx
		push eax
		mov ebx, KeServiceDescriptorTable
		mov ebx, [ebx]	//SSDT表的基地址
		mov eax, lgSsdtIndex
		shl eax, 2		
		add ebx, eax		
		mov ebx, [ebx]
		mov lgSsdtFunAddr, ebx
		pop  eax	
		pop  ebx
	}

	return lgSsdtFunAddr;
}

//2.使用指针的方法获取函数的地址
LONG GetFunticonAddr(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex)
{
	LONG lgSsdtAddr = 0;
	//获取SSDT表的基址
	lgSsdtAddr = (LONG)KeServiceDescriptorTable->ServiceTableBase;

	PLONG plgSsdtFunAddr = 0; 
	//获取内核函数的地址指针
	plgSsdtFunAddr = (PLONG)(lgSsdtAddr+lgSsdtIndex*4);

	//返回内核函数的地址
	return (*plgSsdtFunAddr);	
}


void ReadSsdtForFuntionUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING Win32Device;
	RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\ReadSsdtForFuntion0");
	IoDeleteSymbolicLink(&Win32Device);
	IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS ReadSsdtForFuntionCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS ReadSsdtForFuntionDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return Irp->IoStatus.Status;
}

//参考资料:
//郁金香老师讲课资料

SSDT表的遍历