前排提示:我是搜索型選手,以前沒打過 CTF。我很菜的。
本文由我撰寫的部分放棄版權,請隨意。
白與夜
右鍵那張圖片 Open image in new tab 就能看到 flag 文字。
flag{4_B14CK_C4T}
信息安全 2077
打開 DevTools → Network 複製請求的 CURL,終端修改參數 If-Unmodified-Since
成指定的時間執行就可。
flag{Welc0me_to_competit1on_in_2077}
宇宙終極問題
第一部分:Google 搜索 42 sum of cubes
得到三個數是 -80538738812075974
804357581458175153
126021232973356313
第二部分:
(丟人)
第三部分:
雖然我自己也寫了個 python 腳本,使用 primefac 和 math.stackexchange 上的代碼。但是運行速度過於緩慢,達不到題目的要求。
https://www.alpertron.com.ar/ECM.HTM (再度丟人)
如果服務器給的隨機數合適,就可以表成兩數平方和。但是下列情況之一的,不可能表成兩數平方和:
- 隨機數本身模 4 餘 3
- 因數分解後模 4 餘 3 的質因子冪次爲奇數
網頁讀取器
下載源碼,由於 flask 這種框架有安全問題的可能性較低,肯定是他自己的源碼寫錯了。果不其然,其有一行去除鏈接中第一個 @
及之前所有字符。構造鏈接 http://web1/flag?@example.com
就可。
大冒險
一開始我不會做這個題目,因爲設置了一個干擾選項“打怪升級”,在我看來只有戲劇效果。
後來,我發現“料理大市場”場景可以在控制檯用 ws.send(<integer>)
與服務器通訊,輸入不在 0 到 10 之間的數也可以。那就輸入一個巨大的負數使得 ATK 溢出爲一大正數,由於惡龍攻擊力只有 8 位數,很輕鬆就被我們秒掉了。在與國王的對話中選擇 flag
即可。
flag{what_an_amazing_dream}
Happy LUG
我一讀完題就知道怎麼做了,然而,當時我看錯了域名……
對 Unicode 域名,搜索 Punycode
或者直接打在瀏覽器地址欄回車就行。
$ drill xn--g28h.hack.USTCLUG.org txt
(部分輸出已省略)
xn--g28h.hack.USTCLUG.org. 300 IN TXT "flag{DN5_C4N_H4VE_em0ji_haha}"
命令 drill
是 archlinux 特色,若無請換成 dig
。
正則驗證器
Google 搜索 regex DoS
,找到 Wikipedia 頁面。看源碼只允許 6 字符的正則表達式和 24 字符的文本,我們選擇 (x+)+$
和 xxxxxxxxxxxxxxxxxxxxxxx!
來測試。遂得到 flag。
flag{R3g3x_can_D0S_<signature>}
別樣的 python 考試
我卡 challenge 14 沒做出來。只能 95 分。
以下是不完全解答:
"Hello"
1,1,1.0,1
""
[1],1
[3,2,1]
{1,2},{1,3}
(1,),4,-5
(1,2),-2,-2
3,-1
'12377',''
((10,),)
(),(1,2)
{1},{1}
- 未解出
'','123'
b"\xe9"
1, {0:1}
1e400,1e400
"\u06f0\u1c43\u1c59\u1c59"
[0, 0.0, 0.0j, False, -0.0, -0.0j, -0.0-0.0j]
關於 14 題參見 Python Programming FAQ
小巧玲瓏的 ELF
用 IDA Pro 載入這個 ELF,debug 運行就能看到對應的 C 代碼,導出數據後解密即可。
#include <stdio.h>
const char key[] = {
102, 110, 101, 107, -125, 78, 109, 116, -123, 122, 111, 87, -111, 115, -112, 79, -115, 127, 99, 54, 108, 110, -121, 105, -93, 111, 88, 115, 102, 86, -109, -97, 105, 112, 56, 118, 113, 120, 111, 99, -60, -126, -124, -66, -69, -51
};
int main ()
{
char buf[47];
for (int j = 0; j <= 45; j++)
buf[j] = key[j];
for (int i = 0; i <= 45; i++)
{
buf[i] += i;
buf[i] ^= i;
buf[i] -= 2 * i;
}
buf[46] = '\0';
printf ("%s", buf);
return 0;
}
flag{Linux_Syst3m_C4ll_is_4_f4scin4ting_t00ls}
Shell 駭客
- 由於沒有任何限制,Google 搜索
x64 execve shellcode
即可。我是用 pwntools payload 的,用 websocket 說不定也行。 $ msfvenom -a x86 --platform linux -p linux/x86/exec CMD=/bin/sh -e x86/alpha_upper -f python
即可生成。- 我測試了
ecx86/shellcode_encoder
,指定rax
,發現並不行。查找網上資源打算手寫一個 x64 printable shellcode,失敗。所以本小題未解出。
後來瞭解到有個工具叫 alpha3
三教奇妙夜
打開視頻觀看前一分鐘就能找到兩幀 flag 黑屏圖(即“flag{”)。
$ ffmpeg -i output.mp4 -vf blackdetect=d=0.04:pic_th=0.95:pix_th=0.01 -f rawvideo -y /dev/null
等輸出,再找到秒數對應的幀看就可。
(輸出已經簡略)
[blackdetect @ 0x5621517b67c0] black_start:59.96 black_end:60.04 black_duration:0.08
[blackdetect @ 0x5621517b67c0] black_start:183 black_end:183.08 black_duration:0.08speed= 331x
[blackdetect @ 0x5621517b67c0] black_start:10183 black_end:10183.1 black_duration:0.08peed= 332x
[blackdetect @ 0x5621517b67c0] black_start:30059.1 black_end:30059.2 black_duration:0.08eed= 309x
[blackdetect @ 0x5621517b67c0] black_start:42404.1 black_end:42404.2 black_duration:0.08peed= 308x
[blackdetect @ 0x5621517b67c0] black_start:43104.2 black_end:43104.2 black_duration:0.08peed= 308x
flag{ViDe0_prOcE55_with_program_1s_eaSy}
小插曲:未解出時我曾試圖用 Google Video Intelligence 提取文本,結果爲空。
小 U 的加密
根據題目提示是位運算。用 GHex 打開發現文件各處都有很多的字符 9
(0x39),將全部字節 xor 0x39 就得到原文件,然而我一開始並不認識 MThd MTrk
這個魔數,但可以推測該文件格式編碼效率很低,不是正常的音頻編碼。於是發現其是 MIDI 文件。在 Windows 系統下載一個 MIDI 編輯器打開後即看到 flag 圖形。
flag{justxorandmidi}
獻給最好的你
本題疑似玩梗 2019 年各大高校 9.27 事件(原名“獻給最好的 TA”)。
解壓 APK 包(這個包在我太過低級的 Huawei 手機上並不能安裝),得到 classes.dex 文件。下載 dex2jar 最新的 nightly build,發現仍然無法轉換爲 jar 文件。無奈直接把魔數 dex\n038
改成 dex\n037
,就可以用 dex2jar 了。用 jd-gui 打開得到的 jar 文件,定位到 com/hackergame.eternalEastlyWind/LoginResult.class
,讀一下 login 和 logout 兩個函數的源碼,解密即可。
#!/usr/bin/python3
from base64 import b64encode, b64decode
mysterious_string = "AgfJA2vYz2fTztiWmtL3AxrOzNvUiq=="
flxg_bytes = bytes([
14, 13, 2, 12, 30, 30, 2, 0, 31, 11,
109, 81, 83, 8, 3, 54, 21, 6, 2, 39,
33, 104, 44, 62, 17, 14, 19, 23, 21, 18,
8, 24
])
def xchange_case(s):
ret = ''
for ch in s:
if ch.islower():
ret += ch.upper()
elif ch.isupper():
ret += ch.lower()
else:
ret += ch
return ret
def rewritten_logout(param_string_bytes, param_array_of_bytes):
# param_string rawpassword
# param_array_of_bytes flxg - is related to the flag
i = len(param_array_of_bytes) - 1
lps = len(param_string_bytes)
sb = ''
j = 0
while True:
ch = chr( param_array_of_bytes[j] ^ param_string_bytes[j % lps])
print("pass2", ch)
sb += ch
if j != i:
j += 1
continue
break
print("pass2", sb)
return sb
def rewritten_login(param_string_bytes):
# param_string: password
#array_of_byte = param_string.encode('utf-8')
array_of_bytes = param_string_bytes
original_str = b64encode(array_of_bytes[2:])
new_str = xchange_case(original_str)
print("pass1", new_str)
if new_str != mysterious_str:
print("wrong password")
return False # Failure
return True # Success
def decrypt():
rs = xchange_case(mysterious_string)
bf2 = b64decode(rs)
rewritten_logout(bf2, flxg_bytes)
if __name__ == '__main__': decrypt()
flag{learn_ab1t_andROID_reverse}
天書殘篇
下載那個文件發現只有三種字符:普通空格,製表符 \t
和換行 \n
。找到在線 whitespace 編譯器,載入 whitespace 源碼,點擊右邊 Run 就會出現人能看懂的彙編代碼,拖下來。雖然代碼中有許多 label,但可以看出有一串 label 是在逐位判斷輸入是否符合編碼的 flag,提取數據寫程序解密即可。
#include <stdio.h>
const char source[] = {127, 53, 105, 54, 119, 105, 112, 54, 110, 97, 111, 54, 116, 105, 50, 116, 114, 97, 118, 110, 119, 101, 107, 104, 104, 107, 102, 97, 99, 97, 117, 107, 97, 53, 101, 54, 114, 117, 53, 118, 107, 106, 89, 125, 105, 99, 110, 104};
char buf[49];
int main()
{
buf[48] = '\0';
for (int j = 47; j >= 0; --j)
{
buf[47-j] = source[j] - 2;
}
printf("%s", buf);
return 0;
}
flag{Whit3sp4c3_is_a_difficult_pr0gr4m_l4ngu4g3}
我想要個家
VirtualBox 虛擬機隨便載入一張 Linux Live CD(並非必要)。由於我太菜不會去掉根目錄的 /proc
和 /sys
,只能 chroot
。
把 /mnt
作爲 chroot jail,創建子目錄 lib,複製 bash 和 sleep 到 /mnt
,用 ldd
查看兩個文件的依賴並把相關庫複製到 /mnt/lib
目錄中。按要求在 /mnt
創建目錄、文件和符號鏈接,開一個終端無限循環每 0.1 秒寫入當前時間。
while true
do
sleep 0.1
date +%H:%M:%S > /mnt/Living_Room/Clock
done
在 jail 外準備完成後,複製題目的二進制文件到 /mnt
,用 chroot /mnt /bash
,運行二進制文件。等提示輸入 /sleep 10
,等待 10 秒即可得到 flag,英文是 I am happy now。
被泄漏的薑戈
本題疑似致敬 openbilibili。
上 GitHub 搜索 openlug
,找到此名的用戶和其倉庫 django-common
,clone 之。有價值的只有 db.sqlite3
中的 admin 用戶密碼和 openlug/settings.py
中的 SECRET_KEY
。閱覽 django 官方文檔和源代碼即可用 python 解題。
由於 Kali Linux Live 虛擬機被我不慎關閉,python 控制檯記錄也就永久丟失了。我使用的是官方題解中“複雜的解法”。
flag{Never_leak_your_sEcReT_KEY}
沒有 BUG 的教務系統
只做了第一問,由於第二問需要 pwn 積累,我是做不出來的。
for (i = 0; i <= 7; ++i)
temp_password[i] = ((temp_password[i] | temp_password[i + 1]) & ~(temp_password[i] & temp_password[i + 1]) | i) & ~((temp_password[i] | temp_password[i + 1]) & ~(temp_password[i] & temp_password[i + 1]) & i);
if(memcmp(temp_password, "\x44\x00\x02\x41\x43\x47\x10\x63\x00", 9)) {
cout << "Bad guy! Wrong password!" << endl;
exit(0);
}
記 temp_password[i]
爲 A,temp_password[i+1]
爲 B,i
爲 C,輸入 WolframAlpha 中得到真值表和 Venn 圖,非常漂亮。寫一段程序即可逆推出密碼。
#include <iostream>
using namespace std;
// "\x44\x00\x02\x41\x43\x47\x10\x63\x00"
const char *rsrc = "\x00\x63\x10\x47\x43\x41\x02\x00\x44";
char buf[9] = {0,0,0,0,0,0,0,0,0};
char bitwise_decipher(const char b, const char c, const char v) {
int sum = (b << 2) | (c << 1) | v;
switch (sum) {
case 7:
case 4:
case 2:
case 1:
return 1;
case 6:
case 5:
case 3:
case 0: return 0;
}
return 0;
}
void decipher(char &a, char b, char c, char v) {
a = 0;
for (int i = 0; i < 8; i++) {
a |= (bitwise_decipher(
(b >> i) & 1,
(c >> i) & 1,
(v >> i) & 1
) << i);
}
}
int main() {
for (int j = 1; j < 9; j++) {
decipher(buf[j], buf[j-1], (char)(8-j), rsrc[j]);
}
for (int j = 0; j < 9; j++) std::cout << buf[8-j];
return 0;
}
得到密碼 p455w0rd
。
其他題目均未解出
尾聲
3500,終局 #38,校內榜一(前輩們都沒怎麼打,讓我們萌新玩玩?)
首尾呼應:我好菜啊.jpg 電子競技菜是原罪.jpg