Win64 驱动内核编程-33.枚举与删除对象回调
来源:互联网 发布:ubuntu u盘启动工具 编辑:程序博客网 时间:2024/05/22 13:57
枚举与删除对象回调
对象回调存储在对应对象结构体里,简单来说,就是存储在 ObjectType. CallbackList 这
个双向链表里。但对象结构体在每个系统上都不一定相同。比如 WIN7X64 的结构体如下:
ntdll!_OBJECT_TYPE
+0x000 TypeList : _LIST_ENTRY
+0x010 Name : _UNICODE_STRING
+0x020 DefaultObject : Ptr64 Void
+0x028 Index : UChar
+0x02c TotalNumberOfObjects : Uint4B
+0x030 TotalNumberOfHandles : Uint4B
+0x034 HighWaterNumberOfObjects : Uint4B
+0x038 HighWaterNumberOfHandles : Uint4B
+0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x0b0 TypeLock : _EX_PUSH_LOCK
+0x0b8 Key : Uint4B
+0x0c0 CallbackList : _LIST_ENTRY
Object.CallbackList->FLink 指向的地址,是一个结构体链表,它的定义如下:
typedef struct _OB_CALLBACK
{
LIST_ENTRY ListEntry;
ULONG64 Unknown;
ULONG64 ObHandle;
ULONG64 ObjTypeAddr;
ULONG64 PreCall;
ULONG64 PostCall;
} OB_CALLBACK, *POB_CALLBACK
微软没有公开这个结构体的定义,这个结构体是资料作者逆向出来的。但是至少在 WIN7、WIN8和 WIN8.1 上通用。知道了结构体的定义,枚举就方便了(WINDOWS 目前仅有进程对象回调和线程对象回调,但就算以后有了其它回调,也是通用的):
ULONG EnumObCallbacks(){ULONG c=0;PLIST_ENTRY CurrEntry=NULL;POB_CALLBACK pObCallback;BOOLEAN IsTxCallback;ULONG64 ObProcessCallbackListHead = *(ULONG64*)PsProcessType + ObjectCallbackListOffset;ULONG64 ObThreadCallbackListHead = *(ULONG64*)PsThreadType + ObjectCallbackListOffset;//dprintf("ObProcessCallbackListHead: %p\n",ObProcessCallbackListHead);CurrEntry=((PLIST_ENTRY)ObProcessCallbackListHead)->Flink;//list_head的数据是垃圾数据,忽略do{pObCallback=(POB_CALLBACK)CurrEntry;if(pObCallback->ObHandle!=0){dprintf("ObHandle: %p\n",pObCallback->ObHandle);dprintf("PreCall: %p\n",pObCallback->PreCall);dprintf("PostCall: %p\n",pObCallback->PostCall);c++;}CurrEntry = CurrEntry->Flink;}while(CurrEntry != (PLIST_ENTRY)ObProcessCallbackListHead);//dprintf("ObThreadCallbackListHead: %p\n",ObThreadCallbackListHead);CurrEntry=((PLIST_ENTRY)ObThreadCallbackListHead)->Flink;//list_head的数据是垃圾数据,忽略do{pObCallback=(POB_CALLBACK)CurrEntry;if(pObCallback->ObHandle!=0){dprintf("ObHandle: %p\n",pObCallback->ObHandle);dprintf("PreCall: %p\n",pObCallback->PreCall);dprintf("PostCall: %p\n",pObCallback->PostCall);c++;}CurrEntry = CurrEntry->Flink;}while(CurrEntry != (PLIST_ENTRY)ObThreadCallbackListHead);dprintf("ObCallback count: %ld\n",c);return c;}
执行结果:
对付对象回调,方法还是老三套
1.用 ObUnRegisterCallbacks 传入 ObHandle 注销回调;
2.把记录的回调函数地址改为自己的设置的空回调;
3.给对方设置的回调函数地址写入 RET。
不过这次使用第三种方法要注意,必须先禁掉 PostCall,再禁用 PreCall,否则容易蓝屏。
完整代码:
#define dprintfDbgPrint#defineDEVICE_NAMEL"\\Device\\MyDriver"#define LINK_NAMEL"\\DosDevices\\MyDriver"#define LINK_GLOBAL_NAMEL"\\DosDevices\\Global\\MyDriver"ULONG NtBuildNumber=0;ULONG ObjectCallbackListOffset=0;typedef struct _OB_CALLBACK{LIST_ENTRYListEntry;ULONG64Unknown;ULONG64ObHandle;ULONG64ObjTypeAddr;ULONG64PreCall;ULONG64PostCall;} OB_CALLBACK, *POB_CALLBACK;BOOLEAN GetVersionAndHardCode(){BOOLEAN b=FALSE;RTL_OSVERSIONINFOWosi;osi.dwOSVersionInfoSize=sizeof(RTL_OSVERSIONINFOW);RtlFillMemory(&osi,sizeof(RTL_OSVERSIONINFOW),0);RtlGetVersion(&osi);NtBuildNumber=osi.dwBuildNumber;DbgPrint("NtBuildNumber: %ld\n",NtBuildNumber);switch (NtBuildNumber){case 7600:case 7601:{ObjectCallbackListOffset=0xC0;b=TRUE;break;}case 9200:{ObjectCallbackListOffset=0xC8;//OBJECT_TYPE.CallbackListb=TRUE;break;}case 9600:{ObjectCallbackListOffset=0xC8;//OBJECT_TYPE.CallbackListb=TRUE;break;}default:break;}return b;}KIRQL WPOFFx64(){KIRQL irql=KeRaiseIrqlToDpcLevel();UINT64 cr0=__readcr0();cr0 &= 0xfffffffffffeffff;__writecr0(cr0);_disable();return irql;}void WPONx64(KIRQL irql){UINT64 cr0=__readcr0();cr0 |= 0x10000;_enable();__writecr0(cr0);KeLowerIrql(irql);}VOID DisableObcallbacks(PVOID Address){KIRQL irql;CHAR patchCode[] = "\x33\xC0\xC3";//xor eax,eax + retif(!Address)return;if(MmIsAddressValid(Address)){irql=WPOFFx64();memcpy(Address,patchCode,3);WPONx64(irql);}}ULONG EnumObCallbacks(){ULONG c=0;PLIST_ENTRY CurrEntry=NULL;POB_CALLBACK pObCallback;BOOLEAN IsTxCallback;ULONG64 ObProcessCallbackListHead = *(ULONG64*)PsProcessType + ObjectCallbackListOffset;ULONG64 ObThreadCallbackListHead = *(ULONG64*)PsThreadType + ObjectCallbackListOffset;//dprintf("ObProcessCallbackListHead: %p\n",ObProcessCallbackListHead);CurrEntry=((PLIST_ENTRY)ObProcessCallbackListHead)->Flink;//list_head的数据是垃圾数据,忽略do{pObCallback=(POB_CALLBACK)CurrEntry;if(pObCallback->ObHandle!=0){dprintf("ObHandle: %p\n",pObCallback->ObHandle);dprintf("PreCall: %p\n",pObCallback->PreCall);dprintf("PostCall: %p\n",pObCallback->PostCall);c++;}CurrEntry = CurrEntry->Flink;}while(CurrEntry != (PLIST_ENTRY)ObProcessCallbackListHead);//dprintf("ObThreadCallbackListHead: %p\n",ObThreadCallbackListHead);CurrEntry=((PLIST_ENTRY)ObThreadCallbackListHead)->Flink;//list_head的数据是垃圾数据,忽略do{pObCallback=(POB_CALLBACK)CurrEntry;if(pObCallback->ObHandle!=0){dprintf("ObHandle: %p\n",pObCallback->ObHandle);dprintf("PreCall: %p\n",pObCallback->PreCall);dprintf("PostCall: %p\n",pObCallback->PostCall);c++;}CurrEntry = CurrEntry->Flink;}while(CurrEntry != (PLIST_ENTRY)ObThreadCallbackListHead);dprintf("ObCallback count: %ld\n",c);return c;}
- Win64 驱动内核编程-33.枚举与删除对象回调
- Win64 驱动内核编程-30.枚举与删除线程回调
- Win64 驱动内核编程-31.枚举与删除映像回调
- Win64 驱动内核编程-32.枚举与删除注册表回调
- Win64 驱动内核编程-34.对抗与枚举MiniFilter
- Win64 驱动内核编程-28.枚举消息钩子
- Win64 驱动内核编程-13.回调监控模块加载
- Win64 驱动内核编程-14.回调监控文件
- Win64 驱动内核编程-15.回调监控注册表
- Win64 驱动内核编程-25.X64枚举和隐藏内核模块
- Win64 驱动内核编程-11.回调监控进线程句柄操作
- Win64 驱动内核编程-12.回调监控进线程创建和退出
- Win64 驱动内核编程-1.环境搭建
- Win64 驱动内核编程-18.SSDT
- Win64 驱动内核编程-19.HOOK-SSDT
- Win64 驱动内核编程-20.UnHook SSDT
- Win64 驱动内核编程-3.内核里使用内存
- Win64 驱动内核编程-4.内核里操作字符串
- java查询mongodb中的objectid示例
- 用Makefile 创建进度条
- Uva 12096 The SetStack Computer
- android-支持多种屏幕[处理运行时变更] 十六
- c/c++中的两个反正切函数
- Win64 驱动内核编程-33.枚举与删除对象回调
- 利用gdal实现重采样与裁剪
- 移植linux3.6至mini2451过程中遇到的问题及解决(持续更新中...)
- 8、MAC 上Docker环境搭建
- 第五届蓝桥杯B组java—猜字母
- Uva-7423-Assigning Workstations(贪心+优先队列)
- 攻破JAVA NIO技术壁垒
- tensorflow 入门学习(1)
- 4、搭建个人电子商务平台——ecshop