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的环境部署并不是一个特别人性化的操作,尤其是在各种不同的平台上操作是完全不一样的,还经 ...