-
-
[原创]2022腾讯游戏安全竞赛PC赛道初赛writeup
-
发表于: 2022-4-20 02:23 8886
-
补丁:
分析过程:
IDA静态分析,互斥体防多开,窗口创建流程,D3D设备初始化,窗口消息循环处初始化shellcode并调用DX绘制流程
运行后一段时间程序停止绘制,在绘制流程中把GetTickCount相关时间检测的流程打补丁,不过多赘述
根据文档说明需要将一面黄色的棋子绘制出来,首先猜测可能跟顶点的绘制模式有关,ida动态调试加载符号信息,将DX相关的虚函数进行标识
IASetPrimitiveTopology 的参数依据msdn尝试修改一下,然而蓝色的方块有变化,黄色方块依旧没有画出来,感觉走远了。
回到shellcode的初始化过程中
shellcode调用的地方首先是对一些绘制的buffer进行初始化,然后调用一个解析器,最后对buffer进行回收,buffer初始化和回收的代码就不贴了,直接贴解析器部分的代码
7种命令
case 0是加法,case 1 是减法,case 2是存储器到存储器的赋值,case 3是立即数到存储器的赋值,case 4是某种加密算法,经过一些简单补丁可以验证case 5是画黄色方块 case 6画蓝色方块,case 7是程序退出
简单的写一个py脚本
case 4好像写的不太对,先凑合着用
然后经过修修改改一段时间发现画case 6的跟画case 5的不太一样啊,明明都是画方块,不太对劲
画case 6即蓝色方块
画case 5即黄色方块
蓝色方块绘制流程中crypt之后只有两条语句
黄色方块绘制流程中crypt之后还有额外的三条语句
所以这个ce搜一下批量打一下补丁
(当然全部改成8也可以,switch case default分支会自动到下一个指令)
然后找了个蓝色方块修改一下立即数赋值的语句,感受一下坐标系,发现黄色方块中的立即数赋值不太合理,手动修改一两个发现黄色方块回来了,于是乎把赋值为500和1000修改一下
02
00
00
00
00
00
00
00
03
00
00
00
02
00
00
00
01
00
00
00
00
00
00
00
02
00
00
00
03
00
00
00
01
00
00
00
=
>
02
00
00
00
00
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
03
00
00
00
E8
03
00
00
=
>
03
00
00
00
00
00
00
00
03
00
00
00
F4
01
00
00
=
>
03
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
03
00
00
00
02
00
00
00
01
00
00
00
00
00
00
00
02
00
00
00
03
00
00
00
01
00
00
00
=
>
02
00
00
00
00
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
03
00
00
00
E8
03
00
00
=
>
03
00
00
00
00
00
00
00
03
00
00
00
F4
01
00
00
=
>
03
00
00
00
00
00
00
00
__int64 __usercall sub_7FF62C2E5040@<rax>(...)
{
/
*
省略一些代码
*
/
*
(_OWORD
*
)(a1
-
72
)
=
a6;
*
(_OWORD
*
)(a1
-
88
)
=
a7;
*
(_OWORD
*
)(a1
-
104
)
=
a8;
v20
=
a5;
*
(_OWORD
*
)(a1
-
120
)
=
a9;
v21
=
a4;
v22
=
a2;
v23
=
a3;
v24
=
*
(__int64
*
*
)&a16;
a12
=
1
;
v25
=
a15
+
(a4 ^ (a3
+
a2))
%
256
-
a5
%
256
;
(
*
(void (__fastcall
*
*
)(_QWORD, signed
int
*
, char
*
))(
*
*
(_QWORD
*
*
)&a16
+
0x2F8i64
))(
*
(_QWORD
*
)&a16, &a12, &v45);
/
/
RSGetViewports
v26
=
(v21 ^ v22
*
v23)
%
256
-
(v20 >>
8
)
%
256
;
v27
=
(
float
)(v47
-
(
float
)(
2
*
(v26
+
v22)
-
1
))
/
v47;
v28
=
(
float
)(v47
-
(
float
)(
2
*
v22
+
99
))
/
v47;
v29
=
(
float
)((
float
)(
2
*
(v26
+
v23)
-
1
)
-
v46)
/
v46;
v30
=
(
float
)((
float
)(
2
*
v23
+
99
)
-
v46)
/
v46;
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD, signed __int64, _DWORD,
float
*
*
))(
*
v24
+
0x70
))(
/
/
Map
v24,
*
(_QWORD
*
)&a17,
0i64
,
4i64
,
0
,
&v44);
/
*
....
*
/
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD))(
*
v24
+
0x78
))(v24,
*
(_QWORD
*
)&a17,
0i64
);
/
/
UnMap
v42
=
*
v24;
a14
=
28
;
a13
=
0
;
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, signed __int64,
int
*
, signed
int
*
,
int
*
))(v42
+
0x90
))(
/
/
IASetVertexBuffers
v24,
0i64
,
1i64
,
&a17,
&a14,
&a13);
(
*
(void (__fastcall
*
*
)(__int64
*
, signed __int64))(
*
v24
+
0xC0
))(v24,
5i64
);
/
/
IASetPrimitiveTopology
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64))(
*
v24
+
0x88
))(v24, a18);
/
/
IASetInputLayout
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64, _QWORD, _QWORD))(
*
v24
+
0x58
))(v24, a19,
0i64
,
0i64
);
/
/
SetShader
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64, _QWORD, _QWORD))(
*
v24
+
0x48
))(v24, a20,
0i64
,
0i64
);
/
/
SetShader
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD, _QWORD))(
*
v24
+
0xB8
))(v24,
0i64
,
0i64
,
0i64
);
/
/
SetShader
return
(
*
(__int64 (__fastcall
*
*
)(__int64
*
, signed __int64))(
*
v24
+
0x68
))(v24,
4i64
);
/
/
Draw
}
__int64 __usercall sub_7FF62C2E5040@<rax>(...)
{
/
*
省略一些代码
*
/
*
(_OWORD
*
)(a1
-
72
)
=
a6;
*
(_OWORD
*
)(a1
-
88
)
=
a7;
*
(_OWORD
*
)(a1
-
104
)
=
a8;
v20
=
a5;
*
(_OWORD
*
)(a1
-
120
)
=
a9;
v21
=
a4;
v22
=
a2;
v23
=
a3;
v24
=
*
(__int64
*
*
)&a16;
a12
=
1
;
v25
=
a15
+
(a4 ^ (a3
+
a2))
%
256
-
a5
%
256
;
(
*
(void (__fastcall
*
*
)(_QWORD, signed
int
*
, char
*
))(
*
*
(_QWORD
*
*
)&a16
+
0x2F8i64
))(
*
(_QWORD
*
)&a16, &a12, &v45);
/
/
RSGetViewports
v26
=
(v21 ^ v22
*
v23)
%
256
-
(v20 >>
8
)
%
256
;
v27
=
(
float
)(v47
-
(
float
)(
2
*
(v26
+
v22)
-
1
))
/
v47;
v28
=
(
float
)(v47
-
(
float
)(
2
*
v22
+
99
))
/
v47;
v29
=
(
float
)((
float
)(
2
*
(v26
+
v23)
-
1
)
-
v46)
/
v46;
v30
=
(
float
)((
float
)(
2
*
v23
+
99
)
-
v46)
/
v46;
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD, signed __int64, _DWORD,
float
*
*
))(
*
v24
+
0x70
))(
/
/
Map
v24,
*
(_QWORD
*
)&a17,
0i64
,
4i64
,
0
,
&v44);
/
*
....
*
/
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD))(
*
v24
+
0x78
))(v24,
*
(_QWORD
*
)&a17,
0i64
);
/
/
UnMap
v42
=
*
v24;
a14
=
28
;
a13
=
0
;
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, signed __int64,
int
*
, signed
int
*
,
int
*
))(v42
+
0x90
))(
/
/
IASetVertexBuffers
v24,
0i64
,
1i64
,
&a17,
&a14,
&a13);
(
*
(void (__fastcall
*
*
)(__int64
*
, signed __int64))(
*
v24
+
0xC0
))(v24,
5i64
);
/
/
IASetPrimitiveTopology
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64))(
*
v24
+
0x88
))(v24, a18);
/
/
IASetInputLayout
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64, _QWORD, _QWORD))(
*
v24
+
0x58
))(v24, a19,
0i64
,
0i64
);
/
/
SetShader
(
*
(void (__fastcall
*
*
)(__int64
*
, __int64, _QWORD, _QWORD))(
*
v24
+
0x48
))(v24, a20,
0i64
,
0i64
);
/
/
SetShader
(
*
(void (__fastcall
*
*
)(__int64
*
, _QWORD, _QWORD, _QWORD))(
*
v24
+
0xB8
))(v24,
0i64
,
0i64
,
0i64
);
/
/
SetShader
return
(
*
(__int64 (__fastcall
*
*
)(__int64
*
, signed __int64))(
*
v24
+
0x68
))(v24,
4i64
);
/
/
Draw
}
void __fastcall sub_7FF62C2E1090(__int64 a1)
{
/
*
...
*
/
v1
=
a1;
v2
=
*
(_QWORD
*
)(a1
+
0x28
);
if
( v2 )
{
v3
=
*
(_QWORD
*
)(v1
+
0x38
);
v9
=
xmmword_7FF62C2E3480;
(
*
(void (__fastcall
*
*
)(__int64, __int64, __int128
*
))(
*
(_QWORD
*
)v2
+
0x190i64
))(v2, v3, &v9);
/
/
ClearRenderTargetView
if
( !byte_7FF62C2E8314 )
{
_mm_storeu_si128((__m128i
*
)ProcName, _mm_load_si128((const __m128i
*
)&xmmword_7FF62C2E3490));
Dst
=
0i64
;
v8
=
11257i64
;
strcpy(ModuleName,
"ntdll.dll"
);
v12
=
1835355500
;
v13
=
7959151
;
v4
=
GetModuleHandleA(ModuleName);
v5
=
GetProcAddress(v4, ProcName);
if
( v5 )
((void (__fastcall
*
)(signed __int64, void
*
*
, _QWORD, __int64
*
, signed
int
, signed
int
))v5)(
-
1i64
,
&Dst,
0i64
,
&v8,
4096
,
64
);
v6
=
(char
*
)Dst;
qword_7FF62C2E8308
=
(__int64)Dst;
if
( Dst )
{
memcpy(Dst, sub_7FF62C2E5040,
0x1301ui64
);
/
/
填充代码
}
else
{
*
errno()
=
22
;
invalid_parameter_noinfo();
}
*
(_DWORD
*
)v6
=
0x53C48B48
;
*
((_DWORD
*
)v6
+
1
)
=
0x41575655
;
*
((_WORD
*
)v6
+
4
)
=
0x4156
;
if
( v6
=
=
(char
*
)
0xFFFFFFFFFFFFECFFi64
)
{
*
errno()
=
22
;
invalid_parameter_noinfo();
}
else
{
memcpy(v6
+
0x1301
, &unk_7FF62C2E6350,
0x18F0ui64
);
/
/
填充数据
}
*
(_QWORD
*
)(v6
+
0x2BF1
)
=
D3DCompile;
qword_7FF62C2E8318
=
(__int64 (__fastcall
*
)(_QWORD))(v6
+
0x650
);
/
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
((_DWORD
*
)v6
+
411
)
=
9601
;
*
(_DWORD
*
)(v6
+
1097
)
=
3764
;
*
((_DWORD
*
)v6
+
384
)
=
4865
;
byte_7FF62C2E8314
=
1
;
dword_7FF62C2E8310
=
GetTickCount();
}
if
( qword_7FF62C2E8318 )
{
qword_7FF62C2E8318(
*
(_QWORD
*
)(v1
+
0x30
));
/
/
调用shellcode
GetTickCount();
}
(
*
(void (__fastcall
*
*
)(_QWORD, _QWORD, _QWORD))(
*
*
(_QWORD
*
*
)(v1
+
0x30
)
+
64i64
))(
*
(_QWORD
*
)(v1
+
0x30
),
0i64
,
0i64
);
/
/
dxgi!Present
}
}
void __fastcall sub_7FF62C2E1090(__int64 a1)
{
/
*
...
*
/
v1
=
a1;
v2
=
*
(_QWORD
*
)(a1
+
0x28
);
if
( v2 )
{
v3
=
*
(_QWORD
*
)(v1
+
0x38
);
v9
=
xmmword_7FF62C2E3480;
(
*
(void (__fastcall
*
*
)(__int64, __int64, __int128
*
))(
*
(_QWORD
*
)v2
+
0x190i64
))(v2, v3, &v9);
/
/
ClearRenderTargetView
if
( !byte_7FF62C2E8314 )
{
_mm_storeu_si128((__m128i
*
)ProcName, _mm_load_si128((const __m128i
*
)&xmmword_7FF62C2E3490));
Dst
=
0i64
;
v8
=
11257i64
;
strcpy(ModuleName,
"ntdll.dll"
);
v12
=
1835355500
;
v13
=
7959151
;
v4
=
GetModuleHandleA(ModuleName);
v5
=
GetProcAddress(v4, ProcName);
if
( v5 )
((void (__fastcall
*
)(signed __int64, void
*
*
, _QWORD, __int64
*
, signed
int
, signed
int
))v5)(
-
1i64
,
&Dst,
0i64
,
&v8,
4096
,
64
);
v6
=
(char
*
)Dst;
qword_7FF62C2E8308
=
(__int64)Dst;
if
( Dst )
{
memcpy(Dst, sub_7FF62C2E5040,
0x1301ui64
);
/
/
填充代码
}
else
{
*
errno()
=
22
;
invalid_parameter_noinfo();
}
*
(_DWORD
*
)v6
=
0x53C48B48
;
*
((_DWORD
*
)v6
+
1
)
=
0x41575655
;
*
((_WORD
*
)v6
+
4
)
=
0x4156
;
if
( v6
=
=
(char
*
)
0xFFFFFFFFFFFFECFFi64
)
{
*
errno()
=
22
;
invalid_parameter_noinfo();
}
else
{
memcpy(v6
+
0x1301
, &unk_7FF62C2E6350,
0x18F0ui64
);
/
/
填充数据
}
*
(_QWORD
*
)(v6
+
0x2BF1
)
=
D3DCompile;
qword_7FF62C2E8318
=
(__int64 (__fastcall
*
)(_QWORD))(v6
+
0x650
);
/
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
((_DWORD
*
)v6
+
411
)
=
9601
;
*
(_DWORD
*
)(v6
+
1097
)
=
3764
;
*
((_DWORD
*
)v6
+
384
)
=
4865
;
byte_7FF62C2E8314
=
1
;
dword_7FF62C2E8310
=
GetTickCount();
}
if
( qword_7FF62C2E8318 )
{
qword_7FF62C2E8318(
*
(_QWORD
*
)(v1
+
0x30
));
/
/
调用shellcode
GetTickCount();
}
(
*
(void (__fastcall
*
*
)(_QWORD, _QWORD, _QWORD))(
*
*
(_QWORD
*
*
)(v1
+
0x30
)
+
64i64
))(
*
(_QWORD
*
)(v1
+
0x30
),
0i64
,
0i64
);
/
/
dxgi!Present
}
}
__int64 __usercall sub_7FF62C2E5460@<rax>(
int
a1@<r8d>, signed
int
a2@<r9d>, __int128
*
a3@<xmm6>, __int128
*
a4@<xmm7>, __int128
*
a5@<xmm8>, __int128
*
a6@<xmm9>, __int64 a7, signed
int
a8, signed
int
a9)
{
__int64 v9;
/
/
rsi
signed
int
v10;
/
/
er14
int
v11;
/
/
er15
__int64 result;
/
/
rax
__int64 v13;
/
/
rcx
int
v14;
/
/
edx
int
v15;
/
/
er9
int
v16;
/
/
eax
BYTE
*
v17;
/
/
[rsp
+
50h
] [rbp
-
30h
]
__int64 v18;
/
/
[rsp
+
58h
] [rbp
-
28h
]
__int128 v19;
/
/
[rsp
+
60h
] [rbp
-
20h
]
__int64 v20;
/
/
[rsp
+
70h
] [rbp
-
10h
]
int
v21;
/
/
[rsp
+
78h
] [rbp
-
8h
]
int
v22;
/
/
[rsp
+
7Ch
] [rbp
-
4h
]
v17
=
&ContextRecord.FltSave.Reserved4[
48
];
v9
=
0i64
;
v10
=
a2;
v11
=
a1;
v18
=
0i64
;
_mm_storeu_si128((__m128i
*
)&v19, (__m128i)
0i64
);
v20
=
0i64
;
v21
=
50
;
v22
=
50
;
while
(
2
)
{
result
=
(__int64)v17;
switch (
*
(_DWORD
*
)&v17[
4
*
v9] )
{
case
0
:
result
=
HIDWORD(v18);
LODWORD(v18)
=
HIDWORD(v18)
+
v18;
goto LABEL_10;
case
1
:
result
=
HIDWORD(v18);
LODWORD(v18)
=
v18
-
HIDWORD(v18);
goto LABEL_10;
case
2
:
v13
=
*
(signed
int
*
)&v17[
4
*
v9
+
4
];
v9
+
=
2i64
;
result
=
*
((unsigned
int
*
)&v18
+
v13);
*
((_DWORD
*
)&v18
+
*
(signed
int
*
)&v17[
4
*
v9])
=
result;
goto LABEL_10;
case
3
:
v14
=
*
(_DWORD
*
)&v17[
4
*
v9
+
4
];
v9
+
=
2i64
;
result
=
(__int64)v17;
*
((_DWORD
*
)&v18
+
*
(signed
int
*
)&v17[
4
*
v9])
=
v14;
goto LABEL_10;
case
4
:
+
+
v9;
v15
=
v18;
v16
=
v18
*
(HIDWORD(v18)
+
1
);
LODWORD(v18)
=
*
(_DWORD
*
)&v17[
4
*
v9] ^
0x414345
;
result
=
(unsigned
int
)((signed
int
)(v18 ^ (HIDWORD(v18)
+
v15))
%
256
+
(((signed
int
)(v18 ^ v15
*
HIDWORD(v18))
%
256
+
((signed
int
)(v18 ^ (HIDWORD(v18)
+
v16))
%
256
<<
8
)) <<
8
));
HIDWORD(v18)
=
result;
goto LABEL_10;
case
5
:
result
=
sub_7FF62C2E5040(
a7,
SHIDWORD(v19),
SDWORD2(v19),
v20,
SHIDWORD(v20),
a3,
a4,
a5,
a6,
-
256
,
v11,
v10,
a7,
a8,
a9,
(
int
)v17,
v18,
v19,
*
((__int64
*
)&v19
+
1
),
v20);
goto LABEL_10;
case
6
:
result
=
sub_7FF62C2E5040(
a7,
SHIDWORD(v19),
SDWORD2(v19),
v20,
SHIDWORD(v20),
a3,
a4,
a5,
a6,
-
13771801
,
v11,
v10,
a7,
a8,
a9,
(
int
)v17,
v18,
v19,
*
((__int64
*
)&v19
+
1
),
v20);
goto LABEL_10;
case
7
:
return
result;
default:
LABEL_10:
if
( (unsigned __int64)
+
+
v9 <
0x58F
)
continue
;
return
result;
}
}
}
__int64 __usercall sub_7FF62C2E5460@<rax>(
int
a1@<r8d>, signed
int
a2@<r9d>, __int128
*
a3@<xmm6>, __int128
*
a4@<xmm7>, __int128
*
a5@<xmm8>, __int128
*
a6@<xmm9>, __int64 a7, signed
int
a8, signed
int
a9)
{
__int64 v9;
/
/
rsi
signed
int
v10;
/
/
er14
int
v11;
/
/
er15
__int64 result;
/
/
rax
__int64 v13;
/
/
rcx
int
v14;
/
/
edx
int
v15;
/
/
er9
int
v16;
/
/
eax
BYTE
*
v17;
/
/
[rsp
+
50h
] [rbp
-
30h
]
__int64 v18;
/
/
[rsp
+
58h
] [rbp
-
28h
]
__int128 v19;
/
/
[rsp
+
60h
] [rbp
-
20h
]
__int64 v20;
/
/
[rsp
+
70h
] [rbp
-
10h
]
int
v21;
/
/
[rsp
+
78h
] [rbp
-
8h
]
int
v22;
/
/
[rsp
+
7Ch
] [rbp
-
4h
]
v17
=
&ContextRecord.FltSave.Reserved4[
48
];
v9
=
0i64
;
v10
=
a2;
v11
=
a1;
v18
=
0i64
;
_mm_storeu_si128((__m128i
*
)&v19, (__m128i)
0i64
);
v20
=
0i64
;
v21
=
50
;
v22
=
50
;
while
(
2
)
{
result
=
(__int64)v17;
switch (
*
(_DWORD
*
)&v17[
4
*
v9] )
{
case
0
:
result
=
HIDWORD(v18);
LODWORD(v18)
=
HIDWORD(v18)
+
v18;
goto LABEL_10;
case
1
:
result
=
HIDWORD(v18);
LODWORD(v18)
=
v18
-
HIDWORD(v18);
goto LABEL_10;
case
2
:
v13
=
*
(signed
int
*
)&v17[
4
*
v9
+
4
];
v9
+
=
2i64
;
赞赏
- [原创]2022腾讯游戏安全竞赛PC赛道初赛writeup 8887
- [分享]直播软件obs-studio graphics-hook利用 8773
- [分享]变参模板封装调用约定 9925
- [原创]浅析RING3层的CRC 15662