---
# System prepended metadata

title: AIS3 pre-exam Writeup(2021)

---

AIS3 pre-exam Writeup(2021)
===
排名:152
Scoreboard:https://drive.google.com/file/d/1v-5ag_sQdVHTxWPLj-7hM-akwcJ-prdq/view?usp=sharing

Welcome
---
#### Cat Slayer ᶠᵃᵏᵉ | Nekogoroshi
手動爆破
    
    pwd = 2025830455298
    flag:AIS3{H1n4m1z4w4_Sh0k0gun}

Misc
---
#### Microcheese
(這題是結束後解出來的)
```python=
        if choice == '0':
            pile = int(input('which pile do you choose? '))
            count = int(input('how many stones do you remove? '))
            if not game.make_move(pile, count):
                print_error('that is not a valid move!')
                continue

        elif choice == '1':
            game_str = game.save()
            digest = hash.hexdigest(game_str.encode())
            print('you game has been saved! here is your saved game:')
            print(game_str + ':' + digest)
            return

        elif choice == '2':
            break

```
可以發現選擇0,1,2以外的選項就可以只讓電腦拿走石頭
等到最後我們再把最後一顆石頭拿走就可以拿到flag了
不知道為什麼，我在賽中進到遊戲時第一步選3會出現
```
oops i died
```
然後程式就停止了
賽後發現要先正常的走一步(選0) 之後選3就可以正常跳過了
![](https://i.imgur.com/zjKmAg0.png)
可以發現 程式印出了
```
 you removed 1 stones from pile 0
```
但pile 0的石頭數量卻沒有減少
反覆操作 當只剩一堆有石頭時 出手把石頭拿完就贏了
![](https://i.imgur.com/ilVhvyB.png)
由於印出flag的函數是作者寫的 因此在本機無法印出flag

#### blind
(結束後看writeup解出)
```c=
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>

int syscall_black_list[] = {};

void make_a_syscall()
{
    unsigned long long rax, rdi, rsi, rdx;
    scanf("%llu %llu %llu %llu", &rax, &rdi, &rsi, &rdx);
    syscall(rax, rdi, rsi, rdx);
}

int main()
{
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stdout, 0, 2, 0);
    puts("You can call a system call, then I will open the flag for you.");
    puts("Input: [rax] [rdi] [rsi] [rdx]");
    close(1);
    make_a_syscall();
    int fd = open("flag", O_RDONLY);
    char flag[0x100];
    size_t flag_len = read(fd, flag, 0xff);
    write(1, flag, flag_len);
    return 0;
}                                                                                                                                                                                                                                       
```
可以看到他用close(1); 把stdout關掉 導致flag印不出來
只要想辦法把stdout改成1就可以拿到flag
可以透過dup2(2,1)把stderr的fd(File Descriptor)複製給stdout
讓它的值變成1就可以拿到flag
對照syscall table可知輸入33 2 1 0可以拿到flag

參考資料
https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md
https://stackoverflow.com/a/58890557

Crypto
---
#### microchip


    明文和密文的長度一樣
    每4個字一組 彼此互不影響
    又知key[i]<96
    flag前四位是AIS3
    所以可以算key
    然後逆著解回去就好了
    程式碼如下
```python=
cipher = "&sJ=`A*;HZdoD>'i&sJ=D-i#U>fYuy'yuyfyuG)<"
key = [ 69 , 42 , 87, 10 ]
token=0
idx=0
flag=""
for i in cipher:
    token=int(token)
    idx=int(idx)
    token = idx % 4
    i = ord( i ) - 32
    i=int(i)
    if( i - key[token] < 0 ):
        i+=96
    i-=key[token]
    i += 32
    flag = flag + chr(i)
    idx += 1
print(flag)
```
flag: AIS3{w31c0me_t0_AIS3_cryptoO0O0o0Ooo0}
    
Reverse
---
#### piano
  反組譯piano.dll後拿到(出來的程式碼大約200多行 這邊只列出關鍵的部分)
  ```

	private bool isValid()
	{
		List<int> list = new List<int>
		{
			14, 17, 20, 21, 22, 21, 19, 18, 12, 6,
			11, 16, 15, 14
		};
		List<int> list2 = new List<int>
		{
			0, -3, 0, -1, 0, 1, 1, 0, 6, 0,
			-5, 0, 1, 0
		};
		for (int i = 0; i < 14; i++)
		{
			if (notes[i] + notes[(i + 1) % 14] != list[i])
			{
				return false;
			}
			if (notes[i] - notes[(i + 1) % 14] != list2[i])
			{
				return false;
			}
		}
		return true;
	}

	
  ```
 解個方程式後會拿到幾個數字 打開piano.exe後用正確的順序彈就過了   
flag: AIS3{7wink1e_tw1nkl3_l1ttl3_574r_1n_C_5h4rp}

#### 🐰 Peekora 🥒
結束後看writeup解出
用
```
python3 -m pickletools -a flag_checker.pkl 
```
可以disassemble題目給的.pkl檔案

MARK 做標記
GET  把東西push到stack上
REDUCE 很像是搞成一個function
PUT 從stack上拿東西 但不會pop
然後硬讀
```
        MARK                                      Push markobject onto the stack.
  708: g        GET        1                      Read an object from the memo and push it on the stack.
  711: (        MARK                              Push markobject onto the stack.
  712: g            GET        4                  Read an object from the memo and push it on the stack.
  715: S            STRING     '__eq__'           Push a Python string object.
  725: t            TUPLE      (MARK at 711)      Build a tuple out of the topmost stack slice, after markobject.
  726: R        REDUCE                            Push an object built from a callable and an argument tuple.
  727: (        MARK                              Push markobject onto the stack.
  728: g            GET        1                  Read an object from the memo and push it on the stack.
  731: (            MARK                          Push markobject onto the stack.
  732: g                GET        0              Read an object from the memo and push it on the stack.
  735: S                STRING     '__getitem__'  Push a Python string object.
  750: t                TUPLE      (MARK at 731)  Build a tuple out of the topmost stack slice, after markobject.
  751: R            REDUCE                        Push an object built from a callable and an argument tuple.
  752: (            MARK                          Push markobject onto the stack.
  753: I                INT        13             Push an integer or bool.
  757: t                TUPLE      (MARK at 752)  Build a tuple out of the topmost stack slice, after markobject.
  758: R            REDUCE                        Push an object built from a callable and an argument tuple.
  759: t            TUPLE      (MARK at 727)      Build a tuple out of the topmost stack slice, after markobject.
  760: R        REDUCE                            Push an object built from a callable and an argument tuple.
  761: t        TUPLE      (MARK at 707)          Build a tuple out of the topmost stack slice, after markobject.
  762: R    REDUCE    
 //memo4 == imput[1] == input[13]
```

```
        MARK                                      Push markobject onto the stack.
  523: g        GET        1                      Read an object from the memo and push it on the stack.
  526: (        MARK                              Push markobject onto the stack.
  527: g            GET        1                  Read an object from the memo and push it on the stack.
  530: (            MARK                          Push markobject onto the stack.
  531: g                GET        0              Read an object from the memo and push it on the stack.
  534: S                STRING     '__getitem__'  Push a Python string object.
  549: t                TUPLE      (MARK at 530)  Build a tuple out of the topmost stack slice, after markobject.
  550: R            REDUCE                        Push an object built from a callable and an argument tuple.
  551: (            MARK                          Push markobject onto the stack.
  552: I                INT        5              Push an integer or bool.
  555: t                TUPLE      (MARK at 551)  Build a tuple out of the topmost stack slice, after markobject.
  556: R            REDUCE                        Push an object built from a callable and an argument tuple.
  557: S            STRING     '__eq__'           Push a Python string object.
  567: t            TUPLE      (MARK at 526)      Build a tuple out of the topmost stack slice, after markobject.
  568: R        REDUCE                            Push an object built from a callable and an argument tuple.
  569: (        MARK                              Push markobject onto the stack.
  570: V            UNICODE    'd'                Push a Python Unicode string object.
  573: t            TUPLE      (MARK at 569)      Build a tuple out of the topmost stack slice, after markobject.
  574: R        REDUCE                            Push an object built from a callable and an argument tuple.
  575: t        TUPLE      (MARK at 522)          Build a tuple out of the topmost stack slice, after markobject.
  576: R    REDUCE                                Push an object built from a callable and an argument tuple.
  577: (    MARK                                  Push markobject onto the stack.
  578: t        TUPLE      (MARK at 577)          Build a tuple out of the topmost stack slice, after markobject.
  579: R    REDUCE        
//input[5] == 'd'
```
讀完得到flag
AIS3{dAmwjzphIj}


