OnedriveSymLink

大类
Env
技术标签
逆向-Windows
开发-HookPatch-Windows
优先级
Medium
开始日期
Sep 27, 2021
状态
Maintaining
Public
Public
最后更新
Sep 28, 2021

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
        •