首页
社区
课程
招聘
[原创]xhunter1针对DWM行为分析
2022-12-29 18:10 8745

[原创]xhunter1针对DWM行为分析

2022-12-29 18:10
8745
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
嗨嗨嗨
 
1.位于xhunter1.sys的驱动回调内部有对dwm进程注入shellcode的操作,具体操作如下。
__int64 __fastcall CheckDwm_CreateThreadShellCode(__int64 a1, __int64 a2)
{
  *(_DWORD *)a2 = 0x270;
  *(_DWORD *)(a2 + 4) = 0x12121212;
  *(_DWORD *)(a2 + 12) = 0xC0000001;
  *(_DWORD *)(a2 + 8) = ~*(_DWORD *)(a1 + 8);
  *(_DWORD *)(a2 + 12) = sub_1400087DC(a1 + 24, (PVOID *)(a2 + 16));
  return 0i64;
}
 
2.关于获取DWM的几种方式,猜测可能因为样本对DWM进程处理,导致AC无法注入DWM进程。
__int64 __fastcall sub_1400087DC(__int64 a1, PVOID *a2)
{
  int v4; // ebx
  void *Handle; // rcx
  void *tid; // rcx
  PVOID Object; // [rsp+40h] [rbp+20h] BYREF
  PETHREAD Thread; // [rsp+50h] [rbp+30h] BYREF
 
  Object = 0i64;
  v4 = 0xC000000D;
  if ( (*(_BYTE *)(a1 + 72) & 1) != 0 )
  {
    Handle = *(void **)a1;                      // 通过句柄查DWM
    if ( Handle )
    {
      v4 = HandleToObject(Handle, 0x1000u, &Object);
      if ( v4 >= 0 )
      {
        v4 = ShellCodeCheckDwm(a1, a2, Object);
        ObfDereferenceObject(Object);
        if ( v4 >= 0 )
          goto LABEL_18;
      }
    }
  }
  if ( (*(_BYTE *)(a1 + 72) & 4) != 0 )
  {
    tid = *(void **)(a1 + 16);                  // 通过线程查DWM
    if ( tid )
    {
      v4 = PsLookupThreadByThreadId(tid, &Thread);
      if ( v4 >= 0 )
      {
        Object = IoThreadToProcess(Thread);
        ObfReferenceObject(Object);
        v4 = ShellCodeCheckDwm(a1, a2, Object);
        ObfDereferenceObject(Object);
        ObfDereferenceObject(Thread);
        if ( v4 >= 0 )
          goto LABEL_18;
      }
    }
  }
  if ( (*(_BYTE *)(a1 + 72) & 2) != 0 )
  {
    v4 = PsLookupProcessByProcessId(*(HANDLE *)(a1 + 8), (PEPROCESS *)&Object);// 通过进程ID查DWM
    if ( v4 >= 0 )
    {
      v4 = ShellCodeCheckDwm(a1, a2, Object);
      ObfDereferenceObject(Object);
      if ( v4 >= 0 )
        goto LABEL_18;
    }
  }
  if ( (*(_BYTE *)(a1 + 72) & 8) != 0
    && (v4 = sub_14000AF40(*(_QWORD *)(a1 + 8), &Object), v4 >= 0)// 遍历进程获取Csrss名字的进程ID 在查DWM
    && (v4 = ShellCodeCheckDwm(a1, a2, Object), ObfDereferenceObject(Object), v4 >= 0)
    || (*(_BYTE *)(a1 + 72) & 0x10) != 0
    && (v4 = sub_14000B2F4(*(_QWORD *)(a1 + 8), &Object), v4 >= 0)// 遍历获取Winlogon进程ID
    && (v4 = ShellCodeCheckDwm(a1, a2, Object), ObfDereferenceObject(Object), v4 >= 0) )
  {
LABEL_18:
    _mm_lfence();
  }
  return (unsigned int)v4;
}
 
3.组装ShellCode并在目标进程内部运行
__int64 __fastcall ShellCodeCheckDwm(__int64 a1, PVOID *a2, void *processObj)
{
  void *R0Buf_2; // r13
  unsigned int v7; // edi
  unsigned __int64 len_1; // rsi
  void *R0Buf_1; // r14
  int v11; // esi
  char *v12; // rcx
  ULONG len; // edi
  _OWORD *R0Buf; // rax
  int v15; // eax
  _BYTE *v16; // rax
  __int64 v17; // r8
  char v18; // bl
  _BYTE *v19; // rdi
  PVOID BaseAddress; // [rsp+60h] [rbp-79h] BYREF
  HANDLE ProcessHandle; // [rsp+68h] [rbp-71h] BYREF
  unsigned int v22; // [rsp+70h] [rbp-69h]
  HANDLE v23; // [rsp+78h] [rbp-61h] BYREF
  ULONG_PTR RegionSize; // [rsp+80h] [rbp-59h] BYREF
  __int128 v25; // [rsp+88h] [rbp-51h] BYREF
  __int128 v26; // [rsp+98h] [rbp-41h]
  __int128 v27; // [rsp+A8h] [rbp-31h]
  __int128 v28; // [rsp+B8h] [rbp-21h] BYREF
  struct _KAPC_STATE ApcState; // [rsp+C8h] [rbp-11h] BYREF
 
  RegionSize = 16772i64;
  R0Buf_2 = &unk_140012430;
  v7 = 8976;
  ProcessHandle = 0i64;
  BaseAddress = 0i64;
  len_1 = 12288i64;
  v22 = 8976;
  R0Buf_1 = 0i64;
  if ( !qword_140018080 )
    return 3759800330i64;
  if ( !RtlCreateUserThread && !qword_140018158 )
    return 3759862303i64;
  if ( ObOpenObjectByPointer(processObj, 0x200u, 0i64, 0x1FFFFFu, (POBJECT_TYPE)PsProcessType, 0, &ProcessHandle) < 0 )
  {
    v11 = -535105512;
LABEL_33:
    if ( BaseAddress )
    {
      RegionSize = 0i64;
      ZwFreeVirtualMemory(ProcessHandle, &BaseAddress, &RegionSize, 0x8000u);
    }
    goto LABEL_35;
  }
  if ( ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, 0i64, &RegionSize, 0x3000u, 0x40u) < 0 )
  {
    v11 = -535105513;
    goto LABEL_33;
  }
  if ( BaseAddress )
  {
    v12 = *(char **)(a1 + 48);
    if ( v12 )
    {
      len = *(_DWORD *)(a1 + 56);
      R0Buf = CopyR3BufToR0(v12, len);
      R0Buf_1 = R0Buf;
      if ( R0Buf )
      {
        len_1 = len;
        R0Buf_2 = R0Buf;
        v7 = *(_DWORD *)(a1 + 64);
        v22 = v7;
      }
      else
      {
        v7 = 8976;
      }
    }
    if ( (int)AssembleShellCode((struct _KPROCESS *)processObj, BaseAddress, (_QWORD *)a1, (__int64)R0Buf_2, len_1) < 0 )// 可能是组装ShellCode
    {
      v11 = 0xE01AF039;
      goto LABEL_31;
    }
    v23 = 0i64;
    v28 = 0i64;
    if ( RtlCreateUserThread )
    {
      if ( RtlCreateUserThread(
             ProcessHandle,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             (char *)BaseAddress + v7,
             BaseAddress,
             &v23,
             &v28) < 0 )
      {
        v11 = -535104991;
        goto LABEL_31;
      }
    }
    else
    {
      if ( !qword_140018158 )
      {
LABEL_30:
        v11 = -535104743;
        goto LABEL_31;
      }
      v25 = 0i64;
      v26 = 0i64;
      v27 = 0i64;
      KeStackAttachProcess_0((PRKPROCESS)processObj, &ApcState);
      if ( v15 >= 0 )
      {
        v16 = (_BYTE *)(*(__int64 (__fastcall **)(struct _KTHREAD *))(qword_140018180 + 128))(KeGetCurrentThread());
        v17 = v22;
        v18 = *v16;
        v19 = v16;
        *v16 = 0;
        LODWORD(v25) = 48;
        *((_QWORD *)&v25 + 1) = 0i64;
        DWORD2(v26) = 512;
        *(_QWORD *)&v26 = 0i64;
        v27 = 0i64;
        v11 = qword_140018158(
                &v23,
                0x1FFFFFi64,
                &v25,
                -1i64,
                (char *)BaseAddress + v17,
                BaseAddress,
                4,
                0i64,
                4096i64,
                0x100000i64,
                0i64);
        KeUnstackDetachProcess_0(&ApcState);
        *v19 = v18;
        if ( v11 < 0 )
        {
LABEL_31:
          if ( R0Buf_1 )
            ExFreePoolWithTag(R0Buf_1, 0x78687A31u);
          goto LABEL_33;
        }
      }
    }
    if ( v23 )
    {
      ZwWaitForSingleObject(v23, 0, 0i64);
      ZwClose(v23);
      v11 = sub_1400078FC((struct _KPROCESS *)processObj, ProcessHandle, BaseAddress, (__int64)a2);
      if ( v11 >= 0 )
      {
        if ( (int)R0BufToR3_FreeR0(a2) >= 0 )
        {
          v11 = 0;
        }
        else
        {
          ExFreePoolWithTag(*a2, 0x78687A31u);
          v11 = 0xE01AF31A;
        }
      }
      goto LABEL_31;
    }
    goto LABEL_30;
  }
  v11 = 0xE01AF018;
LABEL_35:
  if ( ProcessHandle )
    ZwClose(ProcessHandle);
  return (unsigned int)v11;
}
 
4.具体组装ShellCode的逻辑。
__int64 __fastcall AssembleShellCode(struct _KPROCESS *a1, void *buf, _QWORD *a3, __int64 R0Buf, unsigned __int64 len)
{
  int v7; // eax
  ULONG64 r0buf; // rax
  const void *v10; // rdx
  void *r0buf_1; // rbx
  PMDL mdl; // [rsp+20h] [rbp-58h] BYREF
  struct _KAPC_STATE ApcState; // [rsp+28h] [rbp-50h] BYREF
 
  mdl = 0i64;
  KeStackAttachProcess_0(a1, &ApcState);
  if ( v7 < 0 )
    return 0xE01AF031i64;
  r0buf = (ULONG64)LockMemR0(buf, 0x4184u, &mdl);
  r0buf_1 = (void *)r0buf;
  if ( r0buf )
  {
    *(_DWORD *)(r0buf + 16532) = 0xE01AF119;
    strcpy((char *)(r0buf + 16652), "dwmcore.dll");
    strcpy((char *)(r0buf + 16612), "gdi32.dll");
    strcpy((char *)(r0buf + 16632), "user32.dll");
    *(_QWORD *)(r0buf + 16712) = a3[3];
    *(_QWORD *)(r0buf + 16720) = a3[4];
    *(_QWORD *)(r0buf + 16728) = a3[5];
    memcpy((void *)r0buf, v10, len);
    unLockMemR0(mdl, r0buf_1);
    KeUnstackDetachProcess_0(&ApcState);
    return 0i64;
  }
  else
  {
    KeUnstackDetachProcess_0(&ApcState);
    return 0xE01AF037i64;
  }
}
 
总结:R3传递参数通过调用驱动接口,驱动接口内部解析参数获的注入的进程、组装来自R3的ShellCode,并在目标进程内部运行ShellCode,由于都是静态分析,未见具体ShellCode逻辑,分析到此为止。
 
绕过:已知xhunter1.sys驱动会注入DWM进程,在未知ShellCode逻辑的情况下可以监控这条线程,当线程启动时关闭绘制,线程结束时启动绘制即可,仅针对上文逻辑。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞2
打赏
分享
最新回复 (7)
雪    币: 37
活跃值: (1888)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
X-Blades 2022-12-29 18:23
2
0

雪    币: 6124
活跃值: (4056)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
黑洛 1 2022-12-29 18:26
3
0

雪    币: 74
活跃值: (7195)
能力值: ( LV9,RANK:335 )
在线值:
发帖
回帖
粉丝
PlaneJun 6 2022-12-30 09:41
4
0

雪    币: 671
活跃值: (3246)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
dx苹果的心愿 1 2022-12-30 09:52
5
0

雪    币: 1519
活跃值: (1982)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
Chords 2022-12-30 12:58
6
0

雪    币: 187
活跃值: (2406)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
杰克王 2022-12-30 13:17
7
0
雪    币: 187
活跃值: (2406)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
杰克王 2022-12-30 13:18
8
0
黑洛
我tm千手观音
游客
登录 | 注册 方可回帖
返回