- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
有anti,hook才会进步. by the.night
首先CreateServiceA/W
这个API想不被挂钩.比较麻烦.
因为这是个很复杂的封装api.
安装驱动本身涉及到注册表操作以及安装服务等操作.(od跳进去看一下就知道了)
要想封装起来.相对麻烦.不怕麻烦可以自己扫函数CRC.
或者get advapi32.dll handle, getprocaddr 跳过函数头调用
===========
但上面两种方法,都是个死磕的方法,
CRC的话,就陷入CRC的pass和anti的话题.
跳过函数头也不靠谱.一个很复杂的封装.很多地方都可以深层去hook.
===========
但是很重要的一点是.驱动通信.
一般写驱动都不会直接在驱动入口函数就把功能执行了,而是给一个驱动通信去操作
所以其实驱动扒走了就扒走了.并不重要.
这就衍生3种防御方法.
1.是做一个通信加密.
即通信传入数据做一个加密处理.到驱动内再解开.
还可以在加上通信key去解.
2.反校验发起通信的进程.
这里做一个小科普.驱动入口函数是发生在pid=4的那个system进程里
而驱动通信IRP是发生调用驱动通信的进程里.
SO.进入驱动后线程里有很多信息可以查的.
3.把驱动通信封装到Zw函数.
一二两条.大家自己扩展.
简单说说第3条。
因为Zw函数是可以直接用int 2e中断进入内核的。
只要获得 index就可以保证在r3下不被HOOK.
================
我们看看这两个函数
DeviceIoControl
ZwDeviceIoControlFile
BOOL DeviceIoControl(
HANDLE hDevice, ebp+8
DWORD dwIoControlCode, +c
LPVOID lpInBuffer, +10
DWORD nInBufferSize, +14
LPVOID lpOutBuffer, +18
DWORD nOutBufferSize, +1c
LPDWORD lpBytesReturned, +20
LPOVERLAPPED lpOverlapped +24
);
NTSTATUS ZwDeviceIoControlFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,--------& typedef struct _IO_STATUS_BLOCK
_In_ ULONG IoControlCode,
_In_opt_ PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_opt_ PVOID OutputBuffer,
_In_ ULONG OutputBufferLength
);
然后用OD步过跟一下.
push ebp+1c
push ebp+18
push ebp+14
push ebp+10
push ebp+c
push & ebp-024 //0x12f654 &typedef struct _IO_STATUS_BLOCK
push 0------------这3个.简易的通信都是0
push 0
push 0
push ebp+8
call ZwDeviceIoControlFile
=====================================
以上是OD跟的情况。
FileHandle 传入指针 传入长度 传出指针 传出长度 通信code 都能直接在ZwDeviceIoControlFile的参数找到
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
这3个,在简易的通信里,都是NULL.
唯独 _Out_ PIO_STATUS_BLOCK IoStatusBlock
这东西,并不是DeviceIoControl的 lpOverlapped参数。
========================
_IO_STATUS_BLOCK 结构定义如下.8字节.
typedef struct _IO_STATUS_BLOCK
{
NTSTATUS Status; //32位的无符号长整型
ULONG Information;} //如果驱动通信成功,不带信息,它最后会被赋值给 lpOverlapped
==============
再来看返回值.
cmp eax,0x103
je 7C801730
cmp eax,ebx ebx=0
jl 7C801752----------------- =0成功.但是
mov eax,dword ptr [ebp+0x20]
mov ecx,dword ptr [ebp-0x20] //0x12f658
mov dword ptr [eax],ecx
NTSTATUS是一个有符号 的长整数。并且分为四个域。最高2位Sev域
00 成功(Success) //成功
01 信息(Informational)//成功带信息
10 警告(Warning)
11 错误(Error)
我们平常自己的简易驱动可以直接判断=0成功即可。
=====================
最后总结ZwDeviceIoControlFile的调用
NTSTATUS ZwDeviceIoControlFile(
_In_ HANDLE FileHandle,------------------------CreateFile获得的句柄
_In_opt_ HANDLE Event,-------------------------0
_In_opt_ PIO_APC_ROUTINE ApcRoutine,--------0
_In_opt_ PVOID ApcContext,-----------------------0
_Out_ PIO_STATUS_BLOCK IoStatusBlock,--------& struct _IO_STATUS_BLOCK
_In_ ULONG IoControlCode,--------------------IoControlCode
_In_opt_ PVOID InputBuffer,-----------------------传入指针
_In_ ULONG InputBufferLength,-----------------传入长度
_Out_opt_ PVOID OutputBuffer,------------------传出指针
_In_ ULONG OutputBufferLength--------------传出长度
);
_IO_STATUS_BLOCK 用一个8字节的空白内存代替.
然后它的后4字节是 实际写出长度.
返回值:
返回0 为调用成功 (或最高16位不=C0)
|
|