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 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.htmlTLDR; 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 ======================================================================= * Device OpenCL API (OpenCL 3.0 ) - Platform ============================================================= * Device 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, 0 x0000ffff 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 90 c Host memory allocated for this attack: 1615 MB (18784 MB free) 861 bd8bac91cac40013172f47ab784a4:robin@0 w0Session..........: hashcat Status...........: Cracked Hash.Mode........: 1000 (NTLM) Hash.Target......: 861 bd8bac91cac40013172f47ab784a4 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. Speed. Speed. 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. Restore.Sub. Candidate.Engine.: Device Generator Candidates. Candidates. Hardware.Mon. Hardware.Mon. 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' 861 bd8bac91cac40013172f47ab784a4:robin@0 w0
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; pwdcode::wor *v1; std::string::pointer M_p; std::string::size_type M_allocated_capacity; std::string::size_type M_string_length; char _M_p; Stream *Stream_1; pwdcode *const v7; std::ostream *v8; __int64 v9; const std::ctype<char > *v10; char n10; std::ostream *v12; std::ctype<char >::char_type (__fastcall *_ZNKSt5ctypeIcE8do_widenEc_1)(const std::ctype<char > *const , char ); __int64 (__fastcall *v15)(_QWORD); std::string retstr_; _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 pwdcode::wor *__fastcall pwdcode::decode[abi:cxx11](pwdcode::wor *__return_ptr retstr, pwdcode *const this) { pwdcode::wor *const v2; pwdcode::wor *const v3; signed __int64 M_string_length; std ::forward_iterator_tag v5; std ::forward_iterator_tag v6; __int64 v7; __int64 M_string_length_1; std ::string ::size_type _M_string_length; std ::string ::size_type M_allocated_capacity; std ::string ::pointer _M_p_1; char n47; std ::forward_iterator_tag v13; std ::forward_iterator_tag v14; std ::string *strnum_1; std ::string *M_p; char *_M_p; __int64 v18; __int64 v19; int v20; std ::forward_iterator_tag v21; std ::forward_iterator_tag v22; std ::string *strnum_2; std ::string *_M_p_2; char *_M_p_3; __int64 v26; __int64 v27; int v28; pwdcode::wor *const v29; pwdcode::wor *v30; unsigned __int64 v31; __int64 v32; char v33; std ::string ::pointer _M_p_4; std ::string ::size_type _M_string_length_1; std ::string ::size_type n15; std ::string *key2_1; int b; int d; std ::string key1; std ::string key2; char *p___beg; __int64 v44; char *__beg; __int64 v46; std ::string v47; std ::string retstr__1; std ::string retstr__2; std ::string key1_; std ::string strnum; std ::string retstr_; std ::string v53; 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; std::ostream *v1; std::ostream *v2; std::ostream *v3; std::ostream *v4; std::ostream *v5; _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; const std::ctype<char > *v1; char v2; std::ostream *v3; __int64 v4; const std::ctype<char > *v5; char v6; std::ostream *v7; std::ostream *v8; __int64 v9; const std::ctype<char > *v10; char v11; std::ostream *v12; __int64 v13; const std::ctype<char > *v14; char v15; std::ostream *v16; std::ctype<char >::char_type (__fastcall *v17)(const std::ctype<char > *const , char ); std::ctype<char >::char_type (__fastcall *v18)(const std::ctype<char > *const , char ); std::ctype<char >::char_type (__fastcall *v19)(const std::ctype<char > *const , char ); std::ctype<char >::char_type (__fastcall *v20)(const std::ctype<char > *const , char ); 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}