GKCTF X DASCTF應急挑戰杯-Maple_root-Writeup
參賽隊員:
b4tteRy, x0r, f1oat
最終成績:2285
最終排名:27
總結
經過最近幾次類線下的演練,感覺慢慢對CTF有點上手了,這次終於不再爆0了,繼續努力
MISC
簽到
wireshark打開可知是shell流量,命令結果編碼為hex+base64。觀察前面幾條whoami/ls
等命令輸出可知每行輸出都是倒序輸出。
故將cat /f14g|base64
的結果每行倒序拼接解碼后得到flag的編輯記錄,去除雙寫得到flag。
你知道apng嗎
將apng轉換為gif后查看,發現部分關鍵幀內有二維碼。
掃描結果順序拼接得到flag。
銀杏島の奇妙冒險
FireFox Forensics
下載下來解壓以后有一個json文件和一個sql存儲的db數據庫文件,查看db數據庫內容是加密的,又根據題目提示本題內容屬於登錄信息相關,應該是FireFox瀏覽器所存儲的登錄信息,在Github上已有相關的解密腳本,直接下載以后將題目給出的兩個文件放入相同目錄,使用python3 firepwd.py
即可成功解密得到flag
excel騷操作
打開看到一行字,根據提示flag隱寫在表格中。
依次查看單元格/解壓查看數據可發現部分單元格值為1,查看單元格格式可發現格式為;;;,改變格式后正常顯示出數字。
設置條件格式,使得所有值為1的單元格黑色填充,並拉伸所有數字范圍內單元格至正方形,得到黑色單元格畫成的漢信碼。
使用中國編碼app掃描得到flag。
Reverse
QQQQT
下載后使用PEID掃描是WIN32程序,拖入IDA32分析可看出程序顯然是由Qt語言所編寫,題目名稱也印證了這一點,一開始在IDA的WinMain窗口中多次依照邏輯查找無果,之后又在OD中嘗試進行動態調試,在分析出的字符串當中找到了flag相關的關鍵詞已經其上下的文本地址
然后在IDA中根據以上地址找到這些字符串所在的位置,可以得到如下函數
int __thiscall sub_4012F0(_DWORD *this)
{
int v1; // edi
_BYTE *v2; // esi
const char *v3; // edx
_BYTE *v4; // esi
int v5; // ecx
int v6; // eax
int v7; // ecx
int v8; // edx
int v9; // edi
int v10; // esi
_BYTE *v11; // ecx
unsigned int v12; // ecx
int v14; // [esp-8h] [ebp-A8h]
char v16[4]; // [esp+10h] [ebp-90h] BYREF
char v17[4]; // [esp+14h] [ebp-8Ch] BYREF
_BYTE *v18; // [esp+18h] [ebp-88h]
const char *v19; // [esp+1Ch] [ebp-84h]
int v20; // [esp+20h] [ebp-80h]
int v21; // [esp+24h] [ebp-7Ch] BYREF
_BYTE *v22; // [esp+28h] [ebp-78h] BYREF
char v23[60]; // [esp+2Ch] [ebp-74h] BYREF
__int128 v24[2]; // [esp+68h] [ebp-38h] BYREF
__int64 v25; // [esp+88h] [ebp-18h]
int v26; // [esp+9Ch] [ebp-4h]
MEMORY[0x5FF6](*(_DWORD *)(this[6] + 4), v16);
v26 = 0;
MEMORY[0x7C7C](v16, v17);
LOBYTE(v26) = 1;
v19 = (const char *)MEMORY[0x7C48](v17);
v24[0] = 0i64;
v24[1] = 0i64;
v25 = 0i64;
strcpy(v23, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
v21 = 138 * strlen(v19) / 0x64;
v14 = v21 + 1;
v1 = 0;
v22 = (_BYTE *)MEMORY[0x8114](v21 + 1);
v2 = v22;
sub_402C08(v22, 0, v14);
v3 = v19;
v20 = (int)(v19 + 1);
if ( strlen(v19) )
{
v4 = &v2[v21];
v18 = v4;
while ( 1 )
{
v20 = ((char)*v4 << 8) + v3[v1];
v5 = v20 / 58;
*v4 = v20 % 58;
if ( v5 )
{
do
{
v6 = (char)*--v4;
v7 = (v6 << 8) + v5;
v20 = v7 / 58;
*v4 = v7 % 58;
v5 = v20;
}
while ( v20 );
v4 = v18;
}
if ( ++v1 >= strlen(v19) )
break;
v3 = v19;
}
v2 = v22;
}
v8 = 0;
if ( !*v2 )
{
do
++v8;
while ( !v2[v8] );
}
v9 = v21;
if ( v8 <= v21 )
{
v10 = v2 - (_BYTE *)v24;
do
{
v11 = (char *)v24 + v8++;
*v11 = v23[(char)v11[v10]];
}
while ( v8 <= v9 );
}
if ( !MEMORY[0x7C1A](v24, "56fkoP8KhwCf3v7CEz") )
{
if ( v19 )
v12 = strlen(v19);
else
v12 = -1;
v22 = (_BYTE *)MEMORY[0x7CCC](v19, v12);
LOBYTE(v26) = 2;
v21 = MEMORY[0x7CCC]("flag", 4);
LOBYTE(v26) = 3;
MEMORY[0x6124](this, &v21, &v22, 1024, 0);
MEMORY[0x7C66](&v21);
MEMORY[0x7C66](&v22);
}
MEMORY[0x7C30](v17);
return MEMORY[0x7C66]();
}
由上方字符串123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
推測為Base58編碼,將字符串56fkoP8KhwCf3v7CEz
以Base58解碼后嘗試提交即為flag
Crash
打開發現本程序是用Golang編寫的,因此使用IDA7.6打開即可對應大部分的字符集,打開main_main看第18行為
if ( v1[1] == 43LL && *(_DWORD *)v0 == 1413696327 && *(_WORD *)(v0 + 4) == 31558 && *(_BYTE *)(v0 + 42) == 125 )
其中,各個等值式分別判定了TCKG
(內存地址中倒序存儲字符串),{F
,}
,因此推斷這里應該就是在進行flag的判定,接着進入main_check函數
void __golang main_check(__int64 a1, unsigned __int64 a2)
{
__int64 v2; // [rsp+10h] [rbp-68h]
__int64 v3; // [rsp+10h] [rbp-68h]
__int64 v4; // [rsp+10h] [rbp-68h]
__int64 v5; // [rsp+18h] [rbp-60h]
__int64 v6; // [rsp+18h] [rbp-60h]
__int64 v7; // [rsp+18h] [rbp-60h]
__int64 v8; // [rsp+18h] [rbp-60h]
__int64 v9; // [rsp+18h] [rbp-60h]
__int64 v10; // [rsp+18h] [rbp-60h]
__int64 v11; // [rsp+20h] [rbp-58h]
__int64 v12; // [rsp+20h] [rbp-58h]
__int64 v13; // [rsp+20h] [rbp-58h]
__int64 v14; // [rsp+20h] [rbp-58h]
__int64 v15; // [rsp+20h] [rbp-58h]
__int64 v16; // [rsp+20h] [rbp-58h]
__int64 v17; // [rsp+28h] [rbp-50h]
__int64 v18; // [rsp+28h] [rbp-50h]
char v19[32]; // [rsp+30h] [rbp-48h] BYREF
char v20[32]; // [rsp+50h] [rbp-28h] BYREF
if ( a2 < 0x1E )
runtime_panicSliceAlen();
v2 = main_encrypto(a1 + 6, 24LL);
if ( v5 == 44 )
{
v11 = runtime_memequal(v2, (__int64)"o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA=", 44LL, 44);
if ( (_BYTE)v5 )
{
if ( a2 < 0x22 )
runtime_panicSliceAlen();
v17 = runtime_stringtoslicebyte((__int64)v19, a1 + 30, 4LL, v5, v11);
Encrypt_HashHex2(v6, v12, v17, v6, v12);
if ( v13 == 64 )
{
v14 = runtime_memequal(
v7,
(__int64)"6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74",
64LL,
v7);
if ( (_BYTE)v7 )
{
if ( a2 < 0x26 )
runtime_panicSliceAlen();
v18 = runtime_stringtoslicebyte((__int64)v20, a1 + 34, 4LL, v7, v14);
Encrypt_HashHex5(v8, v15, v18, v8, v15);
if ( v16 == 128 )
{
runtime_memequal(
v9,
(__int64)"6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9"
"b757caae1ecce804582ae78f87fa3c9",
128LL,
v9);
if ( (_BYTE)v9 )
{
if ( a2 < 0x2A )
runtime_panicSliceAlen();
main_hash(a1 + 38, 4LL, v3, v9);
if ( v10 == 32 )
runtime_memequal(v4, (__int64)"ff6e2fd78aca4736037258f0ede4ecf0", 32LL, 32);
}
}
}
}
}
}
}
可以看出,總共分為了若干段,第一段有六個字符,且使用了DES加密(可直接爆破)第二段是使用了sha256加密,第三段是使用了sha512加密,最后一段則使用了md5加密,以上若干加密段皆可根據前面所截取提交內容內的長度推斷該段加密前明文的長度,因此除第一個DES爆破解密已有相關網站外,其余皆寫相同腳本爆破即可
第一段DES加密可以從encoding_json_Unmarshal
內找到key和iv
"key": "WelcomeToTheGKCTF2021XXX",
"iv": "1Ssecret"
接着發現此處key共有24byte,因此推測為3des,因此進行相應的爆破即可得到第一段flag,后面幾段的解題腳本如下:
sha256 -> 4位
import hashlib
import string
import itertools
dateset = string.ascii_lowercase + string.digits
res = "6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74"
def generate_strings(length=4):
chars = string.ascii_lowercase + string.digits
for item in itertools.product(chars, repeat=length):
tmp = "".join(item)
aa = hashlib.sha256(tmp.encode('utf-8')).hexdigest()
if aa.hexdigest() == res:
print(tmp)
exit(0)
generate_strings()
sha512 -> 4位
import hashlib
import string
import itertools
dateset = string.ascii_lowercase + string.digits
res = "6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9b757caae1ecce804582ae78f87fa3c9"
def generate_strings(length=4):
chars = string.ascii_lowercase + string.digits
for item in itertools.product(chars, repeat=length):
tmp = "".join(item)
aa = hashlib.sha512(tmp.encode('utf-8')).hexdigest()
if aa.hexdigest() == res:
print(tmp)
exit(0)
generate_strings()
md5 -> 4位
import hashlib
import string
import itertools
dateset = string.ascii_lowercase + string.digits
flag = "ff6e2fd78aca4736037258f0ede4ecf0"
def generate_strings(length=4):
chars = string.ascii_lowercase + string.digits
for item in itertools.product(chars, repeat=length):
md5 = hashlib.md5()
tmp = "".join(item)
md5.update(tmp.encode('utf-8'))
if md5.hexdigest() == flag:
print(tmp)
exit(0)
將以上爆破出來的值按照順序連在一起即為flag
Web
easycms
題目提示五位弱密碼,嘗試admin/12345后登陸成功。
嘗試更改主題相關模板代碼提示需要創建/system/tmp/xxxx.txt
(貌似是動態的四個字母)。
在素材庫上傳文件可觀察到路徑是文件名直接拼接來的,故可利用目錄穿越創建上述要求創建的文件。再向模板內插入shell后讀flag即可。