10.1 驱动通信
几乎每个在 Windows 上注册了的驱动程序都有一个设备名和一个符号链接。用户模式 的程序能够通过符号链接获得驱动的句柄,然后使用这个句柄和驱动进行联系。具体函数如 下:
HANDLE WINAPI CreateFileW(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttribute
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
第一个参数,填写文件名或者设备名,这里填写目标驱动的符号连接。 dwDesiredAccess 表示访问方式,读或者写(可以既读又写,也可以不读不写),GENERIC_READ (0x80000000) 读,GENERIC_WRITE (0x40000000)写。dwShareMode 这里设置成 0,表示在 CreateFileW 返回并且安全关闭了句柄之后,才能访问设备。 lpSecurityAttributes 设置成 NULL,表示使 用 默 认 的 安 全 描 述 符 , 并 且 不 能 被 子 进 程 继 承 。 dwCreationDisposition 参 数 设 置 成 OPEN_EXISTING (0x3),表示如果设备存在就打开,其余情况返回错误。最后两个参数简 单的设置成 NULL。
当 CreateFileW 成功返回一个有效的句柄之后,我们就能使用 DeviceIoControl(由 kernel32.dll 导出)传递一个 IOCTL 给设备。
BOOL WINAPI DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
第 一个 参数 由 CreateFileW 返 回的 句柄 。 dwIoControlCode 是 要传 递给 设备 启动 的 IOCTL 代码。这个代码决定了调用驱动中的什么功能。参数 lpInBuffer 指向一个缓冲区,包 含了将要传递给驱动的数据。这个缓冲区是我们后面要重点操作的地方,fuzz 数据将存在这。 nInBufferSize 为传递给驱动的缓冲区的大小。 lpOutBuffer 和 lpOutBufferSize,和前两个参 数一样,不过是用于接收驱动返回的数据。lpBytesReturned 为驱动实际返回的数据的长度。 最后一个参数简单的设置成 NULL。
现在对于驱动的交互,大家应该不陌生了,接下来就祭出我们的 Immunity,用它 Hook 住 DeviceIoControl 然后变形输入缓冲区内的数据,最后 fuzzing every driver。