是开源项目,先放个链接:BlindEye
通过hook BattlEye内核模块导入的 ExAllocatePool
、ExAllocatePoolWithTag
函数,过滤掉report数据包的内存申请,实现内核检测bypass。
如下图所示,BattlEye内核模块的导入表中只导入了很少的系统函数,例如:MmGetSystemRoutineAddress
、FltGetRoutineAddress
等。其余大量导入函数是通过调用MmGetSystemRoutineAddress
、FltGetRoutineAddress
获得的。
BattlEye内核模块在发现异常情况时会发送数据包,通过逆向分析脱掉vmp之后的代码,可以看到上报代码如下所示。
其数据结构如下:
注意到:
本项目基于GoodEye开发。
通过调用PsSetLoadImageNotifyRoutine
注册回调,监控BEDaisy.sys内核模块的加载,通过IAT hook MmGetSystemRoutineAddress
函数,在BattlEye模块调用MmGetSystemRoutineAddress
获得其他导入函数地址时,再次返回对应hook函数地址,以此实现hook其他导入函数。
我们需要hook的函数是ExAllocatePool
、ExAllocatePoolWithTag
,在函数中过滤掉类型为PagedPool
,大小为24的申请内存的请求。
需要注意的是,有些其他函数也会调用ExAllocatePool
、ExAllocatePoolWithTag
这两个函数申请内存,我们需要将这些请求放行,否则BattlEye无法正常启动。我使用的方法是白名单策略,如果调用者以前申请过不被过滤的内存,则该调用者列入白名单,后续的所有申请都会放行。只过滤不在白名单且类型为PagedPool
,大小为24的申请。
具体代码如下:
BattlEye去虚拟化内核模块
BattlEye逆向分析
GoodEye
好久没发帖子了,本来以为上了大学就能专心学技术了,没想到大学竟然这么卷,大一一整年全都在学数学,就没咋学计算机,为了多拿点绩点,后面能去个好学校读研究生,我也跟别人一起卷。
现在马上大三了,数学课都上完了,全是计算机专业课,我学起来也比较轻松,也就能有更多的时间自己学技术了。这个学期抽时间在guided hacking上把GHB1,2,3都学了一遍,目前正在学GHB4,感觉主讲人Rake讲的确实不错,把视频看懂了,再跟着做一做练习确实很有收获,在此推荐一下(没有广告费)。
来个下期预告吧,这个假期应该会完成一个FPS hacking template/framework,算是在guided hacking上的学习总结吧,现在已经初步成型,感兴趣的可以提前关注一下:assualt-cube-hacking。
void __fastcall daisy::report::custom(const void
*
Buffer
, __int64 Size, ReportNode
*
*
Head, ReportNode
*
*
Tail)
{
ReportNode
*
Node;
/
/
rbx
void
*
Data;
/
/
rax
Node
=
(ReportNode
*
)fn_ExAllocatePool(
1i64
,
24i64
);
if
( Node )
{
Data
=
(void
*
)fn_ExAllocatePool(
1i64
, Size);
Node
-
>Data
=
Data;
if
( Data )
{
Node
-
>Size
=
Size;
memmove(Data,
Buffer
, (unsigned
int
)Size);
Node
-
>
Next
=
0i64
;
Node
-
>UnknownFlag
=
0
;
fn_KeWaitForSingleObject(&g_Mutex,
0i64
,
0i64
,
0i64
,
0i64
);
if
(
*
Head )
(
*
Tail)
-
>
Next
=
Node;
else
*
Head
=
Node;
*
Tail
=
Node;
fn_KeReleaseMutex(&g_Mutex,
0i64
);
}
else
{
fn_ExFreePoolWithTag(Node,
0i64
);
}
}
}
void __fastcall daisy::report::custom(const void
*
Buffer
, __int64 Size, ReportNode
*
*
Head, ReportNode
*
*
Tail)
{
ReportNode
*
Node;
/
/
rbx
void
*
Data;
/
/
rax
Node
=
(ReportNode
*
)fn_ExAllocatePool(
1i64
,
24i64
);
if
( Node )
{
Data
=
(void
*
)fn_ExAllocatePool(
1i64
, Size);
Node
-
>Data
=
Data;
if
( Data )
{
Node
-
>Size
=
Size;
memmove(Data,
Buffer
, (unsigned
int
)Size);
Node
-
>
Next
=
0i64
;
Node
-
>UnknownFlag
=
0
;
fn_KeWaitForSingleObject(&g_Mutex,
0i64
,
0i64
,
0i64
,
0i64
);
if
(
*
Head )
(
*
Tail)
-
>
Next
=
Node;
else
*
Head
=
Node;
*
Tail
=
Node;
fn_KeReleaseMutex(&g_Mutex,
0i64
);
}
else
{
fn_ExFreePoolWithTag(Node,
0i64
);
}
}
}
void __fastcall daisy::report::normal(const void
*
Buffer
,
int
Size)
{
ReportNode
*
Node;
/
/
rbx
void
*
Data;
/
/
rax
int
Key;
/
/
eax
char ByteKey;
/
/
r8
char
*
EncryptBuffer;
/
/
rcx
int
i;
/
/
edx
signed __int64 v10;
/
/
rdi
char t;
/
/
al
__int64 TickCount;
/
/
[rsp
+
50h
] [rbp
+
18h
] BYREF
Node
=
(ReportNode
*
)fn_ExAllocatePoolWithTag(
1i64
,
24i64
,
'EB'
);
if
( Node )
{
Node
-
>Size
=
Size
+
4
;
Data
=
(void
*
)fn_ExAllocatePoolWithTag(
1i64
, (unsigned
int
)(Size
+
4
),
'EB'
);
/
/
the first
4
bytes
is
the key
Node
-
>Data
=
Data;
if
( Data )
{
TickCount
=
MEMORY[
0xFFFFF78000000320
];
Key
=
fn_RtlRandomEx(&TickCount);
ByteKey
=
Key;
*
(_DWORD
*
)Node
-
>Data
=
Key;
EncryptBuffer
=
(char
*
)Node
-
>Data
+
4
;
if
( Node
-
>Data
=
=
(PVOID)
-
4i64
)
/
/
WTF?
EncryptBuffer
=
(char
*
)
Buffer
;
i
=
0
;
if
( Size >
0
)
{
v10
=
(_BYTE
*
)
Buffer
-
EncryptBuffer;
do
{
t
=
i
+
+
^ ByteKey ^ EncryptBuffer[v10];
/
/
EncryptBuffer[v10] just means
Buffer
[i]
t ^
=
0xA5u
;
*
EncryptBuffer
+
+
=
t;
ByteKey
=
~t;
}
while
( i < Size );
}
Node
-
>
Next
=
0i64
;
fn_KeWaitForSingleObject(&g_Mutex,
0i64
,
0i64
,
0i64
,
0i64
);
if
( g_EncryptHead )
g_EncryptTail
-
>
Next
=
Node;
else
g_EncryptHead
=
Node;
g_EncryptTail
=
Node;
fn_KeReleaseMutex(&g_Mutex,
0i64
);
}
else
{
fn_ExFreePoolWithTag(Node,
0i64
);
}
}
}
void __fastcall daisy::report::normal(const void
*
Buffer
,
int
Size)
{
ReportNode
*
Node;
/
/
rbx
void
*
Data;
/
/
rax
int
Key;
/
/
eax
char ByteKey;
/
/
r8
char
*
EncryptBuffer;
/
/
rcx
int
i;
/
/
edx
signed __int64 v10;
/
/
rdi
char t;
/
/
al
__int64 TickCount;
/
/
[rsp
+
50h
] [rbp
+
18h
] BYREF
Node
=
(ReportNode
*
)fn_ExAllocatePoolWithTag(
1i64
,
24i64
,
'EB'
);
if
( Node )
{
Node
-
>Size
=
Size
+
4
;
Data
=
(void
*
)fn_ExAllocatePoolWithTag(
1i64
, (unsigned
int
)(Size
+
4
),
'EB'
);
/
/
the first
4
bytes
is
the key
Node
-
>Data
=
Data;
if
( Data )
{
TickCount
=
MEMORY[
0xFFFFF78000000320
];
Key
=
fn_RtlRandomEx(&TickCount);
ByteKey
=
Key;
*
(_DWORD
*
)Node
-
>Data
=
Key;
EncryptBuffer
=
(char
*
)Node
-
>Data
+
4
;
if
( Node
-
>Data
=
=
(PVOID)
-
4i64
)
/
/
WTF?
EncryptBuffer
=
(char
*
)
Buffer
;
i
=
0
;
if
( Size >
0
)
{
v10
=
(_BYTE
*
)
Buffer
-
EncryptBuffer;
do
{
t
=
i
+
+
^ ByteKey ^ EncryptBuffer[v10];
/
/
EncryptBuffer[v10] just means
Buffer
[i]
t ^
=
0xA5u
;
*
EncryptBuffer
+
+
=
t;
ByteKey
=
~t;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2022-6-17 15:58
被鬼才zxy编辑
,原因: