看流星社区

 找回密码
 注册账号
查看: 2035|回复: 0

获取任意NT*和NtUser*系列函数地址(SSDT表和SSDT影子表定位)

[复制链接]

该用户从未签到

发表于 2013-5-6 08:45:04 | 显示全部楼层 |阅读模式
本贴是驱动编程贴。比较经典和实用。凡是驱动编程都要用到的。在  驱动钩子编程上 使用频率很高。
也包括 恢复驱动钩子等。
-------------------------------------------------------------------------------------
影子表是未导出的,需要定位才能找到。由于过程麻烦所以本贴封装了一个函数给大家使用。。。
基于界面、找窗口、后台按键等消息函数 等全是 NtUser* 开头的,是在ssdt影子表上的。
而基于内存、进程方面的函数全是NT*  开头的,是在ssdt表上的。
ssdt表是导出的可以,上面的函数地址很容易 获取。
但是 ssdt影子表是未导出的,上面得函数地址就很麻烦获取。。。
不过现在不用担心麻烦了,以下这个函数 帮你全部搞定。。。。。
封装了一个自定义的函数  GetSSDTCurAddr ,参数只有2个
功能 可以获取任意NT*和NtUser*系列函数地址。


内核函数地址有啥用,我就不多说了。。。各种HOOK 保护全是从内核函数 地址开始的。

还有就是  获取影子表上的函数地址必须 是驱动通信的时候 才能 显示的,否则会蓝屏的。
因为影子表上的 函数地址必须 在 gui线程上 才能显示的。
也就说你在驱动入口内 写了 影子表函数地址 显示,那么就会蓝屏的。
因为这个问题,今天懒了N次。

在驱动编程上 给我感觉就是 要考虑 有些代码的 执行的条件,否则很会蓝屏。。或者无效,




注意我的是win7 32 位的函数序号,你如果要 在xp上测试的话 先把函数序号修改下。
VOID   Test()//支持win7 32 位和 xp 32位
{
  //获取影子表
   
          KeServiceDescriptorTableShadow=(PSYSTEM_SERVICE_TABLE)GetShadowTableAddress();


     if ((KeServiceDescriptorTableShadow!=NULL))
         {
             DbgPrint(" SSDT影子表的NtUserShowWindow地址= %x ",GetSSDTCurAddr(591,TRUE));
                         //TRUE表示是SSDT影子表(简称SSSDT)上的函数, 591 是NtUserShowWindow的函数序号

             DbgPrint(" SSDT表的NtWriteVirtualMemory地址= %x ",GetSSDTCurAddr(399,FALSE));
                         //FALSE 表示是SSDT表上的函数, 339是NtWriteVirtualMemory的函数序号

         }
   else
   {
                DbgPrint("没有找到SSDT影子表 或 SSDT表");
   }

}




#include <ntddk.h>
#include <stdio.h>
#include <windef.h>


#define DEVICE_NAME L"\\Device\\woniu" //Driver Name
#define LINK_NAME L"\\DosDevices\\woniu"  //Link Name


#define IOCTL_BASE        0x800
#define TEMPLATE_CTL_CODE(i) \
        CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PID TEMPLATE_CTL_CODE(1)  //控制码是 801

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObj);
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);


typedef struct _System_Service_Table{   //SSDT结构
        PVOID  ServiceTableBase;
        PVOID  ServiceCounterTableBase;
        ULONG  NumberOfServices;
        PVOID  ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;



NTKERNELAPI KeAddSystemServiceTable(PVOID, PVOID, PVOID, PVOID, PVOID); //此内核函数是导出的是用来找影子表的
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow;
extern  PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;


VOID   Test();//自定义函数-测试获取函数地址
ULONG GetShadowTableAddress();//获取影子表
ULONG GetSSDTCurAddr(IN ULONG Index,BOOL IsShadow);//获取NT*系列函数地址和NtUser*系列函数




NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
        NTSTATUS status = STATUS_SUCCESS;
        UNICODE_STRING ustrLinkName;
        UNICODE_STRING ustrDevName;   
        PDEVICE_OBJECT pDevObj;

        DbgPrint("Drv DriverEntry: %S\n",pRegistryString->Buffer);

        // Create dispatch points for device control, create, close.
        pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
        pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
        pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
        pDriverObj->DriverUnload = DriverUnload;

        RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);//1

        status = IoCreateDevice(pDriverObj, //2
                0,
                &ustrDevName,
                FILE_DEVICE_UNKNOWN,
                0,
                FALSE,
                &pDevObj);

        DbgPrint("Drv Device Name %S",ustrDevName.Buffer);

        if(!NT_SUCCESS(status))
        {
                DbgPrint("Drv IoCreateDevice = 0x%x\n", status);
                return status;
        }

        RtlInitUnicodeString(&ustrLinkName, LINK_NAME);//3

        status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  //4


        if(!NT_SUCCESS(status))
        {
                DbgPrint("Drv IoCreateSymbolicLink = 0x%x\n", status);
                IoDeleteDevice(pDevObj);  
                return status;
        }

        DbgPrint("Drv SymbolicLink:%S",ustrLinkName.Buffer);
        return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
        PIO_STACK_LOCATION pIrpStack;
        ULONG uIoControlCode;
        PVOID pIoBuffer;
        ULONG uInSize;
        ULONG uOutSize;
        long hProcess;

        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
        pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
        uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
        uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

        switch(uIoControlCode)
        {
        case IOCTL_PID:///////控制码如果为 0x801 ,那么就执行以下的代码
                {
                        // DbgPrint("进程PID:%d",*(HANDLE *)pIoBuffer);

                                                    Test();//读取SSDt影子表函数地址 和 SSDt表上的函数地址。
                         status = STATUS_SUCCESS;
                        break;
                }
        }

        if(status == STATUS_SUCCESS)
                pIrp->IoStatus.Information = uOutSize;
        else
                pIrp->IoStatus.Information = 0;

        pIrp->IoStatus.Status = status;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return status;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
        UNICODE_STRING strLink;
        RtlInitUnicodeString(&strLink, LINK_NAME);
        IoDeleteSymbolicLink(&strLink);
        IoDeleteDevice(pDriverObj->DeviceObject);
        DbgPrint("Driver Unloaded\n");
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        DbgPrint("Driver IRP_MJ_CREATE\n");
        return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        DbgPrint("Driver IRP_MJ_CLOSEE\n");
        return STATUS_SUCCESS;
}


/////////////////////////////////////////////////////////////////////////////
//该函数是网上COPY来的-非常的犀利可以获取 影子表。。。。
ULONG GetShadowTableAddress()
{
        ULONG dwordatbyte,i;
        PUCHAR p = (PUCHAR) KeAddSystemServiceTable;
        for(i = 0; i < PAGE_SIZE; i++, p++)//  往下找一页 指针递增1
        {
                __try
                {
                        dwordatbyte = *(PULONG)p;
                }
                __except(EXCEPTION_EXECUTE_HANDLER)
                {
                        return FALSE;
                }
                if(MmIsAddressValid((PVOID)dwordatbyte))
                {
                        if(memcmp((PVOID)dwordatbyte, KeServiceDescriptorTable, 16) == 0)//对比前16字节 相同则找到
                        {
                                if((PVOID)dwordatbyte == KeServiceDescriptorTable)//排除自己
                                {
                                        continue;
                                }
                                return dwordatbyte;
                        }
                }
        }
        return FALSE;
}


//获取函数地址(支持 SSDT影子表上的函数和SSDT表上的函数地址)
ULONG GetSSDTCurAddr(IN ULONG Index,BOOL IsShadow)
{
        ULONG ServiceCount,BaseAddr;

        if (KeServiceDescriptorTableShadow!=NULL)
        {
                ServiceCount=KeServiceDescriptorTableShadow[IsShadow?1:0].NumberOfServices;
                BaseAddr = (ULONG)KeServiceDescriptorTableShadow[IsShadow?1:0].ServiceTableBase;

                if (Index>=ServiceCount) return FALSE;

                return *(PULONG)(BaseAddr+Index * 4);
        }
        return FALSE;
}




VOID   Test()//支持win7 32 位和 xp 32位
{
  //获取影子表
   
          KeServiceDescriptorTableShadow=(PSYSTEM_SERVICE_TABLE)GetShadowTableAddress();


     if ((KeServiceDescriptorTableShadow!=NULL))
         {
             DbgPrint(" SSDT影子表的NtUserShowWindow地址= %x ",GetSSDTCurAddr(591,TRUE));
                         //TRUE表示是SSDT影子表(简称SSSDT)上的函数, 591 是NtUserShowWindow的函数序号

             DbgPrint(" SSDT表的NtWriteVirtualMemory地址= %x ",GetSSDTCurAddr(399,FALSE));
                         //FALSE 表示是SSDT表上的函数, 339是NtWriteVirtualMemory的函数序号

         }
   else
   {
                DbgPrint("没有找到SSDT影子表 或 SSDT表");
   }

}

http://pan.baidu.com/share/link?shareid=520320&uk=3895950538
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-14 10:25

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表