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. Pytorch1.7报错 Output 0 of UnbindBackward is a view and is being modified inplace

    utils里内容改成 if scale_each is True: for idx, _ in enumerate([jj for jj in tensor]): t = tensor[idx] # ...

  2. Reincarnation Without New Body(RWNB): Basic Theory and Baseline 现世转生基本理论及简单操作

    Abstract 投胎学是一门高深的学问,不仅没有现存的理论,也没有过往的经验.根据种种猜测,投胎后前世的记忆也不能保留,造成了很大的不方便.在本文中,我们绕过了投胎需要"来世"的 ...

  3. Pyqt5学习笔记(一)

    Python已有的GUI框架: Tkinter(python内嵌的GUI环境,使用TCL实现,易学易用,方便简单创GUI自带无需安装,适用于Unix.Windows和Mac系统组,在Tk8.0的后续版 ...

  4. Solon 框架详解(十一)- Solon Cloud 的配置说明

    Solon 详解系列文章: Solon 框架详解(一)- 快速入门 Solon 框架详解(二)- Solon的核心 Solon 框架详解(三)- Solon的web开发 Solon 框架详解(四)- ...

  5. HDU_6693 Valentine's Day 【概率问题】

    一.题目 Valentine's Day 二.分析 假设$ s_0 $代表不开心的概率,$ s_1 $代表开心一次的概率. 那么随便取一个物品,那么它的开心概率为$ p _i $,可以推导加入之后使女 ...

  6. 基于sinc的音频重采样(一):原理

    我在前面的文章<音频开源代码中重采样算法的评估与选择>中说过sinc方法是较好的音频重采样方法,缺点是运算量大.https://ccrma.stanford.edu/~jos/resamp ...

  7. 二叉树的建立与遍历(c语言)入门

    树其实在本质上就是一对多,链表就是一对一. 二叉树的建立: 这里的代码采用的是最粗暴的创建方法,无实际用处.但初次学习二叉树可以通过这个创建方法更好的理解二叉树. 二叉树的遍历: 遍历在大体上分为递归 ...

  8. python3 base64

    import base64s='hello world'bytes_by_s=s.encode() #将字符串编码-->字节码,b64_encode_bytes=base64.b64encode ...

  9. PAT (Basic Level) Practice (中文) 1050 螺旋矩阵 (25 分) 凌宸1642

    PAT (Basic Level) Practice (中文) 1050 螺旋矩阵 (25 分) 目录 PAT (Basic Level) Practice (中文) 1050 螺旋矩阵 (25 分) ...

  10. Python数据分析入门(十七):绘制条形图

    条形图的绘制方式跟折线图非常的类似,只不过是换成了plt.bar方法.plt.bar方法有以下常用参数: x:一个数组或者列表,代表需要绘制的条形图的x轴的坐标点. height:一个数组或者列表,代 ...