furryCTF_2025热身赛

[TOC]

热身赛

misc

签到题

话说,你们有发现比赛平台上藏有一个flag吗?

注意flag格式哦~

大厅找到furryCTF{Hack_for_fun_not_for_profit}

盲盒

来开盲盒吧~nwn

注:本题原本的flag格式为flag{},因为懒得改附件了,所以找到flag后请将里面的“flag”修改为“furryCTF”

比如flag{Hi}修改为furryCTF{Hi}即为正确答案。

直接打开xlsx,复制全部文字到txt,搜索flag{无果

类比docx,可以猜想xlsx也可以解压

在/xl下发现sharedStrings.xml,可以用浏览器打开,虽然看起来正常,但是用notepad打开可以发现零宽隐写

1
2
3
4
5
6
7
8
9
10
11
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="762826" uniqueCount="2">
<si>
<t>来开盲盒吧~</t>
<phoneticPr fontId="1" type="noConversion"/>
</si>
<si>
<t>flag 不在这</t>
<phoneticPr fontId="1" type="noConversion"/>
</si>
</sst>
<!-- ‬‌‬‍‬‍‍‍‬‌‌‌‌‍‌‍‬‌‌‬‌‍‬‌‍‍‌‬‌‬‬‬‌‬‍‌‍‌‬‍‍‬‬‌‍‬‌‍‍‌‍‍‍‌‌‌‍‍‍‍‌‬‬‌‬‌‍‬‍‬‍‌‍‌‌‌‌‌‌‍‬‬‌‌‌‌‍‍‌‌‌‌‍‬‬‌‌‌‌‍‬‌‌‌‌‌‌‬‬‌‌‌‌‍‬‍‬‌‌‌‌‍‬‌‌‌‌‌‍‬‌‍‌‌‌‌‍‬‍‌‌‌‌‍‬‌‌‌‌‍‍‬‬我也没说‌‌‌‌‌‌‍‌‌‌‌‌‬‍‌‌‌‌‍‍‌‌‌‌‍‍‍‌‌‌‌‌‍‬‬‌‌‌‌‌‍‬‍‍‌‌‌‌‍‍‌‌‌‌‍‍‌‌‌‌‌‍‍‌‌‌‌‌‍‌‬‌‌‌‌‌‌‍‌‌‌‌‍‬‬‌‌‌‌‍‬‍‌‌‌‌‍‍flag‌‌‌‌‍‌‬‍‌‌‌‌‍‬‬‌‌‌‌‍‍‌‌‌‌‍‌‍‍‌‌‌‌‍‬‌在这呀‌‌‌‌‍‬‌‌‌‌‌‌‬‍nwn‌‌‌‌‍‬‌‌‌‌‌‍‍,你不会想在这里找到flag叭~ -->

随便找个网站解密https://tool.bfw.wiki/tool/1695021695027599.html

解码得到:诶嘿,你还别说他还真就在这里nwn~
flag{Z19_The_Str1ng_In_Exc9l}

furryCTF{Z19_The_Str1ng_In_Exc9l}

IIS服务器

猫猫前段时间闲着没事搭建了一个IIS服务器。

不过,最近猫猫发现,服务器上好像多了个文件……?

非预期,1分钟秒了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ strings IIS.pcapng | grep "furryCTF"

┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ strings IIS.pcapng | grep "furry"
An error occurred on the server when processing the URL. Please contact the system administrator. <p/> If you are the system administrator please click <a href="http://go.microsoft.com/fwlink/?LinkID=82731">here</a> or call the <a href="execute/f12g.txt">furry helper</a> to find out more about this error.
An error occurred on the server when processing the URL. Please contact the system administrator. <p/> If you are the system administrator please click <a href="http://go.microsoft.com/fwlink/?LinkID=82731">here</a> or call the <a href="execute/f12g.txt">furry helper</a> to find out more about this error.
An error occurred on the server when processing the URL. Please contact the system administrator. <p/> If you are the system administrator please click <a href="http://go.microsoft.com/fwlink/?LinkID=82731">here</a> or call the <a href="execute/f12g.txt">furry helper</a> to find out more about this error.
An error occurred on the server when processing the URL. Please contact the system administrator. <p/> If you are the system administrator please click <a href="http://go.microsoft.com/fwlink/?LinkID=82731">here</a> or call the <a href="execute/f12g.txt">furry helper</a> to find out more about this error.

┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ binwalk -e IIS.pcapng

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
27713 0x6C41 gzip compressed data, fastest compression, from FAT filesystem (MS-DOS, OS/2, NT), last modified: 1970-01-01 00:00:00 (null date)

WARNING: One or more files failed to extract: either no utility was found or it's unimplemented

notepad打开分离出来的6C41文件:ZnVycnlDVEZ7RGlkX1lvdV9Ob3RlX1RoZV9EaWZmX0luX0Vycm9yX1BhZ2U/fQ==

base64解码得到furryCTF{Did_You_Note_The_Diff_In_Error_Page?}

后记:尝试直接strings搜索发现了彩蛋

1
{"user":"admin","pass":"flag{Never_Gonna_Give_You_Up}"}

大伙儿好像太无聊了那就整点无聊的东西(?

大概是一些无聊的产物(?

猫猫的一点PS:有谁想读一遍这个玩意喵owo

1
REOREREREREREOREREREREREREOOOREOREREREREOREREREOREREREOOREOREREREREOREREREREREOREOREREREREOOREOREOREOOREREOOREOOREOREOREREREREOOREOREREREREREOREOOOREOREREREOREOOOOREREOREOREOOOREOREREREREREOREOOREOOREREOOREREREREREOREOREOOOOREREOOREREREOREREOOREREREOREREOREOOOOREREOREREREOREOREOREREOREREREREOOREREOOOREOOOREOREOREOREREOOOOREOREOOREREREREOOREOOREREREOOREOOREREREOREOREOREREREOOREREOOREREO

不要被PS带偏么。就是二进制

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
text = "REOREREREREREOREREREREREREOOOREOREREREREOREREREOREREREOOREOREREREREOREREREREREOREOREREREREOOREOREOREOOREREOOREOOREOREOREREREREOOREOREREREREREOREOOOREOREREREOREOOOOREREOREOREOOOREOREREREREREOREOOREOOREREOOREREREREREOREOREOOOOREREOOREREREOREREOOREREREOREREOREOOOOREREOREREREOREOREOREREOREREREREOOREREOOOREOOOREOREOREOREREOOOOREOREOOREREREREOOREOOREREREOOREOOREREREOREOREOREREREOOREREOOREREO"

i = 0
binary = []
while i < len(text):
if text[i] == 'O':
binary.append('1')
i += 1
elif text[i] == 'R' and i+1 < len(text) and text[i+1] == 'E':
binary.append('0')
i += 2
else:
break

binary_str = ''.join(binary)
print(binary_str)

# 验证转换可逆性
check = []
for ch in binary_str:
if ch == '0':
check.append('RE')
else:
check.append('O')
check_str = ''.join(check)
print("\n转换后与原文本一致?", check_str == text)

01000001000000111010000100010001101000010000010100001101010110011011010100001101000001011101000101111001010111010000010110110011000001010111100110001001100010010111100100010101001000011001110111010101001111010110000110110001101100010101000110011001

第一次使用puzzlesolver这个工具,和随波逐流互相补充吧

实际上需要01反转再将字符串倒序

furryCTF{Wanna_2_Eat_OReO_zwz?}

丢失的文档

因为一场停电,猫猫刚写了一半的小说无了……

管他的,万物皆可notepad

furryCTF{How_To_F1x_This_Wor6_D0cument}

Crypto

SAM

猫猫不小心把自己设的密码给忘了,你能帮猫猫恢复一下嘛?

注:flag格式为furryCTF{furryCTF账户的密码}

Hint:猫猫给你准备了一份工具:(这也是猫猫唯一记得的东西了)

?l?l?l?l?l?s……(最后三位忘了.jpg)

遇到没见过的先file一下

1
2
3
4
5
6
7
┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e/sam]
└─$ file sam
sam: MS Windows registry file, NT/2000 or above

┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e/sam]
└─$ file system
system: MS Windows registry file, NT/2000 or above

sam:存储本地账户的密码哈希(LM/NTLM)。

system:包含启动时使用的系统配置和 SysKey(即用来加密 SAM 中哈希的密钥)。

使用secretsdump.py提取密码哈希

1
2
pipx install impacket
secretsdump.py -system system -sam sam LOCAL

可以找到NTLM 哈希861bd8bac91cac40013172f47ab784a4

接下来hashcat爆破,注意题干中的其实是掩码格式,5位小写字母+1位特殊字符+3位???

为加快破解速度,应该至少有两种方法优化

1.用Windows主机破解,性能可能强于WSL

2.可以分类,防止卡死

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?d?d?d'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?l?l?l'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?l?l?d'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?l?d?d'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?d?l?l'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?d?d?l'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?l?d?l'

hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?d?l?d'
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
PS E:\SAM> hashcat.exe -m 1000 -a 3 --force -O '861bd8bac91cac40013172f47ab784a4' '?l?l?l?l?l?s?d?l?d'
hashcat (v7.0.0) starting

You have enabled --force to bypass dangerous warnings and errors!
This can hide serious problems and should only be done when debugging.
Do not report hashcat issues encountered when using --force.

Successfully initialized the NVIDIA main driver CUDA runtime library.

Failed to initialize NVIDIA RTC library.

* Device #1: CUDA SDK Toolkit not installed or incorrectly installed.
CUDA SDK Toolkit required for proper device support and utilization.
For more information, see: https://hashcat.net/faq/wrongdriver
Falling back to OpenCL runtime.

If you are using WSL2 you can use CUDA instead of OpenCL.
Users must not install any NVIDIA GPU Linux driver within WSL 2
For all details: https://docs.nvidia.com/cuda/wsl-user-guide/index.html

TLDR; go to https://developer.nvidia.com/cuda-downloads and follow this path:
Linux -> Architecture -> Distribution -> Version -> deb (local)
Follow the installation Instructions on the website.

nvmlDeviceGetFanSpeed(): Not Supported

OpenCL API (OpenCL 3.0 CUDA 12.8.97) - Platform #1 [NVIDIA Corporation]
=======================================================================
* Device #01: NVIDIA GeForce RTX 5050 Laptop GPU, 8150/8150 MB (2037 MB allocatable), 20MCU

OpenCL API (OpenCL 3.0 ) - Platform #2 [Intel(R) Corporation]
=============================================================
* Device #02: Intel(R) Arc(TM) 130T GPU (16GB), 8398/16797 MB (2047 MB allocatable), 8MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 27

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:
* Optimized-Kernel
* Zero-Byte
* Precompute-Init
* Meet-In-The-Middle
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force
* Raw-Hash

Watchdog: Temperature abort trigger set to 90c

Host memory allocated for this attack: 1615 MB (18784 MB free)

861bd8bac91cac40013172f47ab784a4:robin@0w0

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1000 (NTLM)
Hash.Target......: 861bd8bac91cac40013172f47ab784a4
Time.Started.....: Tue Dec 30 18:27:15 2025, (3 secs)
Time.Estimated...: Tue Dec 30 18:27:18 2025, (0 secs)
Kernel.Feature...: Optimized Kernel (password length 0-27 bytes)
Guess.Mask.......: ?l?l?l?l?l?s?d?l?d [9]
Guess.Queue......: 1/1 (100.00%)
Speed.#01........: 17943.3 MH/s (7.72ms) @ Accel:96 Loops:512 Thr:256 Vec:8
Speed.#02........: 8569.0 MH/s (8.35ms) @ Accel:70 Loops:512 Thr:512 Vec:1
Speed.#*.........: 26512.3 MH/s
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 86788014080/1019422060800 (8.51%)
Rejected.........: 0/86788014080 (0.00%)
Restore.Point....: 127303680/1508020800 (8.44%)
Restore.Sub.#01..: Salt:0 Amplifier:512-676 Iteration:0-512
Restore.Sub.#02..: Salt:0 Amplifier:0-512 Iteration:0-512
Candidate.Engine.: Device Generator
Candidates.#01...: wtphi_0w0 -> xzrkh@1w0
Candidates.#02...: saeea+0w0 -> etghi_0w0
Hardware.Mon.#01.: Temp: 56c Util: 99% Core:1500MHz Mem:9001MHz Bus:8
Hardware.Mon.#02.: N/A

Started: Tue Dec 30 18:27:13 2025
Stopped: Tue Dec 30 18:27:19 2025

recovered显示100%,证明已经破解

1
2
PS E:\SAM> hashcat.exe -m 1000 --show '861bd8bac91cac40013172f47ab784a4'
861bd8bac91cac40013172f47ab784a4:robin@0w0

furryCTF{robin@0w0}

Reverse

猜数字

这游戏我敢打赌,有99%的人都不可能通过第一关!

我甚至怀疑,这游戏根本就没有后面的关卡,他可能只有这一关!

^附件:get flag.exe

1
2
3
4
5
6
7
8
9
10
┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ file flag.exe
flag.exe: PE32+ executable for MS Windows 5.02 (console), x86-64, 19 sections

┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ strings flag.exe | grep "flag{"

┌──(rekjo㉿LAPTOP-BMERJF8L)-[/mnt/e]
└─$ strings flag.exe | grep "furryCTF{"
furryCTF{Rev_Is_1nterest1ng}

是的你没看错,明文硬编码furryCTF{Rev_Is_1nterest1ng}

怪兽入侵

猫猫国被凶狠的怪兽入侵了!

一起来化身为勇者,保护可怜的猫猫们吧!

zip加密,仅能解压flag.txt和flagmaker.exe。花了很久时间爆破无果,patch一下原来是伪加密

一开始先打开的flagmaker.exe,提示输入金币数和钻石数,尝试了常见的114514,1919810都失败了,然后去看看flag.txt

1
/1691111\1131099/1691111467169/169111131221015/169111131221015/169111141281311/16911106108169/16911109661615/16911107541113/1691111558177/1691110612487/16911113761511/1691110101331613/1691110875167/16911113761511/16911114521411/1691110101331613/169111091421515/169111031110127/1691111467169/1691110101331613/1691110712101013/169111136\11313/169111031110127/1691111498915/1691110101331613/1691110414\11611/16911113761511/1691111498915/1691110101331613/16911109661615/169111031110127/1691110101331613/16911108510149/1691111\164109/1691111211689/1691111\11241711/169111131221015/1691110101331613/16911106108169/169111126101215/1691111\11241711/1691111\164109/16911114521411/16911115891013

并没有什么大用

可以先看看main函数

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
__int64 __fastcall main()
{
Stream *Stream; // rax
pwdcode::wor *v1; // rcx
std::string::pointer M_p; // rax
std::string::size_type M_allocated_capacity; // rdx
std::string::size_type M_string_length; // rbx
char _M_p; // r13
Stream *Stream_1; // rax
pwdcode *const v7; // rdx
std::ostream *v8; // r13
__int64 v9; // rax
const std::ctype<char> *v10; // r14
char n10; // dl
std::ostream *v12; // rax
std::ctype<char>::char_type (__fastcall *_ZNKSt5ctypeIcE8do_widenEc_1)(const std::ctype<char> *const, char); // rax
__int64 (__fastcall *v15)(_QWORD); // [rsp+38h] [rbp-70h]
std::string retstr_; // [rsp+40h] [rbp-68h] BYREF

_main();
v15 = *(__int64 (__fastcall **)(_QWORD))__acrt_iob_func;
Stream = __acrt_iob_func(0);
freopen_0("flag.txt", "r", Stream);
while ( scanf("%c", &retstr_) != -1 )
{
M_p = codes[abi:cxx11]._M_dataplus._M_p;
M_allocated_capacity = 15;
M_string_length = codes[abi:cxx11]._M_string_length;
_M_p = (char)retstr_._M_dataplus._M_p;
if ( codes[abi:cxx11]._M_dataplus._M_p != codes[abi:cxx11]._M_local_buf )
M_allocated_capacity = codes[abi:cxx11]._M_allocated_capacity;
if ( codes[abi:cxx11]._M_string_length + 1 > M_allocated_capacity )
{
std::string::_M_mutate(&codes[abi:cxx11], codes[abi:cxx11]._M_string_length, 0, 0, 1);
M_p = codes[abi:cxx11]._M_dataplus._M_p;
}
M_p[M_string_length] = _M_p;
codes[abi:cxx11]._M_string_length = M_string_length + 1;
codes[abi:cxx11]._M_dataplus._M_p[M_string_length + 1] = 0;
}
pwdcode::wor::nice(v1);
Stream_1 = (FILE *)v15(0);
freopen_0("CON", "r", Stream_1);
pwdcode::decode[abi:cxx11](&retstr_, v7);
v8 = (std::ostream *)std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
v9 = *(_QWORD *)(*(_QWORD *)v8 - 24LL);
v10 = *(const std::ctype<char> **)((char *)v8 + v9 + 240);
if ( !v10 )
std::__throw_bad_cast();
if ( *((_BYTE *)v10 + 56) )
{
n10 = *((_BYTE *)v10 + 67);
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)v8 + v9 + 240));
n10 = 10;
_ZNKSt5ctypeIcE8do_widenEc_1 = *(std::ctype<char>::char_type (__fastcall **)(const std::ctype<char> *const, char))(*(_QWORD *)v10 + 48LL);
if ( _ZNKSt5ctypeIcE8do_widenEc_1 != std::ctype<char>::do_widen )
n10 = _ZNKSt5ctypeIcE8do_widenEc_1(v10, 10);
}
v12 = (std::ostream *)std::ostream::put(v8, n10);
std::ostream::flush(v12);
std::string::_M_dispose(&retstr_);
system_0("pause");
return 0;
}

_main是普通的初始化函数。decode函数或许有用

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
// Alternative name is '_ZN7pwdcode6decodeB5cxx11Ev'
pwdcode::wor *__fastcall pwdcode::decode[abi:cxx11](pwdcode::wor *__return_ptr retstr, pwdcode *const this)
{
pwdcode::wor *const v2; // rcx
pwdcode::wor *const v3; // rcx
signed __int64 M_string_length; // rsi
std::forward_iterator_tag v5; // r9
std::forward_iterator_tag v6; // r9
__int64 v7; // rbp
__int64 M_string_length_1; // rbx
std::string::size_type _M_string_length; // r13
std::string::size_type M_allocated_capacity; // rdx
std::string::pointer _M_p_1; // rax
char n47; // r12
std::forward_iterator_tag v13; // r9
std::forward_iterator_tag v14; // r9
std::string *strnum_1; // r8
std::string *M_p; // rcx
char *_M_p; // rdx
__int64 v18; // rax
__int64 v19; // r9
int v20; // eax
std::forward_iterator_tag v21; // r9
std::forward_iterator_tag v22; // r9
std::string *strnum_2; // r8
std::string *_M_p_2; // rcx
char *_M_p_3; // rdx
__int64 v26; // rax
__int64 v27; // r9
int v28; // eax
pwdcode::wor *const v29; // rcx
pwdcode::wor *v30; // rcx
unsigned __int64 v31; // rdi
__int64 v32; // rax
char v33; // bl
std::string::pointer _M_p_4; // rax
std::string::size_type _M_string_length_1; // rsi
std::string::size_type n15; // rdx
std::string *key2_1; // [rsp+20h] [rbp-228h]
int b; // [rsp+98h] [rbp-1B0h]
int d; // [rsp+9Ch] [rbp-1ACh]
std::string key1; // [rsp+A0h] [rbp-1A8h] BYREF
std::string key2; // [rsp+C0h] [rbp-188h] BYREF
char *p___beg; // [rsp+E0h] [rbp-168h] BYREF
__int64 v44; // [rsp+E8h] [rbp-160h]
char *__beg; // [rsp+100h] [rbp-148h] BYREF
__int64 v46; // [rsp+108h] [rbp-140h]
std::string v47; // [rsp+120h] [rbp-128h] BYREF
std::string retstr__1; // [rsp+140h] [rbp-108h] BYREF
std::string retstr__2; // [rsp+160h] [rbp-E8h] BYREF
std::string key1_; // [rsp+180h] [rbp-C8h] BYREF
std::string strnum; // [rsp+1A0h] [rbp-A8h] BYREF
std::string retstr_; // [rsp+1C0h] [rbp-88h] BYREF
std::string v53; // [rsp+1E0h] [rbp-68h] BYREF

pwdcode::wor::nice(retstr);
std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
std::istream::operator>>(refptr__ZSt3cin);
std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
std::istream::operator>>(refptr__ZSt3cin);
pwdcode::wor::nice(v2);
std::to_string(&key1, b);
std::to_string(&key2, d);
pwdcode::wor::nice(v3);
std::string::basic_string(&__beg, &key2);
std::string::basic_string(&p___beg, &key1);
M_string_length = codes[abi:cxx11]._M_string_length;
v47._M_dataplus._M_p = v47._M_local_buf;
std::string::_M_construct<char const*>(&v47, &_end, &_end, v5);
v7 = 0;
if ( M_string_length > 0 )
{
M_string_length_1 = 0;
while ( 1 )
{
n47 = codes[abi:cxx11]._M_dataplus._M_p[M_string_length_1];
if ( n47 != 47 )
break;
if ( M_string_length_1 )
{
key1_._M_dataplus._M_p = key1_._M_local_buf;
std::string::_M_construct<char *>(&key1_, __beg, &__beg[v46], v6);
strnum._M_dataplus._M_p = strnum._M_local_buf;
std::string::_M_construct<char *>(&strnum, p___beg, &p___beg[v44], v13);
v53._M_dataplus._M_p = v53._M_local_buf;
std::string::_M_construct<char *>(&v53, v47._M_dataplus._M_p, &v47._M_dataplus._M_p[v47._M_string_length], v14);
pwdcode::decode_num(&retstr_, (pwdcode *const)&v53, strnum_1);
pwdcode::decode_origin(&retstr__1, (pwdcode *const)&retstr_, &strnum, &key1_, key2_1);
M_p = (std::string *)retstr__1._M_dataplus._M_p;
if ( LODWORD(retstr__1._M_string_length) )
{
_M_p = retstr__1._M_dataplus._M_p;
v18 = 0;
do
{
v19 = 5 * v18;
v20 = *_M_p++;
v18 = v20 - 48 + 2 * v19;
}
while ( &retstr__1._M_dataplus._M_p[LODWORD(retstr__1._M_string_length) - 1 + 1] != _M_p );
}
else
{
v18 = 0;
}
node._M_impl._M_start[v7] = v18;
if ( M_p != (std::string *)retstr__1._M_local_buf )
operator delete(M_p);
if ( retstr_._M_dataplus._M_p != retstr_._M_local_buf )
operator delete(retstr_._M_dataplus._M_p);
if ( v53._M_dataplus._M_p != v53._M_local_buf )
operator delete(v53._M_dataplus._M_p);
if ( strnum._M_dataplus._M_p != strnum._M_local_buf )
operator delete(strnum._M_dataplus._M_p);
if ( key1_._M_dataplus._M_p != key1_._M_local_buf )
operator delete(key1_._M_dataplus._M_p);
key2_1 = 0;
std::string::_M_replace(&v47, 0, v47._M_string_length, &_end);
++M_string_length_1;
++v7;
if ( M_string_length == M_string_length_1 )
goto LABEL_26;
}
else
{
LABEL_9:
if ( M_string_length == ++M_string_length_1 )
goto LABEL_26;
}
}
if ( M_string_length - 1 != M_string_length_1 )
{
_M_string_length = v47._M_string_length;
M_allocated_capacity = 15;
_M_p_1 = v47._M_dataplus._M_p;
if ( v47._M_dataplus._M_p != v47._M_local_buf )
M_allocated_capacity = v47._M_allocated_capacity;
if ( v47._M_string_length + 1 > M_allocated_capacity )
{
std::string::_M_mutate(&v47, v47._M_string_length, 0, 0, 1);
_M_p_1 = v47._M_dataplus._M_p;
}
_M_p_1[_M_string_length] = n47;
v47._M_string_length = _M_string_length + 1;
v47._M_dataplus._M_p[_M_string_length + 1] = 0;
}
goto LABEL_9;
}
LABEL_26:
if ( v47._M_string_length )
{
key1_._M_dataplus._M_p = key1_._M_local_buf;
std::string::_M_construct<char *>(&key1_, __beg, &__beg[v46], v6);
strnum._M_dataplus._M_p = strnum._M_local_buf;
std::string::_M_construct<char *>(&strnum, p___beg, &p___beg[v44], v21);
v53._M_dataplus._M_p = v53._M_local_buf;
std::string::_M_construct<char *>(&v53, v47._M_dataplus._M_p, &v47._M_dataplus._M_p[v47._M_string_length], v22);
pwdcode::decode_num(&retstr_, (pwdcode *const)&v53, strnum_2);
pwdcode::decode_origin(&retstr__2, (pwdcode *const)&retstr_, &strnum, &key1_, key2_1);
_M_p_2 = (std::string *)retstr__2._M_dataplus._M_p;
if ( LODWORD(retstr__2._M_string_length) )
{
_M_p_3 = retstr__2._M_dataplus._M_p;
v26 = 0;
do
{
v27 = 5 * v26;
v28 = *_M_p_3++;
v26 = v28 - 48 + 2 * v27;
}
while ( &retstr__2._M_dataplus._M_p[LODWORD(retstr__2._M_string_length) - 1 + 1] != _M_p_3 );
}
else
{
v26 = 0;
}
node._M_impl._M_start[v7] = v26;
if ( _M_p_2 != (std::string *)retstr__2._M_local_buf )
operator delete(_M_p_2);
if ( retstr_._M_dataplus._M_p != retstr_._M_local_buf )
operator delete(retstr_._M_dataplus._M_p);
if ( v53._M_dataplus._M_p != v53._M_local_buf )
operator delete(v53._M_dataplus._M_p);
if ( strnum._M_dataplus._M_p != strnum._M_local_buf )
operator delete(strnum._M_dataplus._M_p);
if ( key1_._M_dataplus._M_p != key1_._M_local_buf )
operator delete(key1_._M_dataplus._M_p);
LODWORD(v7) = v7 + 1;
}
if ( v47._M_dataplus._M_p != v47._M_local_buf )
operator delete(v47._M_dataplus._M_p);
std::string::_M_dispose(&p___beg);
std::string::_M_dispose(&__beg);
pwdcode::wor::nice(v29);
if ( (int)v7 > 0 )
{
v31 = 0;
do
{
v30 = (pwdcode::wor *)&node._M_impl._M_start[v31 / 8];
v32 = (node._M_impl._M_start[v31 / 8] - 114514 * b) / d;
node._M_impl._M_start[v31 / 8] = v32;
v33 = v32;
_M_p_4 = ecodes[abi:cxx11]._M_dataplus._M_p;
_M_string_length_1 = ecodes[abi:cxx11]._M_string_length;
n15 = 15;
if ( ecodes[abi:cxx11]._M_dataplus._M_p != ecodes[abi:cxx11]._M_local_buf )
n15 = ecodes[abi:cxx11]._M_allocated_capacity;
if ( ecodes[abi:cxx11]._M_string_length + 1 > n15 )
{
std::string::_M_mutate(&ecodes[abi:cxx11], ecodes[abi:cxx11]._M_string_length, 0, 0, 1);
_M_p_4 = ecodes[abi:cxx11]._M_dataplus._M_p;
}
_M_p_4[_M_string_length_1] = v33;
v31 += 8LL;
ecodes[abi:cxx11]._M_string_length = _M_string_length_1 + 1;
ecodes[abi:cxx11]._M_dataplus._M_p[_M_string_length_1 + 1] = 0;
}
while ( 8LL * (unsigned int)(v7 - 1) + 8 != v31 );
}
pwdcode::wor::nice(v30);
std::string::basic_string(retstr, &ecodes[abi:cxx11]);
std::string::_M_dispose(&key2);
std::string::_M_dispose(&key1);
return retstr;
}

但是调用的decode_num和decode_origin都相当复杂,不再呈现

运行一下怪兽入侵.exe

1
2
3
4
5
有一个怪物入侵了地球!快打倒他!
输入attack攻击他!
当前该怪物的生命值为:9223372036854775807
attack 你对怪物造成了1点伤害!
请按任意键继续. . .

先ida看看main函数

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
__int64 __fastcall main()
{
std::ostream *v0; // rax
std::ostream *v1; // rax
std::ostream *v2; // rax
std::ostream *v3; // rax
std::ostream *v4; // rax
std::ostream *v5; // rax

_main();
system_0("color 0e");
while ( hps.hp != hashs )
show();
system_0("color 0a");
v0 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, (char *)&byte_1400B50B7);
std::endl<char,std::char_traits<char>>(v0);
v1 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, (char *)&byte_1400B50CC);
v2 = (std::ostream *)std::ostream::_M_insert<long long>(v1);
v3 = (std::ostream *)std::operator<<<std::char_traits<char>>(v2, (char *)&byte_1400B50D5);
v4 = (std::ostream *)std::ostream::_M_insert<long long>(v3);
v5 = (std::ostream *)std::operator<<<std::char_traits<char>>(v4, (char *)&byte_1400B50DE);
std::endl<char,std::char_traits<char>>(v5);
system_0("pause>>nul");
return 0;
}

show函数:

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
void __cdecl show()
{
__int64 v0; // rax
const std::ctype<char> *v1; // r13
char v2; // dl
std::ostream *v3; // rax
__int64 v4; // rax
const std::ctype<char> *v5; // r13
char v6; // dl
std::ostream *v7; // rax
std::ostream *v8; // r13
__int64 v9; // rax
const std::ctype<char> *v10; // r14
char v11; // dl
std::ostream *v12; // rax
__int64 v13; // rax
const std::ctype<char> *v14; // r14
char v15; // dl
std::ostream *v16; // rax
std::ctype<char>::char_type (__fastcall *v17)(const std::ctype<char> *const, char); // rax
std::ctype<char>::char_type (__fastcall *v18)(const std::ctype<char> *const, char); // rax
std::ctype<char>::char_type (__fastcall *v19)(const std::ctype<char> *const, char); // rax
std::ctype<char>::char_type (__fastcall *v20)(const std::ctype<char> *const, char); // rax

std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
v0 = *(_QWORD *)(*(_QWORD *)refptr__ZSt4cout - 24LL);
v1 = *(const std::ctype<char> **)((char *)refptr__ZSt4cout + v0 + 240);
if ( !v1 )
goto LABEL_25;
if ( *((_BYTE *)v1 + 56) )
{
v2 = *((_BYTE *)v1 + 67);
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)refptr__ZSt4cout + v0 + 240));
v2 = 10;
v17 = *(std::ctype<char>::char_type (__fastcall **)(const std::ctype<char> *const, char))(*(_QWORD *)v1 + 48LL);
if ( v17 != std::ctype<char>::do_widen )
v2 = v17(v1, 10);
}
v3 = (std::ostream *)std::ostream::put(refptr__ZSt4cout, v2);
std::ostream::flush(v3);
std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
v4 = *(_QWORD *)(*(_QWORD *)refptr__ZSt4cout - 24LL);
v5 = *(const std::ctype<char> **)((char *)refptr__ZSt4cout + v4 + 240);
if ( !v5 )
goto LABEL_25;
if ( *((_BYTE *)v5 + 56) )
{
v6 = *((_BYTE *)v5 + 67);
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)refptr__ZSt4cout + v4 + 240));
v6 = 10;
v18 = *(std::ctype<char>::char_type (__fastcall **)(const std::ctype<char> *const, char))(*(_QWORD *)v5 + 48LL);
if ( v18 != std::ctype<char>::do_widen )
v6 = v18(v5, 10);
}
v7 = (std::ostream *)std::ostream::put(refptr__ZSt4cout, v6);
std::ostream::flush(v7);
std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
v8 = (std::ostream *)std::ostream::_M_insert<long long>(refptr__ZSt4cout);
v9 = *(_QWORD *)(*(_QWORD *)v8 - 24LL);
v10 = *(const std::ctype<char> **)((char *)v8 + v9 + 240);
if ( !v10 )
goto LABEL_25;
if ( *((_BYTE *)v10 + 56) )
{
v11 = *((_BYTE *)v10 + 67);
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)v8 + v9 + 240));
v11 = 10;
v19 = *(std::ctype<char>::char_type (__fastcall **)(const std::ctype<char> *const, char))(*(_QWORD *)v10 + 48LL);
if ( v19 != std::ctype<char>::do_widen )
v11 = v19(v10, 10);
}
v12 = (std::ostream *)std::ostream::put(v8, v11);
std::ostream::flush(v12);
std::operator>><char>(refptr__ZSt3cin);
if ( !(unsigned int)std::string::compare(&ans[abi:cxx11], "attack") )
{
system_0("cls");
hps.hp = hashs ^ ((hashs ^ hps.hp) - 1);
system_0("color 0a");
}
else
{
system_0("cls");
system_0("color 0c");
}
std::__ostream_insert<char,std::char_traits<char>>(refptr__ZSt4cout);
v13 = *(_QWORD *)(*(_QWORD *)refptr__ZSt4cout - 24LL);
v14 = *(const std::ctype<char> **)((char *)refptr__ZSt4cout + v13 + 240);
if ( !v14 )
LABEL_25:
std::__throw_bad_cast();
if ( *((_BYTE *)v14 + 56) )
{
v15 = *((_BYTE *)v14 + 67);
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)refptr__ZSt4cout + v13 + 240));
v15 = 10;
v20 = *(std::ctype<char>::char_type (__fastcall **)(const std::ctype<char> *const, char))(*(_QWORD *)v14 + 48LL);
if ( v20 != std::ctype<char>::do_widen )
v15 = v20(v14, 10);
}
v16 = (std::ostream *)std::ostream::put(refptr__ZSt4cout, v15);
std::ostream::flush(v16);
system_0("pause");
system_0("color 0e");
system_0("cls");
}

hashs是定值1428573614285736

x64dbg动调,搜索strings“怪兽”,定位到入口

1
00007FF7C40016A6 | 48:8D15 87390B00         | lea rdx,qword ptr ds:[7FF7C40B5034]     | 00007FF7C40B5034:"当前该怪物的生命值为:"

F2下断点,F8单步往下走,可以确认

1
00007FF7C40016C3 | E8 58E40600              | call 怪兽入侵.7FF7C406FB20                  |

在这一条之后打印血量,所以7FF7C40E0040是目标内存地址,Ctrl+G跳转,可以cheat了

在此处被赋值之后立即修改为36 57 28 14 36 57 28 14,并单步执行

可以看到

1
2
3
有一个怪物入侵了地球!快打倒他!
输入attack攻击他!
当前该怪物的生命值为:0

这个时候如果继续attack,就会发现血量变为-1(无语辣)

破解办法是输入非attack的字符串跳出循环,可以得到

1
2
恭喜!你打败了怪物!
你获得了7934个金币和1518个钻石

将数据输入flagmaker.exe,可得flag

furryCTF{Do_Not_Y0u_Kn0w_8ow_T0_Maker_Cheat}