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。