- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
本贴是驱动编程贴。比较经典和实用。凡是驱动编程都要用到的。在 驱动钩子编程上 使用频率很高。
也包括 恢复驱动钩子等。
-------------------------------------------------------------------------------------
影子表是未导出的,需要定位才能找到。由于过程麻烦所以本贴封装了一个函数给大家使用。。。
基于界面、找窗口、后台按键等消息函数 等全是 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 |
|