Bug2021-10-15 - 导致OneDrive崩溃
有crashdump,原因待分析
实现
- OneDrive的修改实现方式
- API: ReadDirectoryChangesW
- API可能使用方式:
- Blocking(Synchronous):直接调用
- Overlapped:传入OVERLAPPED,通过结构里的hEvent触发
- Completion Routine:传入lpCompletionRoutine回调
- IOCP:传入空OVERLAPPED,调用流程CreateFile → CreateIoCompletionPort → ReadDirectoryChangesW → GetQueuedCompletionStatus
- OneDrive使用的是IOCP ReadDirectoryChangesW
- OneDrive逆向
- WatcherWin::Monitor中调用了ReadDirectoryChangesW → GetQueuedCompletionStatus这两步
- 在同一个队列中有多种不同的消息,ReadDirectoryChangesW所使用的CompletionKey为8,WatcherWin::Monitor解析后,转换为某类CompletionKey(0~7),执行其他操作
- 实现SymLink Notification
- Hook ReadDirectoryChangesExW
- 用Overlapped用法监听多个目录
- WaitForMultipleObjects 监听对应Event
- 将返回的FILE_NOTIFY_INFORMATION中的路径改写
- 将结果通过PostQueuedCompletionStatus发送回HANDLE对应的IOCP
- ReadDirectoryChangesW内部实现
- 通过Native API:NtNotifyChangeDirectoryFile
- 根据ReactOS源码,NtNotifyChangeDirectoryFile内部DeviceIoControl到了文件系统驱动里面,然后存到NotifyChanges相关对象中
- IOCP相关代码不在后续的文件系统的Irp Stack中
- 如何获取HANDLE对应的IOCP
- 可以通过NtSetInformationFile设置,但不能通过NtQueryInformationFile获取
- 根据ReactOS源码,IOCP存储在FileObject→CompletionInfo中
- 根据ReactOS源码,IOCP在HANDLE对应IRP完成的时候触发,无法基于HANDLE手动触发
- 实在无法,额外Hook了CreateIoCompletionPort,通过NtQueryObject获取句柄类型,若为File则判断路径是否为OneDrive,如果是则加入Map,得到HANDLE到IOCP的mapping