驱动编程-ssdt hook--系统服务表

来源:互联网 发布:js 触发事件 编辑:程序博客网 时间:2024/05/16 05:12

整理下自己的驱动编程。

ssdt是系统服务表,每个window系统都会维护自己的系统服务表。我们可以使用kernel detective看下ssdt表。

以openProcess为例子:

开windbg

kd> u nt!ZwOpenProcess
nt!ZwOpenProcess:
804ff720 b87a000000      mov     eax,7Ah  //7A
804ff725 8d542404        lea     edx,[esp+4]
804ff729 9c              pushfd
804ff72a 6a08            push    8
804ff72c e850ed0300      call    nt!KiSystemService (8053e481)
804ff731 c21000          ret     10h
nt!ZwOpenProcessToken:
804ff734 b87b000000      mov     eax,7Bh
804ff739 8d542404        lea     edx,[esp+4]

ZwOpenPeocess的开头

mov     eax,7Ah

7A的十进制就是190对应的ssdt表的第190个。


现在来说下openProcess的hook方法

分为两种:

修改ssdt表:

修改ssdt表的第190地址,在修改之前先保存原来的ssdt地址,然后跳到自己定义的MyopenProcess,在MyOpenProcess结束跳回原来保存的地址。这种修改方法容易被检测出来。


inline hook:

第二种修改openProcess函数的入口使用jmp跳转到自己的函数上,据我所知,大部分保护驱动都是这样的。


代码献上:

miniddk.cpp

#include "miniDDK.h"#include "SSDT.h"#include "IDThook.h"#pragma INITCODE extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING b){//=================Init============================//分开注册 派遣函数KdPrint(("\n\n驱动被加载----------\n"));pDriverObject->MajorFunction[IRP_MJ_CREATE]=ddk_DispatchRoutine_CREATE;pDriverObject->MajorFunction[IRP_MJ_CLOSE]=ddk_DispatchRoutine_CLOSE;pDriverObject->MajorFunction[IRP_MJ_READ]=ddk_DispatchRoutine_READ;pDriverObject->MajorFunction[IRP_MJ_WRITE]=ddk_DispatchRoutine_WRITE;pDriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL]=ddk_DispatchRoutine_CONTROL;CreateMyDriver(pDriverObject);pDriverObject->DriverUnload = DDK_Unload;//=================Init============================//=============inlinehook==================SSDT_NtoldProcess_Addr = GetNt_OldAddress();KdPrint(("SSDT_NtoldProcess_Addr  %x\n",SSDT_NtoldProcess_Addr));//利用SSDT读取当前的NtOpenProcess的地址SSDT_NtcurProcess_Addr = GetCurNtOpenProcess();KdPrint(("NtOpenProcessAddr: %x\n",SSDT_NtcurProcess_Addr));//构建inlinehook的参数newAddr.jmp= 0xE9;newAddr.addr = SSDT_NtoldProcess_Addr - SSDT_NtcurProcess_Addr -5;//if(SSDT_NtoldProcess_Addr!=SSDT_NtcurProcess_Addr){//KdPrint(("OpenProcess被HOOK 已修复------------\n"));//temp = (pjmpCode)SSDT_NtcurProcess_Addr;//oldAddr.jmp = temp->jmp;//oldAddr.addr = temp->addr;//temp->jmp = newAddr.jmp;//temp->addr = newAddr.addr;////}//=============inlinehook==================//================ssdt hook==================//Hook();//================ssdt hook==================//==================IDT hook=================//test();IDThook();//==================IDT hook=================return (1);}#pragma PAGECODEVOID DDK_Unload(IN PDRIVER_OBJECT pDriverObject){UNICODE_STRING symbolName;//=============ssdthook==================//UnHook();//还原SSDT表//=============ssdthook==================//=============inlinehook==================//if(SSDT_NtoldProcess_Addr!=SSDT_NtcurProcess_Addr){//oldAddr.jmp=temp->jmp; //oldAddr.addr=temp->addr ;//}//=============inlinehook==================//==================IDT hook=================IDTunhook();//==================IDT hook=================//删除驱动IoDeleteDevice()IoDeleteDevice(pDriverObject->DeviceObject);//删除符号链接IoDeleteSymbolicLink(symLinkName);RtlInitUnicodeString(&symbolName,L"\\??\\djj_DriverSymbol");IoDeleteSymbolicLink(&symbolName);KdPrint(("驱动被卸载------------\n"));}//INITCODE的代码一最好放在CPP吧 毕初始化一次就消失了#pragma INITCODENTSTATUS CreateMyDriver(IN PDRIVER_OBJECT pDriverObject){NTSTATUS status;PDEVICE_OBJECT pDevObj;//创建设备名称  用RtlInitUnicodeString初始化设备名称指针UNICODE_STRING devName;UNICODE_STRING symbolName;RtlInitUnicodeString(&devName,L"\\Driver\\djj_Driver");RtlInitUnicodeString(&symbolName,L"\\??\\djj_DriverSymbol");//创建设备 用IoCreateDevice创建设备,如果不成功则返回status = IoCreateDevice(pDriverObject,0,&devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj);if(!NT_SUCCESS(status)){KdPrint(("创建设备失败"));return status;}pDevObj->Flags |= DO_BUFFERED_IO;//创建符号链接 用IoCreateSymlicLink创建符号链接,创建成功返回 STATUS_SUCCESS; 创建不成功则调用 status = IoCreateSymbolicLink(&symbolName,&devName);if(!NT_SUCCESS(status)){KdPrint(("创建符号链接失败"));return status;}return STATUS_SUCCESS;}
ssdt.h
#include<ntddk.h>#include <windef.h>#include "defStruct.h"#ifdef __cplusplusextern "C"{#endif#include <NTDDK.h> //这里包含需要用C方式编译的头文件#ifdef __cplusplus}#endif //==================inline ssdt hook==================ULONG SSDT_NtcurProcess_Addr;//声明要再前面 有点无语 只是CULONG SSDT_NtoldProcess_Addr;jmpCode oldAddr,newAddr;pjmpCode temp;//extern "C" extern long KeServiceDescriptorTable;typedef struct _ServiceDescriptorTable {PVOID ServiceTableBase; //System Service Dispatch Table 的基地址  PVOID ServiceCounterTable;//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。  PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表 }*PServiceDescriptorTable; extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable;//NtOpenProcess获取当前地址long GetCurNtOpenProcess(){long SSDT_NtProcess_Addr;_asm{push eaxmov eax,KeServiceDescriptorTablemov eax,[eax]lea eax,[eax+4*7Ah]mov eax,[eax]mov SSDT_NtProcess_Addr,eaxpop eax}return SSDT_NtProcess_Addr;}//获取原来的地址NtOpenProcesslong GetNt_OldAddress(){UNICODE_STRING Old_Address_Name;long Old_Addr;RtlInitUnicodeString(&Old_Address_Name,L"NtOpenProcess");Old_Addr = (long)MmGetSystemRoutineAddress(&Old_Address_Name);//KdPrint(("old_Addr:%x\n",Old_Addr));return Old_Addr;} //==============inline ssdt hook end===========================//============ssdt hook end========================extern "C" typedef  NTSTATUS      __stdcall NTOPENPROCESS (         OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId );NTOPENPROCESS  *RealNtOpenProcess ; NTSTATUS MyOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId){NTSTATUS rc;//KdPrint(("MyOpenProcess hook\n"));//KdPrint(("RealNtOpenProcess  %x\n",RealNtOpenProcess));//KdPrint(("*RealNtOpenProcess  %x\n",*RealNtOpenProcess));rc = (NTSTATUS)RealNtOpenProcess(ProcessHandle,AccessMask,ObjectAttributes,ClientId);return rc;}//hook住OpenProcess使得无法附加 利用修改当前的KeServiceDescriptorTable 7A #pragma PAGECODEvoid Hook(){LONG t_addr;t_addr = (LONG)KeServiceDescriptorTable->ServiceTableBase;LONG *SSDT_Adr = (PLONG)(t_addr+0x7A*4);RealNtOpenProcess = ( NTOPENPROCESS *)(*SSDT_Adr);KdPrint(("*RealNtOpenProcess  %x\n",*RealNtOpenProcess));KdPrint(("RealNtOpenProcess  %x\n",RealNtOpenProcess));long test1,test2,test3;//OpenProcess();[KeServiceDescriptorTable]+4*7Ah__asm //去掉页面保护{    climov eax,cr0and eax,not 10000h //and eax,0FFFEFFFFhmov cr0,eax}_asm{push eaxpush ebxmov eax,KeServiceDescriptorTablemov eax,[eax]   //服务表列表mov test1,eaxlea eax,[eax+4*7Ah] //服务表的指向OpenProcess的首地址mov test2,eaxmov ebx,MyOpenProcess//mov eax,[eax] //NtOpenProcess的首地址mov [eax],ebxmov eax,[eax]mov test3,eax//mov eax,MyOpenProcess //修改服务表为MyOpenProcesspop ebxpop eax}KdPrint(("KeServiceDescriptorTable: %x\n",KeServiceDescriptorTable));KdPrint(("[KeServiceDescriptorTable]: %x\n",test1));KdPrint(("[KeServiceDescriptorTable]+4*7Ah: %x\n",test2));KdPrint(("[[KeServiceDescriptorTable]+4*7Ah]: %x\n",test3));KdPrint(("MyOpenProcess: %x\n",MyOpenProcess));__asm {   mov     eax, cr0   or     eax, 10000h   mov     cr0, eax   sti }   }#pragma PAGECODEvoid UnHook(){long test1,test2,test3;//OpenProcess();[KeServiceDescriptorTable]+4*7Ah__asm //去掉页面保护{    climov eax,cr0and eax,not 10000h //and eax,0FFFEFFFFhmov cr0,eax}_asm{push eaxpush ebxmov eax,KeServiceDescriptorTablemov eax,[eax]   //服务表列表mov test1,eaxlea eax,[eax+4*7Ah] //服务表的指向OpenProcess的首地址mov test2,eaxmov ebx,RealNtOpenProcess//mov eax,[eax] //NtOpenProcess的首地址mov [eax],ebxmov eax,[eax]mov test3,eax//mov eax,MyOpenProcess //修改服务表为MyOpenProcesspop ebxpop eax}KdPrint(("KeServiceDescriptorTable: %x\n",KeServiceDescriptorTable));KdPrint(("[KeServiceDescriptorTable]: %x\n",test1));KdPrint(("[KeServiceDescriptorTable]+4*7Ah: %x\n",test2));KdPrint(("[[KeServiceDescriptorTable]+4*7Ah]: %x\n",test3));KdPrint(("MyOpenProcess: %x\n",MyOpenProcess));__asm {   mov     eax, cr0   or     eax, 10000h   mov     cr0, eax   sti }   }//============ssdt hook end========================



0 0