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;
}

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

本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征码搜索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT函数原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代码实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值