嗨嗨嗨
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逻辑的情况下可以监控这条线程,当线程启动时关闭绘制,线程结束时启动绘制即可,仅针对上文逻辑。