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表的遍历的更多相关文章
- SSDT表概念具体解释
		SSDT 的全称是 System Services Descriptor Table,系统服务描写叙述符表. 这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系 ... 
- SSDT表概念详解
		SSDT 的全称是 System Services Descriptor Table,系统服务描述符表. 这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来 ... 
- Lua 多维表的遍历中的赋值
		说到Lua的遍历将要使用到循环:先说遍历再说循环: 遇到这样类似结构的一个table Data={ []={p1=,pa={,,}}, []={p1=,pa={,,}}, []={p1=,pa={,, ... 
- SSDT表详解
		SSDT(system service dispatch table) 系统服务分派表 SSPT(system service parameter table) 系统服务参数表 #pragma pac ... 
- 内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式.
		内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式. 一丶IDT解析. 我们知道.IDT表中存放着各种中断信息.比如当我们调用int 3的时候,则会调用IDT表中的第三项来进行调用. 而函数 ... 
- 64位内核开发第四讲,查看SSDT表与showSSDT表
		目录 SSDt表与ShadowSSDT表的查看. 一丶SSDT表 1.什么是SSDT表 2.查看步骤 二丶ShadowSSDT表 1.什么是ShadowSSDT表 2.如何查看. 三丶工具介绍 SSD ... 
- SSDT表函数Hook原理
		其实 SSDT Hook 的原理是很简单的,我们可以知道在 SSDT 这个数组中呢,保存了系统服务的地址,比如对于 Ring0 下的 NtQuerySystemInformation 这个系统服务的地 ... 
- SSDT表结构的深入学习
		SSDT表的知识目录: A.了解SSDT结构 B.由SSDT索引号获取当前函数地址 C.如何获取索引号 D.获取起源地址-判断SSDT是否被HOOK E.如何向内核地址写入自己代码 A. ... 
- 驱动开发:Win10内核枚举SSDT表基址
		三年前面朝黄土背朝天的我,写了一篇如何在Windows 7系统下枚举内核SSDT表的文章<驱动开发:内核读取SSDT表基址>三年过去了我还是个单身狗,开个玩笑,微软的Windows 10系 ... 
随机推荐
- 用go实现常见的数据结构
			目录 1 golang常见数据结构实现 1.1 链表 1.2 可变数组 1.3 栈和队列 1.3.1 原生切片实现栈和队列 1.3.1.1 切片原生栈实现 1.3.1.2 切片原生队列实现 1.3.2 ... 
- LeetCode-二叉搜索树的范围和
			二叉搜索树的范围和 LeetCode-938 首先需要仔细理解题目的意思:找出所有节点值在L和R之间的数的和. 这里采用递归来完成,主要需要注意二叉搜索树的性质. /** * 给定二叉搜索树的根结点 ... 
- Spark性能调优-RDD算子调优篇(深度好文,面试常问,建议收藏)
			RDD算子调优 不废话,直接进入正题! 1. RDD复用 在对RDD进行算子时,要避免相同的算子和计算逻辑之下对RDD进行重复的计算,如下图所示: 对上图中的RDD计算架构进行修改,得到如下图所示的优 ... 
- 确保某个BeanDefinitionRegistryPostProcessor Bean被最后执行的几种实现方式
			目录 一.事出有因 二.解决方案困境 三.柳暗花明,终级解决方案 第一种实现方案 第二种实现方案 第三种实现方案 四.引发的思考 一.事出有因  最近有一个场景,因同一个项目中不同JAR包依赖同一个 ... 
- WPF 基础 - x 名称空间详解
			名称 种类(默认Attribute) 备注 x:Array 标记拓展 可作为 ListBox.ItemsSource 的值 x:Class 指定与 .cs 中哪个类合并,所指示的类型在声明时使用 pa ... 
- Windows搭建flutter开发环境以及android&idea配置
			Flutter:是谷歌新推出的一款能够支持Android和IOS跨平台开发的全新的UI框架. 拥有自己的一套UI渲染引擎,所以目前的测试数据来看,在性能上面,并没有比原生App性能低多少,所以目前来看 ... 
- 2020年Acm暑期考核Hznu _2797
			题目链接:http://acm.hznu.edu.cn/OJ/problem.php?id=2797 题意:求1-N中有多少数字满足: x是正整数且无前导0. x(mod 666) = S(x). 6 ... 
- Java 操作PPT数字签名(一):添加、检测、删除签名
			本文简要概述如何通过Java程序来处理PPT中的数字签名,文章主要分三个部分来介绍,即数字签名的添加.验证以及删除. 基本操作思路: 1. 添加签名:[加载PPT文档]→[添加签名]→[保存文档] 2 ... 
- Linux内核源码分析之setup_arch (四)
			前言 Linux内核源码分析之setup_arch (三) 基本上把setup_arch主要的函数都分析了,由于距离上一篇时间比较久了,所以这里重新贴一下大致的流程图,本文主要分析的是bootmem_ ... 
- 配置docker的pdflatex环境
			技术背景 Latex在文档撰写方面是不可或缺的工具,尤其是在写文章方面,是必须要用到的文字排版工具.但是latex的环境部署并不是一个特别人性化的操作,尤其是在各种不同的平台上操作是完全不一样的,还经 ... 
