SSDT(System Services Descriptor Table),系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。
通过修改此表的函数地址可以对常用windows函数及API进行hook,从而实现对一些关心的系统动作进行过滤、监控的目的。一些HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块,
目前极个别病毒确实会采用这种方法来保护自己或者破坏防毒软件,但在这种病毒进入系统前如果防毒软件能够识别并清除它将没有机会发作.
SSDT到底是什么呢?打一个比方,SSDT相当于系统内部API的指向标,作用就是告诉系统,需要调用的API在什么地方。
请看源码解析
[cpp]
/*************************************************************************
*
*ZwQuerySystemInformation函数常用结构
*
**************************************************************************/
#ifndef _SPS_H_
#define _SPS_H_ 1
#include <ntddk.h>
#include "table.h"
#include "pe.h"
#endif
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // 0
SystemProcessorInformation, // 1
SystemPerformanceInformation, // 2
SystemTimeOfDayInformation, // 3
SystemNotImplemented1, // 4
SystemProcessesAndThreadsInformation, // 5
SystemCallCounts, // 6
SystemConfigurationInformation, // 7
SystemProcessorTimes, // 8
SystemGlobalFlag, // 9
SystemNotImplemented2, // 10
SystemModuleInformation, // 11 系统模块
SystemLockInformation, // 12
SystemNotImplemented3, // 13
SystemNotImplemented4, // 14
SystemNotImplemented5, // 15
SystemHandleInformation, // 16
SystemObjectInformation, // 17
SystemPagefileInformation, // 18
SystemInstructionEmulationCounts, // 19
SystemInvalidInfoClass1, // 20
SystemCacheInformation, // 21
SystemPoolTagInformation, // 22
SystemProcessorStatistics, // 23
SystemDpcInformation, // 24
SystemNotImplemented6, // 25
SystemLoadImage, // 26
SystemUnloadImage, // 27
SystemTimeAdjustment, // 28
SystemNotImplemented7, // 29
SystemNotImplemented8, // 30
SystemNotImplemented9, // 31
SystemCrashDumpInformation, // 32
SystemExceptionInformation, // 33
SystemCrashDumpStateInformation, // 34
SystemKernelDebuggerInformation, // 35
SystemContextSwitchInformation, // 36
SystemRegistryQuotaInformation, // 37
SystemLoadAndCallImage, // 38
SystemPrioritySeparation, // 39
SystemNotImplemented10, // 40
SystemNotImplemented11, // 41
SystemInvalidInfoClass2, // 42
SystemInvalidInfoClass3, // 43
SystemTimeZoneInformation, // 44
SystemLookasideInformation, // 45
SystemSetTimeSlipEvent, // 46
SystemCreateSession, // 47
SystemDeleteSession, // 48
SystemInvalidInfoClass4, // 49
SystemRangeStartInformation, // 50
SystemVerifierInformation, // 51
SystemAddVerifier, // 52
SystemSessionProcessesInformation // 53
}SYSTEM_INFORMATION_CLASS; //内核模块类型,我们要列举的是SystemProcessesAndThreadsInformation,进程和线程信
//线程信息
typedef struct _SYSTEM_THREAD_INFORMATION
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; //线程结构
//进程信息
typedef struct _SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryDelta; //NextEntryOffset下一个进程结构的偏移量,每一个进程对应一个结构
//最后一个进程的NextEntryOffset=0
ULONG NumberOfThreads; //线程数目
LARGE_INTEGER Reserved ;
LARGE_INTEGER CreateTime; //创建时间
LARGE_INTEGER UserTime; //用户模式(Ring 3)的CPU时间
LARGE_INTEGER KernelTime; //内核模式(Ring 0)的CPU时间
UNICODE_STRING ProcessName; //进程名
KPRIORITY BasePriority; //进程优先权
ULONG ProcessId; //进程标识符
ULONG InheritedFromProcessId; //父进程的标识符
ULONG HandleCount; //句柄数目
ULONG Reserved2 ;
ULONG PrivatePageCount;
VM_COUNTERS VirtualMemoryCounters; //虚拟存储器的结构
IO_COUNTERS IoCounters; //IO计数结构
SYSTEM_THREAD_INFORMATION Threads[0]; //进程相关线程的结构数组
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
//------------------------------------------------------------------------------
//模块信息
typedef struct _SYSTEM_MODULE_INFORMATION {
ULONG Reserved ;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
//模块列表
typedef struct _SYSMODULELIST{
ULONG ulCount;
SYSTEM_MODULE_INFORMATION smi ;
} SYSMODULELIST, *PSYSMODULELIST;
//-----------------------------------------------------------------------------------
//DRIVER_SECTION结构
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union {
struct
{
ULONG TimeDateStamp;
};
struct
{
PVOID LoadedImports;
};
};
struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
//===================================================================================
NTKERNELAPI NTSTATUS
ZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
); //最终是通过遍历EPROCESS获取的
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
); //定义结构
NTSYSAPI BOOLEAN NTAPI KeAddSystemServiceTable(
ULONG lpAddressTable,
BOOLEAN bUnknown,
ULONG dwNumEntries,
ULONG lpParameterTable,
ULONG dwTableID
);
//****************************函数声明*************************************
//根据地址查找模块
void FindModuleByAddress( ULONG Address, PVOID buffer);
//根据RVA查找SSDT 文件偏移
ULONG FindFileOffsetByRva( ULONG ModuleAddress,ULONG Rva);
//路径解析出子进程名
void GetModuleName( char *ProcessPath, char *ProcessName);
//根据服务号得到当前的地址
ULONG FindOriAddress( ULONG index );
//得到SSDT Shadow表地址
ULONG GetSSDTShadowAddress2();
ULONG GetWin32Base2( PDRIVER_OBJECT driver);
ULONG FindShadowOriAddress( ULONG index );
/*****************************************************************************************
*
*函数名:FindModuleByAddress
*功能描述:根据函数地址查找所属模块
*
******************************************************************************************/
/*****************************************************************************************
*
* 原理: 利用ZwQuerySystemInformation传入SystemModuleInformation(11)得到系统模块列表
* 得到每个模块的起始和结束地址
* 比对地址,在那个范围就属于哪个模块
* 得到模块名
*
******************************************************************************************/
#include "refresh.h"
void FindModuleByAddress( ULONG Address, PVOID buffer)
{
NTSTATUS status;
ULONG size;
ULONG i;
ULONG minAddress;
ULONG maxAddress;
PSYSMODULELIST List;
ZwQuerySystemInformation( SystemModuleInformation ,&size,0,&size);
KdPrint(("[FindModuleByAddress] size:0x%x\n",size));
List=(PSYSMODULELIST)ExAllocatePool(NonPagedPool,size);
if(List==NULL)
{
KdPrint(("[FindModuleByAddress] malloc memory failed\n"));
return ;
}