#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
typedef unsigned long DWORD;
typedef unsigned long *PDWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef struct _MOUDULE_INFO {
DWORD d_Reserved1;
DWORD d_Reserved2;
PVOID p_Base; //基地址
DWORD d_Size; //大小
DWORD d_Flags;
WORD w_Index;
WORD w_Rank;
WORD w_LoadCount;
WORD w_NameOffset;//名字偏移
BYTE a_bPath[MAXIMUM_FILENAME_LENGTH];//保存模块路径
} MODULE_INFO, *PMODULE_INFO, **PPMODULE_INFO;
typedef struct _MODULE_LIST
{
int d_Modules;
MODULE_INFO a_Modules[];
} MODULE_LIST, *PMODULE_LIST, **PPMODULE_LIST;
typedef struct _NTOSKRNL {
DWORD Base;
DWORD End;
} NTOSKRNL, *PNTOSKRNL;
#define SystemModuleInformation 11
/***************************************
声明全局变量PMODULE_LIST g_pml;
NTOSKRNL g_noskrnl;
***************************************/
PMODULE_LIST g_pml;
NTOSKRNL g_noskrnl;
#pragma pack(1)
typedef struct ServiceDescriptorEntry
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
PServiceDescriptorTableEntry_t KeServiceDescriptorTableShadow = NULL;
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
PMDL g_pmdlSystemCall;
PVOID *MappedSystemCallTable;
int *g_aSSDT;
NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
ULONG SystemInformationCLass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
ZWQUERYSYSTEMINFORMATION NtQuerySystemInformation;
NTKERNELAPI
NTSTATUS
KeAddSystemServiceTable(
IN PULONG Base,
IN PULONG Count OPTIONAL,
IN ULONG Limit,
IN PUCHAR Number,
IN ULONG Index
);
NTSTATUS DispathCreateClose(PDEVICE_OBJECT pDevObj,PIRP pIrp);
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject);
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
/*************************************************
*函数名称:GetListOfModules
*功能:分配内存,取得指向内核模块的指针
*返回:指向(MODULE_LIST)指针
***********************************************/
PMODULE_LIST GetListOfModules(PNTSTATUS pns)
{
ULONG ul_Size;
ULONG *pul_MListAddr = NULL;
NTSTATUS ns;
PMODULE_LIST pml = NULL;
//先获取所需的缓冲区大小
DbgPrint("Begin to GetModuleList!\n");
NtQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)SYSTEMSERVICE(ZwQuerySystemInformation);
NtQuerySystemInformation(SystemModuleInformation,
&ul_Size,
0,
&ul_Size);
//分配内存
pul_MListAddr = (ULONG *)ExAllocatePool(PagedPool,ul_Size);
if(!pul_MListAddr)
{
DbgPrint("pul_MListAddr NULL!\n");
if(pns != NULL)
*pns = STATUS_INSUFFICIENT_RESOURCES;
return (PMODULE_LIST)pul_MListAddr;
}
ns = NtQuerySystemInformation(SystemModuleInformation,
pul_MListAddr,
ul_Size,
0);
//判断是否失败
if(ns != STATUS_SUCCESS)
{
DbgPrint("NtQuerySystemInformation Failes!\n");
//释放分配的内存
ExFreePool((PVOID)pul_MListAddr);
if(pns != NULL)
*pns = ns;
return NULL;
}
pml = (PMODULE_LIST)pul_MListAddr;
if(pns != NULL)
*pns = ns;
DbgPrint("NtQuerySystemInformation SucessFul!\n");
return pml;
}
/**************************************************************
*函数名:GetntoskrnlBase
*功能:通过搜索内核模块找到ntoskrl.exe,取得其开始地址其结尾地址
*报存在全局变量结构中
*参数:模块名称
:
**************************************************************/
NTSTATUS GetntoskrnlBase(char *szModuleName)
{
int count;
NTSTATUS pns;
g_pml = NULL;
g_noskrnl.Base = 0;
g_noskrnl.End = 0;
g_pml = GetListOfModules(&pns);
if(!NT_SUCCESS(pns))
{
DbgPrint("获取内核模块有误!\n");
return pns;
}
if(!g_pml)
{
DbgPrint("g_pml = GetListOfModules(&pns)Failes!\n");
return STATUS_UNSUCCESSFUL;
}
for(count = 0; count < g_pml->d_Modules; count++)
{
DbgPrint("%s\n",g_pml->a_Modules[count].a_bPath+g_pml->a_Modules[count].w_NameOffset);
//查找noskrnl.exe
//模块名称==模块路径指针+ 名字偏移
if(_stricmp(szModuleName,g_pml->a_Modules[count].a_bPath +
g_pml->a_Modules[count].w_NameOffset) == 0)
{
g_noskrnl.Base = (DWORD)(g_pml->a_Modules[count].p_Base);
g_noskrnl.End = ((DWORD)g_pml->a_Modules[count].p_Base +
g_pml->a_Modules[count].d_Size);
DbgPrint("找到内核地址%08x,END:%08x\n",g_noskrnl.Base,g_noskrnl.End);
break;
}
}
ExFreePool(g_pml);
if(g_noskrnl.Base != 0)
{
return STATUS_SUCCESS;
DbgPrint("成功取得地址!\n");
}
else
{
DbgPrint("取地址fail!\n");
return STATUS_UNSUCCESSFUL;
}
}
/****************************************************************
*函数名称:void CheckSSDTHooks(PServiceDescriptorTableEntry_t pTable)
*功能查找:SSDT表中的被HOOK的地址也可以用于查找SHADOWSSDT表中的HOOK
*参数:SSDT
*******************************************************************/
void CheckSSDTHooks(PServiceDescriptorTableEntry_t pKeServiceDescriptorTable)
{
unsigned int i;
DbgPrint("begin to check!Base:%08xEnd:%08x\n",g_noskrnl.Base,g_noskrnl.End);
for(i = 0; i< pKeServiceDescriptorTable->NumberOfServices; i++)
{
g_aSSDT[i] = pKeServiceDescriptorTable->ServiceTableBase[i];
if(((DWORD)pKeServiceDescriptorTable->ServiceTableBase[i] < g_noskrnl.Base) ||
((DWORD)pKeServiceDescriptorTable->ServiceTableBase[i] > g_noskrnl.End))
{
DbgPrint("System Call is %x hooked at addr %08x!\n",i,
pKeServiceDescriptorTable->ServiceTableBase[i]);
}
}
}
/********************************************************************
*函数名称:RepairSSDTHook()
*功能:和保存在全局数组中的地址比较 如果不相等
进入HOOK地址中JMP回到原来没有HOOK的地址
*
***********************************************************************/
void RepairSSDTHook(PServiceDescriptorTableEntry_t pKeServiceDescriptorTable)
{
unsigned int i;
unsigned int uOffset;
char *pFtion;
unsigned long ul_Fution;
for(i=0; i<pKeServiceDescriptorTable->NumberOfServices; i++)
{
if(g_aSSDT[i] != (DWORD)pKeServiceDescriptorTable->ServiceTableBase[i])
{
DbgPrint("地址%08x已经改变\n",pKeServiceDescriptorTable[i]);
ul_Fution = pKeServiceDescriptorTable->ServiceTableBase[i];
uOffset = (DWORD)pKeServiceDescriptorTable->ServiceTableBase[i] - g_aSSDT[i] - 5;
_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}
*( (char *)(&((unsigned char *)ul_Fution)[0]) )=0xe9;
*( (unsigned long *)(&((unsigned char *)ul_Fution)[1]) ) = uOffset;
_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
}
}
}
VOID GetSSDTShadowBase()
{
__try
{
UCHAR *cPtr;
UCHAR *pOpcode;
ULONG Length;
for (cPtr = (PUCHAR)KeAddSystemServiceTable;
cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;
cPtr += Length)
{
Length = SizeOfCode(cPtr, &pOpcode);
if (!Length) break;
if ( *(PUSHORT)cPtr == 0x888D )
{
KeServiceDescriptorTableShadow = (PServiceDescriptorTableEntry_t)(*(ULONG *)((ULONG)pOpcode + 2));
break;
}
}
} __except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("GetSSDTShadowBase : Raised exception 0x%X.\n", GetExceptionCode());
}
}
/***********************************************************
*函数名称DbgPrintTheSSDTAndShowSSDT()
*函数功能:打印SSDT表和SSDTSHOW表的地址
*
***********************************************************/
NTSTATUS DbgPrintTheSSDTAndShowSSDT()
{
int i,n;
PVOID pShadowSSDT=NULL;
GetSSDTShadowBase();
if(!KeServiceDescriptorTableShadow)
return STATUS_UNSUCCESSFUL;
/* g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTableShadow[1].Base,
KeServiceDescriptorTableShadow[1].Limit*4);
if(!g_pmdlSystemCall)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
/* // Change the flags of the MDL
g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
*/
DbgPrint("the system_table:%08x\n",KeServiceDescriptorTableShadow);
DbgPrint("the KeServiceDescriptorTable:%08x\n",KeServiceDescriptorTable.ServiceTableBase);
DbgPrint("the system_table of keservicedecriptortable :%08x\n",KeServiceDescriptorTableShadow[1].ServiceTableBase);
n = (int)KeServiceDescriptorTableShadow[1].NumberOfServices;
__try{
pShadowSSDT = (PVOID)KeServiceDescriptorTableShadow[1].ServiceTableBase;
if(!*((ULONG *)pShadowSSDT))
{
return STATUS_UNSUCCESSFUL;
}
i = 0;
while(i<n)
{
DbgPrint("%x----------%08x\n",i,KeServiceDescriptorTableShadow[1].ServiceTableBase[i]);
i++;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("GetSSDTShadowBase : Raised exception 0x%X.\n", GetExceptionCode());
}
//KeServiceDescriptorTableShadow = system_descriptor_table->win32k.ServiceTableBase;
//DbgPrint("the KeServiceDescriptorTableShadow:%08x",MappedSystemCallTable[0]);
//DbgPrint("&MeppedSystemCallTable[]:%08x\n",&MappedSystemCallTable[0]);
//if(MappedSystemCallTable[1] != NULL)
// DbgPrint("the next is:%08x\n",MappedSystemCallTable[1]);
// DbgPrint("the NumberOfKeServiceDescriptorTableShadow:%x\n",
// KeServiceDescriptorTableShadow[1].Limit);
// n = KeServiceDescriptorTableShadow[1].Limit;
//for(i=0; i <= n; i++)
// DbgPrint("%x----------->%08x\n",i,KeServiceDescriptorTableShadow.ServiceTableBase[i]);
return STATUS_SUCCESS;
}
/
NTSTATUS RootkitUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("RootkitUnload");
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status=STATUS_SUCCESS;
DbgPrint("DriverEntry Load!\n");
DriverObject->DriverUnload = HelloDDKUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] =DispathCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispathCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
//创建驱动设备对象
status = CreateDevice(DriverObject);
g_aSSDT = (int *)ExAllocatePool(PagedPool,0x11c * sizeof(DWORD));
if(STATUS_SUCCESS == GetntoskrnlBase("ntkrnlpa.exe"))
{
CheckSSDTHooks(&KeServiceDescriptorTable);
DbgPrint("STATUS_SUCCESS == GetntoskrnlBase sucessful!\n");
}
else
{
DbgPrint("STATUS_SUCCESS == GetntoskrnlBase faile!\n");
}
//status = DbgPrintTheSSDTAndShowSSDT();
return status;
}
NTSTATUS DispathCreateClose(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
DbgPrint("DispathCreateClose\n");
//DbgPrintTheSSDTAndShowSSDT();
return STATUS_SUCCESS;
}
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING symLinkName;
//创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
//创建设备
status = IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj );
if (!NT_SUCCESS(status))
return status;
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
//创建符号链接
RtlInitUnicodeString(&symLinkName,L"\\??\\slShowSSDT");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName,&devName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice( pDevObj );
return status;
}
return STATUS_SUCCESS;
}
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pNextObj->DeviceExtension;
//删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);
pNextObj = pNextObj->NextDevice;
IoDeleteDevice( pDevExt->pDevice );
}
if(g_pmdlSystemCall)
{
MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
IoFreeMdl(g_pmdlSystemCall);
}
}
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
// 假设失败
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
// 取得此IRP(pIrp)的I/O堆栈指针
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// 取得I/O控制代码
ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
// 取得I/O缓冲区指针和它的长度
//PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
//ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(uIoControlCode)
{
case CHAR_CONVERT:
{
RepairSSDTHook(&KeServiceDescriptorTable);
}
break;
}
// 完成请求
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}