打开三环的exe,发现是一个MFC的程序。可以看到打开之后创建了一个线程
线程中调用了 NtQuerySystemInformation
,并将 D3DCompile
作为了参数中的一员,初步分析是用于通信的代码。接下来到驱动中找对应的通信函数。
在 sub_140001438
中,可以看到调用了 ZwSetSystemInformation
,且providersinature和三环传入的参数相同。可以判定这里是在注册通信。 sub_1400013E0
是通信的处理函数。
跟进去可以发现 sub_1400014A0
是真正的通信处理函数。至此可以判断三环并没有进行什么操作,只是与零环进行了通信,主要逻辑都在零环实现。
这个函数中,首先获取了 dwm.exe
的 eprocess
和 pid
,然后进行了获取模块地址和获取函数地址的初始化操作。
接下来根据系统版本的不同,用不同的方法寻找特征码并定位到需要hook的函数
接下来申请了两块内存,然后将驱动中保存的 shellcode
进行相应的解密并填充到申请的内存地址中去
之后进行了shellcode中一些参数的填充
在完成参数的填充后,使用mdl+锁页写内存方式,对dwm.exe中dxgi.dll的相关内容进行修改,达到hook的目的。
5秒之后重新使用同样的方式,将hook恢复。因此图像只能被绘制5秒。
再过1.5秒对shellcode的内存进行释放操作
为了方便之后shellcode的定位,这里将恢复hook和释放内存的代码进行patch,使得shellcode和hook不会被清除。分别将+18cb和+19ab处的 jz
改为 jmp
。
使用CE在 dxgi.dll
中对相应特征码进行查找,可以找到在我本机(21h2)中,hook的位置为 dxgi.dll+6EFC0
。hook后该地址中的内容如下
由于该驱动向dwm.exe中注入了shellcode,因此在shellcode被解密之后使用windbg将shellcode dump下来进行分析。shellcode中的内容如下。
可以看到和初赛的题目类似,也是有三个函数,点进去看也是使用opcode的虚拟机代码。但是发现sub_0并没有发生任何改变。因此这里直接套用我初赛时的代码对其进行分析。分析发现与初赛不同,本次shellcode的绘制并不是先画11个格子的flag再画31个格子的ACE,而是不按顺序地画。因此需要将初赛时的hookhandler函数稍加修改。每次发现坐标在 -1~1
之外的格子时进行旗帜的绘制。修改后的代码如下
为了让钩子正确挂到shellcode+30e的位置,需要进行的流程如下
以下为关键部分的代码。分别在 2022GameSafeRace+1657
和 2022GameSafeRace+1791
处挂上inlinehook。hookhandler函数中进行的操作已经在上面给出描述,这里不贴具体代码。
在注入dll并按步骤加载驱动后,可以看到flag被正确绘制了出来。
使用github上的一个开源项目https://github.com/lainswork/dwm-screen-shot ,可以截图。
截图的效果如下
为了给屏幕上的内容进行截图,想到可以对directX中处理swapchain的函数进行hook。直接从swapchain中取出渲染的图像。这样就能绕过通过将图像绘制在不同dc上而达到的反截图效果。一些游戏辅助的绘制代码也是使用了这个思路,对dwm.exe中swapchain相关的一些函数进行挂钩,然后直接在这里面进行绘制,这样就能绕过一般的截图方法。
具体代码删掉了,找别人要的一份绘制的代码,闭源的,不好往出发(,简单来说就是找了一个hook点,可以拿到swapchain。
这里用了DirectXTK库里面的 SaveWICTextureToFile
来将图像保存到硬盘上,代码如下。
最后将得到的dll注入到dwm.exe中,可以成功得到截图。
EXTERN_C VOID HookHandler(PGuestContext context)
{
static
bool
flag
=
false;
if
(!flag) { flag
=
true; A(
"inline hook成功!"
); }
float
xgap
=
0.064935
, ygap
=
0.118343
;
/
/
同一格子内部距离
float
xbet
=
0.012987
, ybet
=
0.023669
;
/
/
两个相邻格子之间的距离
float
trans
=
getScreenZoom()
/
1.25
;
xgap
*
=
trans, ygap
*
=
trans, xbet
*
=
trans, ybet
*
=
trans;
/
/
进行缩放
float
origin_a1_x
=
-
0.9305
;
float
origin_a1_y
=
0.906692
;
if
(fabs(getScreenZoom()
-
1.00
) < eps) origin_a1_y
=
0.906692
;
/
/
缩放
100
%
else
if
(fabs(getScreenZoom()
-
1.25
) < eps) origin_a1_y
=
0.882840
;
/
/
缩放
125
%
else
if
(fabs(getScreenZoom()
-
1.50
) < eps) origin_a1_y
=
0.858773
;
/
/
缩放
150
%
else
if
(fabs(getScreenZoom()
-
1.75
) < eps) origin_a1_y
=
0.834448
;
/
/
缩放
175
%
if
(fabs(getScreenZoom()
-
1.00
) < eps) origin_a1_x
=
-
0.9472
;
/
/
缩放
100
%
else
if
(fabs(getScreenZoom()
-
1.25
) < eps) origin_a1_x
=
-
0.9305
;
/
/
缩放
125
%
else
if
(fabs(getScreenZoom()
-
1.50
) < eps) origin_a1_x
=
-
0.9236
;
/
/
缩放
150
%
else
if
(fabs(getScreenZoom()
-
1.75
) < eps) origin_a1_x
=
-
0.9139
;
/
/
缩放
175
%
PInfo info
=
(PInfo)(context
-
>mRcx);
static
int
ct
=
0
;
ct
+
+
;
static
int
wrong_ct
=
0
;
bool
wrong_flag
=
false;
if
(info
-
>a1.x <
-
1.0
|| info
-
>a1.x >
1.0
||
info
-
>a2.x <
-
1.0
|| info
-
>a2.x >
1.0
||
info
-
>a3.x <
-
1.0
|| info
-
>a3.x >
1.0
||
info
-
>a4.x <
-
1.0
|| info
-
>a4.x >
1.0
||
info
-
>a1.y <
-
1.0
|| info
-
>a1.y >
1.0
||
info
-
>a2.y <
-
1.0
|| info
-
>a2.y >
1.0
||
info
-
>a3.y <
-
1.0
|| info
-
>a3.y >
1.0
||
info
-
>a4.y <
-
1.0
|| info
-
>a4.y >
1.0
)
{
wrong_flag
=
true;
wrong_ct
+
+
;
}
if
(wrong_flag)
{
if
(wrong_ct <
=
6
)
{
float
a1x
=
origin_a1_x;
float
a1y
=
origin_a1_y
-
(wrong_ct
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct <
=
9
)
{
float
a1x
=
origin_a1_x
+
(wrong_ct
-
6
)
*
(xgap
+
xbet);
float
a1y
=
origin_a1_y
-
(
4
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct
=
=
10
)
{
float
a1x
=
origin_a1_x
+
(
7
-
6
)
*
(xgap
+
xbet);
float
a1y
=
origin_a1_y
-
(
2
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct
=
=
11
)
{
float
a1x
=
origin_a1_x
+
(
8
-
6
)
*
(xgap
+
xbet);
float
a1y
=
origin_a1_y
-
(
3
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
wrong_ct
=
0
;
}
}
if
(ct
=
=
42
) ct
=
0
;
}
EXTERN_C VOID HookHandler(PGuestContext context)
{
static
bool
flag
=
false;
if
(!flag) { flag
=
true; A(
"inline hook成功!"
); }
float
xgap
=
0.064935
, ygap
=
0.118343
;
/
/
同一格子内部距离
float
xbet
=
0.012987
, ybet
=
0.023669
;
/
/
两个相邻格子之间的距离
float
trans
=
getScreenZoom()
/
1.25
;
xgap
*
=
trans, ygap
*
=
trans, xbet
*
=
trans, ybet
*
=
trans;
/
/
进行缩放
float
origin_a1_x
=
-
0.9305
;
float
origin_a1_y
=
0.906692
;
if
(fabs(getScreenZoom()
-
1.00
) < eps) origin_a1_y
=
0.906692
;
/
/
缩放
100
%
else
if
(fabs(getScreenZoom()
-
1.25
) < eps) origin_a1_y
=
0.882840
;
/
/
缩放
125
%
else
if
(fabs(getScreenZoom()
-
1.50
) < eps) origin_a1_y
=
0.858773
;
/
/
缩放
150
%
else
if
(fabs(getScreenZoom()
-
1.75
) < eps) origin_a1_y
=
0.834448
;
/
/
缩放
175
%
if
(fabs(getScreenZoom()
-
1.00
) < eps) origin_a1_x
=
-
0.9472
;
/
/
缩放
100
%
else
if
(fabs(getScreenZoom()
-
1.25
) < eps) origin_a1_x
=
-
0.9305
;
/
/
缩放
125
%
else
if
(fabs(getScreenZoom()
-
1.50
) < eps) origin_a1_x
=
-
0.9236
;
/
/
缩放
150
%
else
if
(fabs(getScreenZoom()
-
1.75
) < eps) origin_a1_x
=
-
0.9139
;
/
/
缩放
175
%
PInfo info
=
(PInfo)(context
-
>mRcx);
static
int
ct
=
0
;
ct
+
+
;
static
int
wrong_ct
=
0
;
bool
wrong_flag
=
false;
if
(info
-
>a1.x <
-
1.0
|| info
-
>a1.x >
1.0
||
info
-
>a2.x <
-
1.0
|| info
-
>a2.x >
1.0
||
info
-
>a3.x <
-
1.0
|| info
-
>a3.x >
1.0
||
info
-
>a4.x <
-
1.0
|| info
-
>a4.x >
1.0
||
info
-
>a1.y <
-
1.0
|| info
-
>a1.y >
1.0
||
info
-
>a2.y <
-
1.0
|| info
-
>a2.y >
1.0
||
info
-
>a3.y <
-
1.0
|| info
-
>a3.y >
1.0
||
info
-
>a4.y <
-
1.0
|| info
-
>a4.y >
1.0
)
{
wrong_flag
=
true;
wrong_ct
+
+
;
}
if
(wrong_flag)
{
if
(wrong_ct <
=
6
)
{
float
a1x
=
origin_a1_x;
float
a1y
=
origin_a1_y
-
(wrong_ct
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct <
=
9
)
{
float
a1x
=
origin_a1_x
+
(wrong_ct
-
6
)
*
(xgap
+
xbet);
float
a1y
=
origin_a1_y
-
(
4
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct
=
=
10
)
{
float
a1x
=
origin_a1_x
+
(
7
-
6
)
*
(xgap
+
xbet);
float
a1y
=
origin_a1_y
-
(
2
-
1
)
*
(ygap
+
ybet);
info
-
>a1.x
=
a1x, info
-
>a1.y
=
a1y;
info
-
>a2.x
=
a1x
+
xgap, info
-
>a2.y
=
a1y;
info
-
>a3.x
=
a1x, info
-
>a3.y
=
a1y
-
ygap;
info
-
>a4.x
=
a1x
+
xgap, info
-
>a4.y
=
a1y
-
ygap;
}
else
if
(wrong_ct
=
=
11
)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课