[原创]暑假浅谈系列第一帖——通信篇
那些年我们使用过的驱动通信方式
这个是整章的全局函数
PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(pIrp);
ULONG uLenth=stack->Parameters.Read.Length;
ULONG Offset=stack->Parameters.Read.ByteOffset.QuadPart;
一
我最喜欢的通信方式 : 设备通信----DO_BUFFERED_IO
1.优点:方便快捷,可以定义很长很长的结构体,稳定。
2.缺点:只能用于小数据的处理,效率不好,必须使用readfile 和 writefile进行交互通信.
3.注意事项:
①
WINBASEAPI
BOOL
WINAPI
ReadFile(
__in HANDLE hFile,//这个是设备的句柄
__out_bcount_part_opt(nNumberOfBytesToRead, *lpNumberOfBytesRead) //你要out的缓冲区(结构体)__out_data_source(FILE) LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,//你要读取多少的字节数;r0对应 uLenth=stack->Parameters.Read.Length;1
__out_opt LPDWORD lpNumberOfBytesRead,//这个是返回的大小;r0对应pIrp->IoStatus.Information = uLenth;
__inout_opt LPOVERLAPPED lpOverlapped//同步才会用到;r0没用要
);
②
WriteFile(
__in HANDLE hFile,//对应设备句柄
__in_bcount_opt(nNumberOfBytesToWrite) LPCVOID lpBuffer,//要传人的缓冲区
__in DWORD nNumberOfBytesToWrite,//缓冲区的大小uLenth=stack->Parameters.Write.Length;2
__out_opt LPDWORD lpNumberOfBytesWritten,//传出大小//同上
__inout_opt LPOVERLAPPED lpOverlapped//同步不管
);
③:如果想稳定的交互信息,最关键还是传人 大小 ;假如大小太小,数据很多,那么到了内核层,由于事先irp分配的大小(r3决定的空间1.2决定),你可能取出 多余数据(溢出了),或者直接蓝屏了(访问到无效空间)。
二
DO_DIRECT_IO 直接读写
1.优点:看起来更加的安全
,可以得到缓冲区的地址。
2.缺点:麻烦.必须判断 mdl_len 是否和传人的东西 相一致,不然肯定要蓝的,或者产生多余数据.
3.注意事项: 直接设备操作是锁定了 mdl,可以理解为映射到mdl,进行操作,你看的全部是微软为了方便我们,写的宏,认真去里面看的话,可以发现他是一个 链表结构
typedef __struct_bcount(Size) struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
我最不喜欢的 其他读取方式
1.不要设置标志;
2.缺点:麻烦,要有异常分发,他的地址直接来自 user_address。
总结:
1.设备驱动辅助核心就在 r3 readfile write上面.
2.他和r3其实没多大关系,全部都和r0有关,这也看出了irp这个结构的神奇之处.
3.标志对设备的影响
4.他只有三种通信方式
=========================分割线============================
Io通信篇:
这个是大家用的最广的:
1.优点:可以自定义通信码,有4种通信方式:
全局变量:
uIoContrlCode=pIostack->Parameters.DeviceIoControl.IoControlCode;
uInSize=pIostack->Parameters.DeviceIoControl.InputBufferLength;
uOutSize=pIostack->Parameters.DeviceIoControl.OutputBufferLength;
uIobuffer=pIrp->AssociatedIrp.SystemBuffer;
首先我们看一下这个函数:
WINBASEAPI
BOOL
WINAPI
DeviceIoControl(
__in HANDLE hDevice,//设备对象
__in DWORD dwIoControlCode,//通信码;r0 对应 uIoContrlCode=pIostack->Parameters.DeviceIoControl.IoControlCode;
__in_bcount_opt(nInBufferSize) LPVOID lpInBuffer,//输入指针
__in DWORD nInBufferSize,//输入大小;r0对应uInSize=pIostack->Parameters.DeviceIoControl.InputBufferLength;
__out_bcount_part_opt(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,//输出缓冲区(结构)
__in DWORD nOutBufferSize,//输出大小;r0对应 uOutSize=pIostack->Parameters.DeviceIoControl.OutputBufferLength;
__out_opt LPDWORD lpBytesReturned,//返回大小;r0对应pIrp->IoStatus.Information=uOutSize;
__inout_opt LPOVERLAPPED lpOverlapped//同步
);
它的通信方式
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
首先我们看他的宏:
DeviceType:
#define FILE_DEVICE_BEEP 0x00000001
#define FILE_DEVICE_CD_ROM 0x00000002
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
#define FILE_DEVICE_CONTROLLER 0x00000004
#define FILE_DEVICE_DATALINK 0x00000005
#define FILE_DEVICE_DFS 0x00000006
#define FILE_DEVICE_DISK 0x00000007
#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
#define FILE_DEVICE_FILE_SYSTEM 0x00000009
#define FILE_DEVICE_INPORT_PORT 0x0000000a
#define FILE_DEVICE_KEYBOARD 0x0000000b
#define FILE_DEVICE_MAILSLOT 0x0000000c
#define FILE_DEVICE_MIDI_IN 0x0000000d
#define FILE_DEVICE_MIDI_OUT 0x0000000e
#define FILE_DEVICE_MOUSE 0x0000000f
#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
#define FILE_DEVICE_NAMED_PIPE 0x00000011
#define FILE_DEVICE_NETWORK 0x00000012
#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
#define FILE_DEVICE_NULL 0x00000015
#define FILE_DEVICE_PARALLEL_PORT 0x00000016
#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
#define FILE_DEVICE_PRINTER 0x00000018
#define FILE_DEVICE_SCANNER 0x00000019
#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
#define FILE_DEVICE_SERIAL_PORT 0x0000001b
#define FILE_DEVICE_SCREEN 0x0000001c
#define FILE_DEVICE_SOUND 0x0000001d
#define FILE_DEVICE_STREAMS 0x0000001e
#define FILE_DEVICE_TAPE 0x0000001f
#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
#define FILE_DEVICE_TRANSPORT 0x00000021
#define FILE_DEVICE_UNKNOWN 0x00000022
#define FILE_DEVICE_VIDEO 0x00000023
#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
#define FILE_DEVICE_WAVE_IN 0x00000025
#define FILE_DEVICE_WAVE_OUT 0x00000026
#define FILE_DEVICE_8042_PORT 0x00000027
#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
#define FILE_DEVICE_BATTERY 0x00000029
#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
#define FILE_DEVICE_MODEM 0x0000002b
#define FILE_DEVICE_VDM 0x0000002c
#define FILE_DEVICE_MASS_STORAGE 0x0000002d
#define FILE_DEVICE_SMB 0x0000002e
#define FILE_DEVICE_KS 0x0000002f
#define FILE_DEVICE_CHANGER 0x00000030
#define FILE_DEVICE_SMARTCARD 0x00000031
#define FILE_DEVICE_ACPI 0x00000032
#define FILE_DEVICE_DVD 0x00000033
#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
#define FILE_DEVICE_DFS_VOLUME 0x00000036
#define FILE_DEVICE_SERENUM 0x00000037
#define FILE_DEVICE_TERMSRV 0x00000038
#define FILE_DEVICE_KSEC 0x00000039
#define FILE_DEVICE_FIPS 0x0000003A
#define FILE_DEVICE_INFINIBAND 0x0000003B
#define FILE_DEVICE_VMBUS 0x0000003E
#define FILE_DEVICE_CRYPT_PROVIDER 0x0000003F
#define FILE_DEVICE_WPD 0x00000040
#define FILE_DEVICE_BLUETOOTH 0x00000041
#define FILE_DEVICE_MT_COMPOSITE 0x00000042
#define FILE_DEVICE_MT_TRANSPORT 0x00000043
#define FILE_DEVICE_BIOMETRIC 0x00000044
#define FILE_DEVICE_PMI 0x00000045
很多吧,包含了 文件设备等等。
我们可以用这些干一些事情.
Function:
0x0000-0x7FFFF为微软保留;
0x800-0xFFF为程序猿自定义;
Method:
METHOD_BUFFERED:缓冲区 和设备一样.
METHOD_IN_DIRECT:直接读取.
METHOD_Out_DIRECT:直接写.
METHOD_NEITHER:其他方式,需要异常分发判断.
由于和上面差不多,自己看代码,就不浪费口水了.
总结:
1.IO通信说白了就是writefile readfile的结合体.
2.都有自己的缓冲区,有地址传人
是不是觉得,上面这句话有点问题. 通信码?

==========================分割线========================

ZwCreateFile(
__out PHANDLE FileHandle, //通信码
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_opt PLARGE_INTEGER AllocationSize,
__in ULONG FileAttributes,
__in ULONG ShareAccess,
__in ULONG CreateDisposition,
__in ULONG CreateOptions,
__in_bcount_opt(EaLength) PVOID EaBuffer, //缓冲区
你说对不对
__in ULONG EaLength
);
#endif
A盾是这么做的,找一个函数只要可以有一块缓冲区可以进去就好,可以容纳足够的大小.
所以我们可以ssdt or inline someone function 进行hook 接着自己判断处理就ok了.
你想怎么劫持,恢复就废了,再来判断你就蓝了.
PS:
群:Super-Rootkis 121157016 欢迎大家来玩,进来主要公告.
老V sandman 八爷 老恒
都在里面
本人14号有事要去杭州,呆一个月:
1. 想找一份实习工作,没多少钱都没关系.
2.打杂端菜都可以,希望
有一份兼职
3.今年大二,对自己充满新的期待,x64 vt 搞起(我与时代不同步( ⊙ o ⊙ )啊!)
