SSDT表的遍历
阅读原文时间:2023年07月10日阅读:2
//VS2005创建的工程,系统xp sp2

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//stdafx.h文件
#ifndef _WIN32_WINNT        // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501    // Change this to the appropriate value to target other versions of Windows.
#endif                        

#ifdef __cplusplus
extern "C"
{

#endif

#include <ntddk.h>
#include <ntddstor.h>
#include <mountdev.h>
#include <ntddvol.h>

//注意:全局变量要在这里定义

//系统服务描述符表-在ntoskrnl.exe中导出KeServiceDescriptorTable这个表
#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
    //System Service Dispatch Table的基地址
    PVOID ServiceTableBase;
    //SSDT中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。
    PVOID ServiceCounterTable;
    //由 ServiceTableBase 描述的服务的数目。
    unsigned int NumberOfServices;
    //每个系统服务参数字节数表的基地址-系统服务参数表SSPT
    PVOID ParamTableBase;
}*PServiceDescriptorTable;
#pragma pack()

//导出系统服务描述符表SSDT的指针
extern  PServiceDescriptorTable  KeServiceDescriptorTable; 

#ifdef __cplusplus
}
#endif

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//ReadSsdtForFuntion.cpp文件
#include "stdafx.h"

//由SSDT索引号获取当前函数地址,如:
//NtOpenProcess  [[KeServiceDescriptorTable]+0x7A*4]  

void ReadSsdtForFuntionUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS ReadSsdtForFuntionCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS ReadSsdtForFuntionDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

//1.纯汇编读取内核函数的地址
LONG GetFunctionAddr_ASM(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex);

//2.用指针读取内核函数的地址
LONG GetFunticonAddr(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex);

#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
    UNICODE_STRING DeviceName,Win32Device;
    PDEVICE_OBJECT DeviceObject = NULL;
    NTSTATUS status;
    unsigned i;

    //SSDT表的范围
    LONG lgSsdtNumber = -1;

    RtlInitUnicodeString(&DeviceName,L"\\Device\\ReadSsdtForFuntion0");
    RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\ReadSsdtForFuntion0");

    //设置默认处理例程
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
        DriverObject->MajorFunction[i] = ReadSsdtForFuntionDefaultHandler;

    //设置创建例程
    DriverObject->MajorFunction[IRP_MJ_CREATE] = ReadSsdtForFuntionCreateClose;
    //设置关闭例程
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = ReadSsdtForFuntionCreateClose;

    //设置卸载例程
    DriverObject->DriverUnload = ReadSsdtForFuntionUnload;

    //创建设备对象
    status = IoCreateDevice(DriverObject,
                            0,
                            &DeviceName,
                            FILE_DEVICE_UNKNOWN,
                            0,
                            FALSE,
                            &DeviceObject);
    if (!NT_SUCCESS(status))
        return status;
    if (!DeviceObject)
        return STATUS_UNEXPECTED_IO_ERROR;

    DeviceObject->Flags |= DO_DIRECT_IO;
    DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;

    //创建符号连接
    status = IoCreateSymbolicLink(&Win32Device, &DeviceName);
    if (!NT_SUCCESS(status))
        return status;

    //初始化完成,可以工作了
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    //设置测试断点
    __asm int 3

    //获取SSDT表的范围
    lgSsdtNumber = KeServiceDescriptorTable->NumberOfServices;

    //使用方法1.遍历SSDT
    KdPrint(("使用方法1.遍历SSDT\r\n"));
    for (i = 0; i < lgSsdtNumber; i++)
    {
        KdPrint(("Index:%04X--FunAddr:%08X\r\n", i, GetFunctionAddr_ASM(KeServiceDescriptorTable, i)));
    }

    //使用方法2.遍历SSDT
    KdPrint(("使用方法2.遍历SSDT\r\n"));
    for (i = 0; i < lgSsdtNumber; i++)
    {
        KdPrint(("Index:%04X--FunAddr:%08X\r\n", i, GetFunticonAddr(KeServiceDescriptorTable, i)));
    }

    return STATUS_SUCCESS;
}

//1.使用汇编的方法读取内核函数的地址
LONG GetFunctionAddr_ASM(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex)
{
    LONG lgSsdtFunAddr = 0;

    //lgSsdtFunAddr = [[KeServiceDescriptorTable]+lgSsdtIndex*4]
    __asm
    {
        push ebx
        push eax
        mov ebx, KeServiceDescriptorTable
        mov ebx, [ebx]  //SSDT表的基地址
        mov eax, lgSsdtIndex
        shl eax, 2
        add ebx, eax
        mov ebx, [ebx]
        mov lgSsdtFunAddr, ebx
        pop  eax
        pop  ebx
    }

    return lgSsdtFunAddr;
}

//2.使用指针的方法获取函数的地址
LONG GetFunticonAddr(PServiceDescriptorTable KeServiceDescriptorTable, LONG lgSsdtIndex)
{
    LONG lgSsdtAddr = 0;
    //获取SSDT表的基址
    lgSsdtAddr = (LONG)KeServiceDescriptorTable->ServiceTableBase;

    PLONG plgSsdtFunAddr = 0;
    //获取内核函数的地址指针
    plgSsdtFunAddr = (PLONG)(lgSsdtAddr+lgSsdtIndex*4);

    //返回内核函数的地址
    return (*plgSsdtFunAddr);
}

void ReadSsdtForFuntionUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING Win32Device;
    RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\ReadSsdtForFuntion0");
    IoDeleteSymbolicLink(&Win32Device);
    IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS ReadSsdtForFuntionCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS ReadSsdtForFuntionDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Irp->IoStatus.Status;
}

//参考资料:
//郁金香老师讲课资料