SSDT表结构的深入学习
SSDT表的知识目录:
A、了解SSDT结构
B、由SSDT索引号获取当前函数地址
C、如何获取索引号
D、获取起源地址-判断SSDT是否被HOOK
E、如何向内核地址写入自己代码
A、了解SSDT结构
SSDT的全称是 System ServicesDescriptor Table--系统服务描述符表,是由 ntoskrnl.exe导出KeServiceDescriptorTable 这个表,是全局的,声明导出即可在编程中使用。
typedef struct ServiceDescriptorEntry
{
unsigned int *ServiceTableBase; //SystemService Dispatch Table 的基地址
unsigned int *ServiceCounterTable(0);
//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由 sysenter 更新。
unsigned int NumberOfServices; //由 ServiceTableBase描述的服务的数目。
unsigned char *ParamTableBase;
//包含每个系统服务参数字节数表的基地址-系统服务参数表
} SSDT_Entry;
用windbg 了解SSDT结构,命令:
dp nt!KeServiceDescriptorTable
B、由SSDT索引号获取当前函数地址
[[KeServiceDescriptorTable基址] + index*4]
C、如何获取SSDT索引号
用工具查看如:狙剑、火眼等
D、获取起源地址-判断SSDT是否被HOOK
MmGetSystemRoutineAddress函数,得到系统导出函数的地址
包含头文件Wdm.h 或Ntddk.h
//NTKERNELAPI
PVOID
MmGetSystemRoutineAddress (
__in PUNICODE_STRING SystemRoutineName
)
/*++
Routine Description:
This functionreturns the address of the argument function pointer if
it is in the kernelor HAL, NULL if it is not.
Arguments:
SystemRoutineName -Supplies the name of the desired routine.
Return Value:
Non-NULL functionpointer if successful. NULL if not.
Environment:
Kernel mode,PASSIVE_LEVEL, arbitrary process context.
--*/
{
PKTHREADCurrentThread;
NTSTATUS Status;
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
ANSI_STRINGAnsiString;
PLIST_ENTRYNextEntry;
UNICODE_STRINGKernelString;
UNICODE_STRINGHalString;
PVOIDFunctionAddress;
LOGICAL Found;
ULONGEntriesChecked;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
EntriesChecked = 0;
FunctionAddress =NULL;
KernelString.Buffer= (const PUSHORT) KERNEL_NAME;
KernelString.Length= sizeof (KERNEL_NAME) - sizeof (WCHAR);
KernelString.MaximumLength = sizeof KERNEL_NAME;
HalString.Buffer =(const PUSHORT) HAL_NAME;
HalString.Length =sizeof (HAL_NAME) - sizeof (WCHAR);
HalString.MaximumLength = sizeof HAL_NAME;
do {
Status =RtlUnicodeStringToAnsiString (&AnsiString,
SystemRoutineName,
TRUE);
if (NT_SUCCESS(Status)) {
break;
}
KeDelayExecutionThread (KernelMode, FALSE,(PLARGE_INTEGER)&MmShortTime);
} while (TRUE);
//
// Arbitraryprocess context so prevent suspend APCs now.
//
CurrentThread =KeGetCurrentThread ();
KeEnterCriticalRegionThread(CurrentThread);
ExAcquireResourceSharedLite (&PsLoadedModuleResource, TRUE);
//
// Check only thekernel and the HAL for exports.
//
NextEntry =PsLoadedModuleList.Flink;
while (NextEntry !=&PsLoadedModuleList) {
Found = FALSE;
DataTableEntry= CONTAINING_RECORD(NextEntry,
KLDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
if (RtlEqualUnicodeString(&KernelString,
&DataTableEntry->BaseDllName,
TRUE)) {
Found =TRUE;
EntriesChecked += 1;
}
else if(RtlEqualUnicodeString (&HalString,
&DataTableEntry->BaseDllName,
TRUE)){
Found =TRUE;
EntriesChecked += 1;
}
if (Found ==TRUE) {
FunctionAddress = MiFindExportedRoutineByName(DataTableEntry->DllBase,
&AnsiString);
if(FunctionAddress != NULL) {
break;
}
if (EntriesChecked== 2) {
break;
}
}
NextEntry =NextEntry->Flink;
}
ExReleaseResourceLite (&PsLoadedModuleResource);
KeLeaveCriticalRegionThread (CurrentThread);
RtlFreeAnsiString(&AnsiString);
returnFunctionAddress;
}
//WRK中的源码
E、如何向内核地址写入自己代码
在后期版本的操作系统中,要求SSDT是只读的,因此任何合法的程序都不可能修改这个表,不过聪明的大牛们还是想出了修改SSDT表的方法。
方法一:更改注册表(需要重启)
HKLM\SYSTEM\CurrentControlset\Control\SessionManger\MemoryManagement\EnforceWriteProtection= 0
与
HKLM\SYSTEM\CurrentControlset\Control\SessionManger\MemoryManagement\DisablePagingExecutive= 1
方法二:修改CR0寄存器的第1位即wp位置0
//关闭内存保护
_asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
//恢复内存保护
_asm
{
push eax
mov eax, CR0
or eax , not 0FFFEFFFFh
mov CR0, eax
pop eax
}
方法三:利用MDL(Memory Descriptor List)来绕过写保护
//MDL reference defined inntddk.h
typedef struct _MDL{
Struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
Struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
}MDL,*PMDL;
//MDL Flags
#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
#define MDL_PAGES_LOCKED 0x0002
#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
#define MDL_ALLOCATED_FIXED_SIZE 0x0008
#define MDL_PARTIAL 0x0010
#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
#define MDL_IO_PAGE_READ 0x0040
#define MDL_WRITE_OPERATION 0x0080
#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
#define MDL_LOCK_HELD 0x0200
#define MDL_PHYSICAL_VIEW 0x0400
#define MDL_IO_SPACE 0x0800
#define MDL_NETWORK_HEADER 0x1000
#define MDL_MAPPING_CAN_FAIL 0x2000
#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
//声明
#pragma pack(1)
typedef struct ServiceDescriptorEntry{
unsigned int* ServiceTableBase;
unsigned int* ServiceCounterTableBase;
unsigned int NumberOfService;
unsigned char* ParamTableBase;
}SSDT_Entry;
#pragma pack()
//导出SSDT表
_declspec(dllimport)SSDT_Entry KeServiceDescriptorTable;
//保存原始的系统调用地址
PMDL g_pmdlSystemCall;
PVOID *MappedSystemCallTable;
//创建MDL
g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable, ServiceTableBase, KeServcieDescriptorTable.NumberOfService*4);
if(!g_pmdlSystemCall)
{
return STATUS_UNSUCCESSFUL;
}
//构建非分页内存
MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
//改变MDL的标志
g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA ;
//锁定内存
MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
参考资料:
《Windows内核的安全防护》推荐
http://blog.csdn.net/evi10r/article/details/6840564
SSDT表结构的深入学习的更多相关文章
- VSTO学习笔记(八)向 Word 2010 中写入表结构
原文:VSTO学习笔记(八)向 Word 2010 中写入表结构 前几天公司在做CMMI 3级认证,需要提交一系列的Word文档,其中有一种文档要求添加公司几个系统的数据库中的表结构.我临时接到了这项 ...
- Activiti学习(二)数据表结构
Activiti工作流引擎数据库表结构 数据库表的命名 Acitiviti数据库中表的命名都是以ACT_开头的.第二部分是一个两个字符用例表的标识.此用例大体与服务API是匹配的. l ...
- Oracle 学习系列之一(表空间与表结构)
create tablespace user3 datafile 'e:\test\user3_data.dbf' size 20M --表空间初始大小为: 20Mautoextend on next ...
- oracle 学习笔记 复制表结构
1.复制表结构以及数据 create table d_table_name as select * from s_table_name; ---注意并不会创建索引 2.只复制表结构 create t ...
- SQL server学习(二)表结构操作、SQL函数、高级查询
数据库查询的基本格式为: select ----输出(显示)你要查询出来的值 from -----查询的依据 where -----筛选条件(对依据(数据库中存在的表)) group by ----- ...
- Spring batch学习 持久化表结构详解(2)
#接上一篇 这一篇讲一下持久化需要表 batch_job_execution, batch_job_execution_context, batch_job_execution_params, bat ...
- hive学习5(复制表结构)
hive复制表结构 CREATE TABLE new_table LIKE old_table; 例:创建一个和stg_job表一样表结构的s_job表 create table s_job like ...
- Mysql学习—查看表结构、修改和删除数据表
原文出自:http://blog.csdn.net/junjieguo/article/details/7668775 查看表结构 查看表结构可以用语句DESCRIBE或SHOW CREATE TAB ...
- android 基础学习(6)-----sqlite3查看表结构
原文:http://blog.csdn.net/richnaly/article/details/7831933 sqlite3查看表结构 在android下通过adb shell命令可以进入sqli ...
随机推荐
- Linux 虚拟文件系统四大对象:超级块、inode、dentry、file之间关系
更多嵌入式原创文章,请关注公众号:一口Linux 一:文件系统 1. 什么是文件系统? 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 通常文件系统是用于存储和组织文件的一 ...
- 有钱人买钻石+dfs中使用贪心
有钱人买钻石 ECNU-3306 题解:这个题目,乍一看以为是dp背包,可是数据量却那么大,只有1,5,10,25四种面额的硬币,每种数量若干,要使得能够刚好兑换成功总金额,在此前提下,还要使得硬币数 ...
- 设计模式之建造者模式(BuilderPattern)
一.意义 将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 说明:复杂对象的构建,比如一个对象有几十个成员属性,那么我们在创建这个对象,并给成员属性赋值时,就会很麻烦.采用 ...
- WorkSkill整理之 java用Scanner 类输入数组并打印
输入不确定长度的数组 import java.util.*; public static void main(String[] args){ System.out.println("请输入一 ...
- FZU_1608 Huge Mission 【线段树区间更新】
一.题目 Huge Mission 二.分析 区间更新,用线段树的懒标记即可.需要注意的时,由于是在最后才查询的,没有必要每次更新都对$sum$进行求和.还有一点就是初始化的问题,一定记得线段树上每个 ...
- python tempfile 创建临时目录
一.tempfile介绍 该模块创建临时文件和目录.它适用于所有支持的平台.TemporaryFile,NamedTemporaryFile,TemporaryDirectory,和SpooledTe ...
- 一种借助POI粗略的标注城市也许重要的区域的方法
第一部分 很久以前,我住在村子里,因为村子小,所以对村子的一草一木都很熟悉,在熟悉的环境里就很有安全感. 后来我到了大城市,却发现城市太大了,一辈子都熟悉不完. 这个城市的绝大部分地方我都没有去过,就 ...
- [系统重装日志1]快速迁移/恢复Mendeley的文献和笔记
一时手贱把原先系统的EFI分区给删了,按照网上的教程还没有恢复成功,无奈之下只能重装系统,想想这么多环境和配置真是酸爽. 身为一个伪科研工作者,首先想到的是自己的文献和阅读笔记.我所使用的文献管理工具 ...
- linux程序开机自动启动
linux如果需要实现开机启动, 可以找到 $HOME/.config/autostart 目录(没有的话新建一个),在该文件夹下创建一个空文件,文件名自拟,后缀必须是desktop,如:dingda ...
- LinkedList源码个人解读
LinkedList的基本结构是双向链接的直线结构. 链表的构造函数有两个,其中空构造函数什么都没做,就是一个空实现. /** * Constructs an empty list. */ publi ...