首页
社区
课程
招聘
[讨论]解锁Irp文件占坑的方法
2023-10-4 20:03 2795

[讨论]解锁Irp文件占坑的方法

2023-10-4 20:03
2795

先上链接: https://bbs.kanxue.com/thread-257384.htm

1.很简单 只用调用一个函数 NtfsDecrementCleanupCounts这个函数

上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
VOID
NtfsDecrementCleanupCounts (
    IN PSCB Scb,
    IN PLCB Lcb OPTIONAL,
    IN BOOLEAN NonCachedHandle
    )
 
/*++
 
Routine Description:
 
    This procedure decrements the cleanup counts for the associated data structures
    and if necessary it also start to cleanup associated internal attribute streams
 
Arguments:
 
    Scb - Supplies the Scb used in this operation
 
    Lcb - Optionally supplies the Lcb used in this operation
 
    NonCachedHandle - Indicates this handle is for a user non-cached handle.
 
Return Value:
 
    None.
 
  翻译:
        此过程减少关联数据结构的清理计数
    如果有必要,它还会开始清理关联的内部属性流
 
论据:
 
    Scb - 提供此操作中使用的 Scb
 
    Lcb - 可选择提供此操作中使用的 Lcb
 
    NonCachedHandle - 指示此句柄用于用户非缓存句柄。
 
--*/
 
{
    PVCB Vcb = Scb->Vcb;
 
    ASSERT_SCB( Scb );
    ASSERT_FCB( Scb->Fcb );
    ASSERT_VCB( Scb->Fcb->Vcb );
    ASSERT_OPTIONAL_LCB( Lcb );
 
    //
    //  First we decrement the appropriate cleanup counts
    //
 
    if (ARGUMENT_PRESENT(Lcb)) { Lcb->CleanupCount -= 1; }
 
    InterlockedDecrement( &Scb->CleanupCount );
    Scb->Fcb->CleanupCount -= 1;
 
    if (NonCachedHandle) {
 
        Scb->NonCachedCleanupCount -= 1;
    }
 
    InterlockedDecrement( &Vcb->CleanupCount );
 
    //
    //  Now if the Fcb's cleanup count is zero that indicates that we are
    //  done with this Fcb from a user handle standpoint and we should
    //  now scan through all of the Scb's that are opened under this
    //  Fcb and shutdown any internal attributes streams we have open.
    //  For example, EAs and ACLs.  We only need to do one.  The domino effect
    //  will take of the rest.
    //
 
    if (Scb->Fcb->CleanupCount == 0) {
 
        PSCB NextScb;
 
        //
        //  Remember if we are dealing with a system file and return immediately.
        //
 
        if (NtfsSegmentNumber( &Scb->Fcb->FileReference ) < FIRST_USER_FILE_NUMBER &&
            NtfsSegmentNumber( &Scb->Fcb->FileReference ) != ROOT_FILE_NAME_INDEX_NUMBER) {
 
            return;
        }
 
        for (NextScb = CONTAINING_RECORD(Scb->Fcb->ScbQueue.Flink, SCB, FcbLinks);
             &NextScb->FcbLinks != &Scb->Fcb->ScbQueue;
             NextScb = CONTAINING_RECORD( NextScb->FcbLinks.Flink, SCB, FcbLinks )) {
 
            //
            //  Skip the root index on the volume.
            //
 
            if (SafeNodeType( NextScb ) == NTFS_NTC_SCB_ROOT_INDEX) {
 
                continue;
            }
 
            //
            //  If we have an index with children then break out.
            //
 
            if ((SafeNodeType( NextScb ) == NTFS_NTC_SCB_INDEX) &&
                !IsListEmpty( &NextScb->ScbType.Index.LcbQueue )) {
 
                break;
            }
 
            //
            //  If there is an internal stream then dereference it and get out.
            //
 
            if (NextScb->FileObject != NULL) {
 
                NtfsDeleteInternalAttributeStream( NextScb,
                                                   (BOOLEAN) (Scb->Fcb->LinkCount == 0) );
                break;
            }
        }
    }
 
    //
    //  And return to our caller
    //
 
    return;
}

IDA 的代码显示 win7x64 ntfs.sys NtfsDecrementCleanupCounts 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
__int64 __fastcall NtfsDecrementCleanupCounts(__int64 a1, __int64 a2, __int64 a3, __int64 a4, int a5)
{
  __int64 v5; // r10
  __int64 result; // rax
  __int64 v8; // rcx
  unsigned __int16 *v9; // rdx
  __int64 v10; // rdx
 
  v5 = *(_QWORD *)(a2 + 0x78);
  if ( a3 )
    --*(_DWORD *)(a3 + 0xCC);
  if ( (*(_BYTE *)(*(_QWORD *)(a2 + 112) + 4i64) & 4) != 0 )
    return ((__int64 (__fastcall *)(__int64, __int64, __int64, __int64))sub_2A1A4)(a1, a2, a3, a4);
  _InterlockedAdd((volatile signed __int32 *)(a2 + 0x88), 0xFFFFFFFF);
  result = *(_QWORD *)(a2 + 0x70);
  _InterlockedAdd((volatile signed __int32 *)(result + 0x10), 0xFFFFFFFF);
  if ( (_DWORD)a4 )
    --*(_DWORD *)(a2 + 0x84);
  if ( a5 )
  {
    result = *(_QWORD *)(a2 + 0x70);
    --*(_DWORD *)(result + 0xEC);
  }
  _InterlockedAdd((volatile signed __int32 *)(v5 + 0xD8), 0xFFFFFFFF);
  v8 = *(_QWORD *)(a2 + 112);
  if ( !*(_DWORD *)(v8 + 16) )
  {
    v9 = 0i64;
    if ( (((unsigned int)&loc_200FF + 1) & *(_DWORD *)(v8 + 4)) == 0 || *(_DWORD *)(v8 + 8) == 5 )
    {
      while ( 1 )
      {
        v10 = v9 ? *((_QWORD *)v9 + 12) : *(_QWORD *)(v8 + 48);
        result = v8 + 48;
        if ( v10 == v8 + 48 )
          break;
        v9 = (unsigned __int16 *)(v10 - 96);
        if ( !v9 )
          break;
        result = *v9;
        if ( (_WORD)result != 1796 && *((_DWORD *)v9 + 43) != 32 )
        {
          if ( *((_DWORD *)v9 + 34) )
            return result;
          if ( (_WORD)result == 1795 )
          {
            result = (__int64)(v9 + 252);
            if ( *(_QWORD *)result != result )
              return result;
          }
          if ( *((_QWORD *)v9 + 24) && !_bittest((const signed __int32 *)v9 + 32, 0xAu) )
            return ((__int64 (__fastcall *)(__int64, unsigned __int16 *, bool, _QWORD))NtfsDeleteInternalAttributeStream)(
                     a1,
                     v9,
                     *(_WORD *)(v8 + 164) == 0,
                     0i64);
        }
      }
    }
  }
  return result;
}

3. 我的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
typedef VOID(*__fastcall pNtfsDecrementCleanupCounts)(__int64 a1, __int64 a2, __int64* a3, int a4, int a5);
pNtfsDecrementCleanupCounts NtfsDecrementCleanupCounts = NULL;
/*****************************************************************************
* @FunctionName : brief
* @Author : Thanatos
* @Date : 2023/10/4 19:38
* @Inparam : WCHAR* szPath 路径
* @Outparam :
*****************************************************************************/
NTSTATUS TestXCBFunction(WCHAR* szPath)
{
    NtfsDecrementCleanupCounts = 0xFFFFF88001261660;
     
 
    IO_STATUS_BLOCK ioStatus;
 
 
    HANDLE handle;
 
    WCHAR tmppath[MAX_PATH] = { 0 };
 
    wcscpy(tmppath, L"\\??\\");
    wcscat(tmppath, szPath);
 
 
    UNICODE_STRING uDeletePathName;
    RtlInitUnicodeString(&uDeletePathName, tmppath);
 
 
    OBJECT_ATTRIBUTES                 objAttributes = { 0 };
    InitializeObjectAttributes(&objAttributes, &uDeletePathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
 
 
    NTSTATUS ntStatus = ZwCreateFile(
        &handle,
        SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
        &objAttributes,
        &ioStatus,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        FILE_OPEN,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0);
    if (NT_SUCCESS(ntStatus))
    {
        PFILE_OBJECT FileObject;
 
        ntStatus = ObReferenceObjectByHandle(handle,
            DELETE,
            *IoFileObjectType,
            KernelMode,
            &FileObject,
            NULL);
 
        if (!NT_SUCCESS(ntStatus))
        {
            ZwClose(handle);
            return ntStatus;
        }
 
 
        if (MmIsAddressValid(NtfsDecrementCleanupCounts))
        {
 
            PVOID pSCB = FileObject->FsContext;
            PVOID pCCB = FileObject->FsContext2;
 
            NtfsDecrementCleanupCounts(0, pSCB, 0, FileObject->Flags & 8, 0);
 
        }
        else
        {
            ntStatus = STATUS_INVALID_PARAMETER;
        }
 
 
        ObDereferenceObject(FileObject);
 
        ZwClose(handle);
 
 
 
 
 
    }
 
    kprintf("ntStatus %ws %x\n", szPath, ntStatus);
    return ntStatus;
}

第一次写。。。不知道怎么去描述


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回