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表结构的深入学习的更多相关文章

  1. VSTO学习笔记(八)向 Word 2010 中写入表结构

    原文:VSTO学习笔记(八)向 Word 2010 中写入表结构 前几天公司在做CMMI 3级认证,需要提交一系列的Word文档,其中有一种文档要求添加公司几个系统的数据库中的表结构.我临时接到了这项 ...

  2. Activiti学习(二)数据表结构

    Activiti工作流引擎数据库表结构 数据库表的命名 Acitiviti数据库中表的命名都是以ACT_开头的.第二部分是一个两个字符用例表的标识.此用例大体与服务API是匹配的. l        ...

  3. Oracle 学习系列之一(表空间与表结构)

    create tablespace user3 datafile 'e:\test\user3_data.dbf' size 20M --表空间初始大小为: 20Mautoextend on next ...

  4. oracle 学习笔记 复制表结构

    1.复制表结构以及数据 create table d_table_name as select * from s_table_name;  ---注意并不会创建索引 2.只复制表结构 create t ...

  5. SQL server学习(二)表结构操作、SQL函数、高级查询

    数据库查询的基本格式为: select ----输出(显示)你要查询出来的值 from -----查询的依据 where -----筛选条件(对依据(数据库中存在的表)) group by ----- ...

  6. Spring batch学习 持久化表结构详解(2)

    #接上一篇 这一篇讲一下持久化需要表 batch_job_execution, batch_job_execution_context, batch_job_execution_params, bat ...

  7. hive学习5(复制表结构)

    hive复制表结构 CREATE TABLE new_table LIKE old_table; 例:创建一个和stg_job表一样表结构的s_job表 create table s_job like ...

  8. Mysql学习—查看表结构、修改和删除数据表

    原文出自:http://blog.csdn.net/junjieguo/article/details/7668775 查看表结构 查看表结构可以用语句DESCRIBE或SHOW CREATE TAB ...

  9. android 基础学习(6)-----sqlite3查看表结构

    原文:http://blog.csdn.net/richnaly/article/details/7831933 sqlite3查看表结构 在android下通过adb shell命令可以进入sqli ...

随机推荐

  1. CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

    除法 201709-5 这道题有很多种方法来做,最常用的就是线段树和树状数组. 如果使用线段树来做,就会想到区间修改的update函数.但是这里可能会涉及到v是1或者a[j]是0的情况,所以用这种方法 ...

  2. C# smtp邮件发送

    第一种方式发送邮件,不读取配置文件发送邮件,(本地测试可以,但是服务器上不行) /// <summary> /// 发送邮件 /// </summary> /// <pa ...

  3. pytorch(09)transform模块(基础)

    transforms transforms运行机制 torchvision.transforms:常用的图像预处理方法 torchvision.datasets:常用数据及的dataset实现,mni ...

  4. 使用jsoup十分钟内掌握爬虫技术

    对,就是十分钟,没有接触过爬虫的你,肯定一脸懵逼,感觉好高深的样子,一开始我也有点懵,但用了以后发现还是很简单的,java爬虫框架有很多,让我有种选择困难症,通过权衡比较还是感觉jsoup比较好用些, ...

  5. Codeforces1493D GCD of an Array

    题目链接 点我跳转 题目大意 给定一个长度为 \(N\) 的序列 \(A\) 有 \(Q\) 次操作,每次操作给定两个数 \(i\) , \(X\),使得 \(A[i] = A[i] \times X ...

  6. 漏洞复现-CVE-2018-15473-ssh用户枚举漏洞

          0x00 实验环境 攻击机:Win 10 0x01 影响版本 OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机 0x02 漏洞复现 针 ...

  7. Node.js 模块化你所需要知道的事

    一.前言 我们知道,Node.js是基于CommonJS规范进行模块化管理的,模块化是面对复杂的业务场景不可或缺的工具,或许你经常使用它,但却从没有系统的了解过,所以今天我们来聊一聊Node.js模块 ...

  8. pwnable.kr第二题collision

    1 col@prowl:~$ ls -al 2 total 36 3 drwxr-x--- 5 root col 4096 Oct 23 2016 . 4 drwxr-xr-x 114 root ro ...

  9. Java进阶专题(二十八) Service Mesh初体验

    前言 ​ ⽬前,微服务的架构⽅式在企业中得到了极⼤的发展,主要原因是其解决了传统的单体架构中存在的问题.当单体架构拆分成微服务架构就可以⾼枕⽆忧了吗? 显然不是的.微服务架构体系中同样也存在很多的挑战 ...

  10. 亲测有效JS中9种数组去重方法

    码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14555831.html 目录 码文不易,转载请带上本文链接,感谢~ https://www ...