简介

2020年12月微软发布CVE-2020-17096的补丁,zecops团队对此漏洞进行了分析,文章在这里,本文根据其文章进行复现学习。这个洞是NTFS模块,zecops分析出来是内存泄露,但是微软对这类内存泄漏的洞很少收,并且标注的是Remote Code Execution,zecops团队也没有找到远程代码执行的地方,所以真正是否为zecops团队分析的那样还需要进一步研究。

补丁对比

问题出在ntfs.sys中,下面是对比的18362.117118362.1256,出除去一些未识别的符号,可以直接定位到NtfsOffloadRead函数

从函数名可以猜到是文件卸载读的操作,搜一下文档可以找到[MS-FSCC],其中的2.3.41 FSCTL_OFFLOAD_READ Request就是卸载读的操作,应该和这个函数有关

before patch

after patch

新版本红框函数内第一个参数从NULL变为 IrpConetxt 并删除了一些对参数的判断,这个 IrpContext 就是 NtfsOffloadRead 函数的第一个参数 ,第一个函数和调试跟踪有关,应该是开发人员使用的,所以重点应该放在第二个 NtfsExtendedCompleteRequestInternal函数,下面的代码基于补丁前的版本,如果第一个参数为NULL则直接跳过对第一个参数的操作,然后调用IRP完成函数

void __fastcall NtfsExtendedCompleteRequestInternal(__int64 a1, IRP *irp, int a3, __int64 a4, int a5)
{
  _QWORD *v5; // r13
  unsigned __int8 v6; // r12
  IRP *Irp; // rsi
  _IO_STACK_LOCATION *v10; // r15
  __int64 v11; // rax
  void *v12; // rcx
  bool v13; // sf
  void *v14; // rcx
  _QWORD *v15; // r14
  _QWORD *v16; // rax
  void *v17; // rcx
  PFILE_OBJECT v18; // rax
  __int64 v19; // rcx
  __int64 v20; // r8

  v5 = 0i64;
  v6 = a4;
  Irp = irp;
  v10 = 0i64;
  if ( irp )
  {
    v10 = irp->Tail.Overlay.CurrentStackLocation;
    if...
  }
  if ( a1 )
  {
    // ...
  }
LABEL_27:
  if ( Irp )
  {
    v18 = v10->FileObject;
    if ( v18 )
      v5 = v18->FsContext;
    Irp->IoStatus.Status = a3;
    if ( (unsigned __int8)(v10->MajorFunction - 3) <= 1u
      && a3 == 0xC000009A
      && v5
      && (*(_DWORD *)(v5[21] + 4i64) & 4) != 0
      && IoIsOperationSynchronous(Irp) )
    {
      ++NtfsFailedPagingFileOps;
    }
    if ( v10->MajorFunction == 3 && a3 == 0xC000009A && (Irp->Flags & 2) != 0 )
      ++NtfsFailedPagingReads;
    IofCompleteRequest(Irp, 1);
  }
}

在patch之后会传入IrpContext,若其非零则会解析很多字段,做一些释放资源和释放内存的操作,调用一些CancelCleanupDereference的函数,由此猜测patch之前没有很好的处理这些释放的资源,导致了内存泄露

if ( irpcontext )
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖