Win64 驱动内核编程-33.枚举与删除对象回调
转载:http://www.voidcn.com/article/p-wulgeluy-bao.html
枚举与删除对象回调
对象回调存储在对应对象结构体里,简单来说,就是存储在 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 dprintf DbgPrint #define DEVICE_NAME L"\\Device\\MyDriver"
#define LINK_NAME L"\\DosDevices\\MyDriver"
#define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\MyDriver" ULONG NtBuildNumber=0;
ULONG ObjectCallbackListOffset=0; typedef struct _OB_CALLBACK
{
LIST_ENTRY ListEntry;
ULONG64 Unknown;
ULONG64 ObHandle;
ULONG64 ObjTypeAddr;
ULONG64 PreCall;
ULONG64 PostCall;
} OB_CALLBACK, *POB_CALLBACK; BOOLEAN GetVersionAndHardCode()
{
BOOLEAN b=FALSE;
RTL_OSVERSIONINFOW osi;
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.CallbackList
b=TRUE;
break;
}
case 9600:
{
ObjectCallbackListOffset=0xC8; //OBJECT_TYPE.CallbackList
b=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 + ret
if(!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;
}
最新文章
- 兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输
- Hyper-V端口映射
- Spring Boot+Cloud RestTemplate 调用IP或域名
- codeforces 725D . Contest Balloons(贪心+优先队列)
- Tomcat输出catalina.out的大小控制
- Table显示滚动条
- Eclipse、MyEclipse优化,提高运行速度
- 【hadoop之翊】——基于CentOS的hadoop2.4.0伪分布安装配置
- GetDirectories 出错的解决方法
- log4j.xml(信息打印)
- FreeBSD 系统的配置.
- Meet Python
- @Autowired注解警告Field injection is not recommended
- h5-canvas 单像素操作
- Linux服务器tomcat无法通过ip加端口访问
- python hex() oct() bin() math 内置函数
- 对C语言中指针的入门理解
- PYTHON实现识别图片
- MVC中使用Castle.Windsor
- 《Python核心编程》第二版第五章答案
热门文章
- SSH爆破应急响应
- kali 使用John破解zip压缩包的密码
- OAuth 第三方登录授权码(authorization code)方式的小例子
- vue-cli配置移动端自适应flexible.js
- Spring Boot + Mybatis 配置多数据源
- mcp2515屏蔽寄存器和过滤寄存器的学习
- cpu绘图的本质:生成图片的二进制(数字)信息
- 函数式编程—函数的关系—is-a、has-a、use-a
- MongoDB权限配置
- 异常STATUS_FATAL_USER_CALLBACK_EXCEPTION(0xc000041d)